;
; SYSLIB Module Name:  SFNAME
; Author:  Richard Conn
; SYSLIB Version Number:  2.0
; Module Version Number:  1.0
; Module Entry Points:
;	FNAME
; Module External References:
;	CAPS
;
;*
;*  FNAME is a file name scanner.  Pointing to the first character
;*	of a file name specification of the form 'du:filename.typ', where
;*	any part of this specification is optional, this routine fills in
;*	an FCB with zeros, properly initializes the FN and FT (File Name and
;*	File Type) fields if 'filename.typ' or any part thereof is present,
;*	and returns the value of d and u if they are specified (or FFH if they
;*	are not).
;*

;*
;*  EXTERNALS
;*
	EXT	CAPS	; CAPITALIZE ROUTINE

;*
;*  BASIC EQUATES
;*
MAXDISK	EQU	16	; MAX NUMBER OF DISKS
MAXUSER	EQU	31	; MAX USER NUMBER
CPM	EQU	0	; CP/M ENTRY
CR	EQU	0DH
LF	EQU	0AH

;*
;*  MAIN MODULE
;*	ON ENTRY, DE PTS TO FCB TO BE FILLED AND HL PTS TO FIRST BYTE OF
;*		TARGET STRING; FCB IS 36 BYTES LONG
;*	ON EXIT, B=DISK NUMBER (1 FOR A, ETC) AND C=USER NUMBER
;*		HL PTS TO TERMINATING CHAR
;*		A=0 AND Z SET IF ERROR IN DISK OR USER NUMBERS, A=0FFH AND NZ
;*			IF OK
;*
FNAME::
	PUSH	D	; SAVE DE
	MVI	A,0FFH	; SET DEFAULT DISK AND USER
	STA	DISK
	STA	USER
	MVI	B,36	; INIT FCB
	PUSH	D	; SAVE PTR
	XRA	A	; A=0
FNINI:
	STAX	D	; STORE ZERO
	INX	D	; PT TO NEXT
	DCR	B	; COUNT DOWN
	JNZ	FNINI
	POP	D	; GET PTR BACK
;  SCAN FOR COLON IN STRING
	PUSH	H	; SAVE PTR
COLON:
	MOV	A,M	; SCAN FOR COLON OR SPACE
	INX	H	; PT TO NEXT
	CPI	':'	; COLON FOUND?
	JZ	COLON1
	CPI	','	; COMMA FOUND?
	JZ	GETF1
	CPI	' '+1	; DELIM?
	JC	GETF1
	JMP	COLON	; CONTINUE IF NOT END OF LINE
COLON1:
	POP	H	; CLEAR STACK
	MOV	A,M	; SAVE POSSIBLE DRIVE SPEC
	CALL	CAPS	; CAPITALIZE
	CPI	'A'	; DIGIT IF LESS THAN 'A'
	JC	USERCK	; PROCESS USER NUMBER
	SUI	'A'	; CONVERT TO 0-15
	CPI	MAXDISK	; WITHIN BOUNDS?
	JC	SVDISK
ERREXIT:
	XRA	A	; ERROR INDICATOR
	POP	D	; RESTORE DE
	RET

;  LOG IN SPECIFIED DISK
SVDISK:
	INR	A	; ADJUST TO 1 FOR A
	STA	DISK	; SAVE FLAG
	INX	H	; PT TO NEXT CHAR

;  CHECK FOR USER
USERCK:
	MOV	A,M	; GET POSSIBLE USER NUMBER
	CPI	':'	; NO USER NUMBER
	JZ	GETFILE
	CPI	'?'	; ALL USER NUMBERS?
	JNZ	USERC1
	STA	USER	; SET VALUE
	INX	H	; PT TO AFTER
	MOV	A,M	; MUST BE COLON
	CPI	':'
	JZ	GETFILE
	JMP	ERREXIT	; FATAL ERROR IF NOT COLON AFTER ?
USERC1:
	XRA	A	; ZERO USER NUMBER
	MOV	B,A	; B=ACCUMULATOR FOR USER NUMBER
USRLOOP:
	MOV	A,M	; GET DIGIT
	INX	H	; PT TO NEXT
	CPI	':'	; DONE?
	JZ	USRDN
	SUI	'0'	; CONVERT TO BINARY
	JC	ERREXIT	; USER NUMBER ERROR?
	CPI	10
	JNC	ERREXIT
	MOV	C,A	; NEXT DIGIT IN C
	MOV	A,B	; OLD NUMBER IN A
	ADD	A	; *2
	ADD	A	; *4
	ADD	B	; *5
	ADD	A	; *10
	ADD	C	; *10+NEW DIGIT
	MOV	B,A	; RESULT IN B
	JMP	USRLOOP
USRDN:
	MOV	A,B	; GET NEW USER NUMBER
	CPI	MAXUSER+1	; WITHIN RANGE?
	JNC	ERREXIT
	STA	USER	; SAVE IN FLAG
	JMP	GETFILE

;  EXTRACT FILE NAME
GETF1:
	POP	H	; GET PTR TO BYTE
GETFILE:
	MOV	A,M	; PTING TO COLON?
	CPI	':'
	JNZ	GFILE1
	INX	H	; SKIP OVER COLON
GFILE1:
	MOV	A,M	; GET NEXT CHAR
	CPI	','	; DELIM?
	JZ	GFQUES
	CPI	' '+1	; NOT A DELIMITER?
	JNC	GFILE2
GFQUES:
	INX	D	; FILL WITH '?'
	MVI	B,11	; 11 BYTES
	MVI	A,'?'
GFFILL:
	STAX	D	; PUT ?
	INX	D	; PT TO NEXT
	DCR	B	; COUNT DOWN
	JNZ	GFFILL
FNDONE:
	LDA	DISK	; GET DISK NUMBER
	MOV	B,A	; ... IN B
	LDA	USER	; GET USER NUMBER
	MOV	C,A	; ... IN C
	POP	D	; RESTORE REGS
	MVI	A,0FFH	; NO ERROR
	ORA	A	; SET FLAGS
	RET
;  GET FILE NAME FIELDS
GFILE2:
	MVI	B,8	; AT MOST 8 BYTES FOR FN
	CALL	SCANF	; SCAN AND FILL
	MVI	B,3	; AT MOST 3 BYTES FOR FT
	MOV	A,M	; GET DELIMITER
	CPI	'.'	; FN ENDING IN '.'?
	JNZ	GFILE3
	INX	H	; PT TO CHAR AFTER '.'
	CALL	SCANF	; SCAN AND FILL
	JMP	FNDONE	; DONE ... RETURN ARGS
GFILE3:
	CALL	SCANF4	; FILL WITH <SP>
	JMP	FNDONE
;
;  SCANNER ROUTINE
;
SCANF:
	CALL	DELCK	; CHECK FOR DELIMITER
	JZ	SCANF4	; <SP> FILL IF FOUND
	INX	D	; PT TO NEXT BYTE IN FN
	CPI	'*'	; ? FILL?
	JNZ	SCANF1
	MVI	A,'?'	; PLACE '?'
	STAX	D
	JMP	SCANF2
SCANF1:
	STAX	D	; PLACE CHAR
	INX	H	; PT TO NEXT POSITION
SCANF2:
	DCR	B	; COUNT DOWN
	JNZ	SCANF	; CONTINUE LOOP
SCANF3:
	CALL	DELCK	; "B" CHARS OR MORE - SKIP TO DELIMITER
	RZ
	INX	H	; PT TO NEXT
	JMP	SCANF3
SCANF4:
	INX	D	; PT TO NEXT FN OR FT
	MVI	A,' '	; <SP> FILL
	STAX	D
	DCR	B	; COUNT DOWN
	JNZ	SCANF4
	RET

;*
;*  BUFFERS
;*
DISK:	DS	1	; DISK NUMBER
USER:	DS	1	; USER NUMBER

;
;  CHECK CHAR PTED TO BY HL FOR A DELIMITER
;    RET WITH Z FLAG SET IF DELIMITER
;
DELCK:
	MOV	A,M	; GET CHAR
	CALL	CAPS	; CAPITALIZE
	ORA	A	; 0=DELIM
	RZ
	CPI	' '+1	; <SP>+1
	JC	DELCK1	; <SP> OR LESS
	CPI	'='
	RZ
	CPI	5FH	; UNDERSCORE
	RZ
	CPI	'.'
	RZ
	CPI	':'
	RZ
	CPI	';'
	RZ
	CPI	','
	RZ
	CPI	'<'
	RZ
	CPI	'>'
	RET
DELCK1:
	CMP	M	; COMPARE WITH SELF FOR OK
	RET

	END
