; Copyright (C) Reston Publishing Company, Inc. 1983 ; #start ParseFileRef ------------------------------------------ ; ; ParseFileRef: parse the (presumed) fileref from the text ; addressed by HL into the FCB addressed by DE. ; ; preserves -- BC, DE ; returns -- HL-->byte after the last one used ; Z-flag true if syntax was ok ; ; Note: leading white space must be skipped before calling this ; routine. Some strange filerefs are passed as ok, like "M:", ; ".", and ".typ", but they are legit. The drivecode is NOT ; validated e.g. "@:" is accepted. Ambiguous filerefs are not ; flagged, "?" may appear (as may "*" which is invalid). Lower ; case characters are converted to uppercase. ;--------------------------------------------------------------- ParseFileRef: push b push d ; xra a stax d ; default drivecode ; inx h mov a,m dcx h cpi ':' ; drivecode? JRNZ ParseFile2 ; (nope) mov a,m sbi 'A'-1 ; convert to A: = 1, etc stax d ; ..and set drivecode inx h inx h ; HL-->after drivecode ; ParseFile2: inx d ; DE-->filename field push d ; ..save that mvi a,AsciiBlank lxi b,8+3 ; length of name, type call FillA ; ..cleared to blanks pop d ; DE-->filename again ; mvi b,8 ; length of max filename call MoveHtoDelim JRNZ ParseFile4 ; bad, name exceeds 8 bytes ; cpi '.' ; filetype to follow? JRZ ParseFile3 ; (looks like it) xra a ; no, not a "." delimiter JMPR ParseFile4 ; blank type field, ok ; ParseFile3: inx h ; step over the dot mvi b,3 ; max length of .typ call MoveHtoDelim ; move it, check delimiter ; ParseFile4: pop d pop b ret ; ; #start MoveHtoDelim ------------------------------------------ ; MoveToDelim: Move text from [HL++] into a fixed-length field ; at [DE++], as in moving a filename from a command to an FCB. ; Moved letters are forced to uppercase. The B register (not ; the BC pair, note) contains the maximum length to move. On ; return, DE has been advanced past the field, HL points to the ; byte after the one last moved, A contains the byte, and the Z ; flag is set if that terminal byte is a delimiter. ; preserves: C ; returns: DE advanced by the entry value of B ; B = 00h ; HL-->the byte after the last one moved ; A = that byte ; Note: if the initial HL byte is a delimiter, no movement will ; be done. Call Delimiter beforehand to verify that there is ; something to be moved. ;--------------------------------------------------------------- MoveHtoDelim: call Delimiter ; load and test [HL] JRZ MoveHtoD2 ; (a delimiter) call UpperCase ; convert lowercase stax d ; stow uppercase nondelimiter inx d inx h DJNZ MoveHtoDelim ; moved all B bytes-worth jmp Delimiter ; A:=next byte, set Z ; MoveHtoD2: ; hit a delimiter inx d ; ..advance DE to field end DJNZ MoveHtoD2 ret ; return Z true, A = delimiter ; ; #include textlib.inc,Delimiter ; #include textlib.inc,UpperCase ; #end MoveHtoDelim ; #include textlib.inc,FillA ; #end ParseFileRef ; #start CmdNumOpt --------------------------------------------- ; ; CmdNumOpt: locate a numeric option (/nn) HL-->text. If one is ; found, return its binary value in DE, Z true, Cy false. If a ; slash appears but not a digit, return Z true, Cy true. And if ; no slash is found, return Z false. ; preserves -- BC ; output -- HL updated past the next "/" and "nn" if any ; DE contains binary integer or 0000h ; Z true if /... appears ; C true if it is /x..., false if /n... ;--------------------------------------------------------------- CmdNumOpt: lxi d,0 ; initialize the numeric value call CmdCharOpt ; find the next "/" delimiter rnz ; (there is none, Z false) call CheckDigit ; is the next byte a digit? JRZ CmdNumOpt2 ; (continue if so) xra a ; no. Z true for "/ found", but stc ; ..Cy true for "not numeric" ret ; return that. CmdNumOpt2: ; HL->one or more digits call DecToBinary ; convert number up to 65535 xra a ; return Z true, Cy false ret ; #include textlib.inc,CheckDigit ; #include arithlib.inc,DecToBinary ; #start CmdCharOpt -------------------------------------------- ; ; CmdCharOpt: locate the next option marker (/x..) in HL-->text. ; If one is found, return Z true, and the following byte "x" in ; the A register. If no / is found, ; preserves -- BC, DE ; output -- HL updated to the "x" or to the terminal null. ; A contains the "x" or A contains null ; Z flag set or not ;--------------------------------------------------------------- CmdCharOpt: call CmdSlash ; find the next "/" rnz ; (there is none, A=00h) inx h ; step over it, mov a,m ; get the following byte ret ; and return it. ; #start CmdSlash ---------------------------------------------- ; ; CmdSlash: scan HL forward over text to a "/" character. Return ; true (Z) if "/" is found, else return false. ; preserves -- BC, DE ; output -- HL advanced to a / or to the terminal null byte ; Z flag set ; Note: this is intended for scanning the command tail, and ; assumes that the text is bounded by a 00h byte. ;--------------------------------------------------------------- CmdSlash: push b mvi b,'/' mvi c,0 call ScanForBC ; look for / or null, whichever cmp b ; set Z flag for / found pop b ret ; #start ScanForBC --------------------------------------------- ; ; ScanForBC: HL-->text, B and C contain alternative delimiters. ; Scan HL ahead until it addresses a byte that matches B or C. ; preserves -- BC, DE ; returns -- HL advanced, A = byte found. ;-------------------------------------------------------------- ScanForBC: mov a,m cmp b rz cmp c rz inx h JMPR ScanForBC ; #end ScanForBC ; #end CmdSlash ; #end CmdCharOpt ; #end CmdNumOpt ,m cmp b rz