;routine to perform parse of [DU/DIR:]FN[.FT] ;date: 19 Oct 88 ;author: A.E. Hawley ;version 1.2 previous: v 1.1, 22.02.88 (for ZMACLNK) ;v 1.2 configured for ZMLIB ; 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 ;----------------------------------------- ;CALL WITH: ; HL -> Token to be parsed as Z3 filespec ; DE -> FCB drive byte ; B = Default Drive, (A...P = 1...16) ; C = Default User, 0...31 ;RETURN WITH: ; HL -> Delimiter which terminated the parse ; DE is preserved ; BC = D/U, with defaults replaced by explicit D or U ; FCB drive byte, FN, FT, map fields initialized ; FCB-1 = 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 bc,(defdu) ; get the default drive/user 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 dec hl ld (hl),c ld hl,15 add hl,de ;->error flag cp (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 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 gotit: pop de ; Get FCB pointer back push de ;clear FN field after du/dir scan use inc de ;12/04/87 call ifcb pop de ld hl,15 add hl,de ; point to RC byte of the FCB ld (hl),a ; 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 jr setdu ; ..and go store it. ;----------------------------------------- direrr: ; Error exit for dirscn, duscan duerr: xor a ; Return NZ to show failure dec a 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. duscn: ex de,hl ; Switch FCB pointer to HL inc hl ; Point to first byte of file name in FCB ld bc,(tempusr) ; Preset C to current user, B to current drive 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 ' ' jr z,duscn3 ; 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 b,h ; DU value is now in BC duscn3: ;test against system logical limits for DU ld a,16 ;highest possible drive cp b jr c,duerr ld a,31 ;highest possible user # cp c jr c,duerr setdu: ld (tempusr),bc xor a ; Set Z to flag success ret ;----------------------------------------- tempusr: ;temporary local values db 0 tempdr: db 0 end