;routine to perform parse of [DU/DIR:]FN[.FT] ;date: 09/18/91 ;author: A.E. Hawley ;version 1.3 previous: v 1.2, 10/19/88 ;v 1.5 10/25/91 ; added logic to decrement default DRive in SCAN: if it ; is 0ffh. This records the occurrence of a lone ':'. ; Also added error handling after the call to DIRSCN so ; a bogus value is not put into BC! ;v 1.4 09/12/91 ; corrected SCAN to store the error flag! ; corrected main routine to properly test error flag! ; added code in main routine to store User at FCB+13 ;v 1.3 09/08/91 ; Modified DUSCN so that default DU passed in BC ; is not tested for out-of-range values. Such values ; can then be used to test for presence of user ; supplied D or U, and defaults provided separately. ; If BC contains legal values, operation is unchanged. ;v 1.2 10/19/88 ; Modified delimiter list to include '/' ; Default D/U are passed in BC rather than an external. ; Uses ALL 8080 registers, no Z80 special registers PUBLIC dirscn,duscn,fname GLOBAL fill,ifcb,inifcb,mpy16,pkgoff,radbin GLOBAL rten1,sdelm,sksp,ucase ;----------------------------------------- ;entry- HL -> Token to be parsed as Z3 filespec ; DE -> FCB drive byte ; B = Default Drive ; C = Default User ;exit- HL -> Delimiter which terminated the parse ; DE is preserved ; BC = D/U, with defaults replaced by explicit D or U ; (caller is responsible for legality of defaults) ; if BC=-1 on entry, a parsed colon decrements B allowing ; detection of an FS of form ':[FN.FT]' (10/25/91) ; FCB drive byte, FN, FT, map fields initialized ; FCB-1 = FCB+13 = Default or declared User area ; NZ = Error, FCB+15 contains error flag ; Z = no error ; A = number of '?' in fn/ft. (wildcard count) ;----------------------------------------- fname: push de ; Save pointer while initializing ld (tempusr),bc ; Initialize temporary DU call inifcb ; Initialize FCB pop de push de call scan ; parse token into the FCB ;on return, A=number of '?' encountered pop de ;->fcb push hl ; Initialize fcb-1, fcb with bc ld h,d ld l,e ld (hl),b ; Drive dec hl ld (hl),c ; User ld hl,13 add hl,de ;-> Z3 User byte ld (hl),c inc hl inc hl ;->error flag inc (hl) dec (hl) ;returns Z if no errors pop hl ;->next char after token ret ;return NZ if bad du or wildcards ;----------------------------------------- ; This routine processes a token pointed to by HL. It attempts ; to interpret the token according to the form [DU:|DIR:]NAME.TYP and places ; the corresponding values into the FCB pointed to by DE. ; On entry, HL->token, DE->target fcb, BC=current DU (1..16,0..32) ; On exit, HL points to the delimiter encountered at the end of the token. ; The Z flag is set if a wild card was detected in the token, and A=? count. ; The drive byte is initialized, and the S1 byte contains the user number. ; BC contains the Drive/User. ; ERROR conditions: on a bad directory reference, the RC byte in the FCB ; will be set to NZ. (usually 0FFh) scan: call scanf8 ; Extract possible file name cp ':' ; Was terminating character a colon? jr nz,scant ; If not, go on to extract file type inc hl ; Point to character after colon ; Code for resolving directory specifications returns ; with a nonzero value and NZ flag setting ; if the DU/DIR specification cannot be resolved. push hl push de ld bc,(tempusr) ; Preset C to current user, B to current drive ld a,b inc a ; -1 default? jr nz,scan1 ; no, don't disturb it dec b ; else make it 0FEh to show colon present ld (tempusr),bc ; and save it scan1: call duscn ;check for DU form jr z,gotit pop de ;not DU, check for DIR pop hl push hl push de call dirscn ;returns nz if bad dir|no ndir|not Z3 jr nz,scan3 ;not found, BC destroyed gotit: ld (tempusr),bc scan3: pop de ; Get FCB pointer back ld b,a ; save error flag push de ;clear FN field after du/dir scan use inc de ;12/04/87 call ifcb ; ret A=B=0, Z pop de ld hl,15 add hl,de ; point to RC byte of the FCB ld (hl),b ; Store error flag there (NZ if error) ld a,(tempdr) ; Set designated drive ld (de),a ; ..into FCB pop hl ; Restore pointer to token string ;..and save error flag pointer call scanf8 ; Scan for file name ; Process the file type specification in the token scant: ld a,(hl) ; Get ending character of file name field ex de,hl ; Switch FCB pointer into HL ld bc,8 ; Offset to file type field add hl,bc ex de,hl ; Switch pointers back cp '.' ; See if file type specified jr nz,scant2 ; If not, skip over file type parsing inc hl ; Point to character after '.' push de ; Save pointer to FCB file type ld b,3 ; Maximum characters in file type call scanfield ; Parse file type into FCB pop de scant2: call scanf3 ; Skip to next delimiter or line end ; Set zero flag if '?' in filename.typ qmcnt equ $+1 ; Pointer for in-the-code modification ld a,0 ; Number of question marks or a ; Set zero flag ld bc,(tempusr) ; return DU in BC ret ;----------------------------------------- ; This routine invokes SCANFIELD for a file name field. It initializes the ; question mark count and preserves the FCB pointer. scanf8: xor a ; Initialize question mark count ld (qmcnt),a push de ; Save pointer to FCB ld b,8 ; Scan up to 8 characters call scanfield pop de ; Restore pointer to FCB ret ; This routine scans a command-line token pointed to by HL for a field whose ; maximum length is given by the contents of the B register. The result is ; placed into the FCB buffer pointed to by DE. Wild cards of '?' and '*' are ; expanded. On exit, HL points to the terminating delimiter. scanfield: call sdelm ; Done if delimiter encountered ret z inc de ; Point to next byte in FCB cp '*' ; Is character a wild card? jr nz,scanf1 ; Continue if not ld a,'?' ; Process '*' by filling with '?'s ld (de),a call qcountinc ; Increment count of question marks jr scanf2 ; Skip so HL pointer left on '*' scanf1: ; Not wildcard character '*' call ucase ; make sure it's upper case ascii ld (de),a ; Store character in FCB inc hl ; Point to next character in command line cp '?' ; Check for question mark (wild) call z,qcountinc ; Increment question mark count scanf2: djnz scanfield ; Decrement char count until limit reached scanf3: call sdelm ; Skip until delimiter ret z ; Zero flag set if delimiter found inc hl ; Pt to next char in command line jr scanf3 ; Subroutine to increment the count of question mark characters in the ; parsed file name. qcountinc: push hl ld hl,qmcnt ; Point to count inc (hl) ; Increment it pop hl ret ;----------------------------------------- ; This code attempts to interpret the token in the FCB pointed to by register ; pair DE as a DIR (named directory) prefix. If it is successful, the drive ; and user values are stored in TEMPDR and TEMPUSR, and the zero flag is set. dirscn: inc de ; Point to first byte of directory form ex de,hl ; Switch pointer to FCB to HL ld de,15h ; Offset to NDR address push hl ; Preserve pointer to FCB call pkgoff ; Get NDR address from ENV into DE pop hl jr z,direrr ; Branch if no NDR implemented dirsc1: ld a,(de) ; Get next character or a ; Zero if end of NDR jr z,direrr inc de ; Point to name of directory inc de push hl ; Save pointer to name we are looking for push de ; Save pointer to NDR entry ld b,8 ; Number of characters to compare dirsc2: ld a,(de) cp (hl) jr nz,dirsc3 ; If no match, quit and go on to next DIR inc hl ; Point to next characters to compare inc de djnz dirsc2 ; Count down dirsc3: pop de ; Restore pointers pop hl jr z,dirsc4 ; Branch if we have good match ex de,hl ; Advance to next entry in NDR ld bc,16 ; 8 bytes for name + 8 bytes for password add hl,bc ex de,hl jr dirsc1 ; Continue comparing dirsc4: ; Match found ex de,hl ; Switch pointer to NDR entry into HL push hl ; ..and save it for later dec hl ; Point to user corresponding to the DIR ld c,(hl) ; Get user value into C dec hl ; Point to drive ld b,(hl) ; Get it into B pop hl ret ;----------------------------------------- direrr: ; Error exit for dirscn, duscan duerr: or 0ffh ; Return NZ to show failure ret ;----------------------------------------- ; This code attempts to interpret the token in the FCB pointed to by register ; pair DE as a DU (drive/user) prefix. If it is successful, the drive and ; user values are stored in TEMPDR and TEMPUSR, and the zero flag is set. ; Entry- BC = default drive, user duscn: ex de,hl ; Switch FCB pointer to HL inc hl ; Point to first byte of file name in FCB ld a,(hl) ; Get possible drive specification sub 'A' ; Otherwise convert to number 0..15 jr c,duscn1 ; If < 0, leave B as is cp 16 jr nc,duscn1 ; If > 15, leave B as is ld b,a ; Otherwise use value given inc hl ; ..and point to next character inc b ; Shift drive to range 1..16 duscn1: ld a,(hl) ; Get possible user specification cp ' ' ret z ; if none present, leave C as is push bc ; Save DU values in BC call rten1 ; Get specified decimal user number into BC pop hl ; Restore values to HL jr c,duerr ; Return NZ if invalid decimal conversion ld a,b ; Get high byte of result or a ; Make sure it is zero ret nz ; If not, return NZ to show bad user number ld a,31 sub c ; if CY set, then number > 31 sbc a,a ; propagate CY into A and set flags ret nz ; NZ = bad user number ld b,h ; DU value is now in BC xor a ; Set Z to flag success ret ;----------------------------------------- tempusr: ;temporary local values db 0 tempdr: db 0 end