; PARSDS.MAC ; ; Version 1.3 -- October 8, 1990 -- Gene Pizzetta ; Corrected lingering bug that reported invalid date entry when ; time spec ended in a colon (no minute) and was followed by ; another command line parameter. ; ; Version 1.2 -- September 3, 1990 -- Gene Pizzetta ; Modified from Carson Wilson's ZSPARSDS.Z80 module from ZSLIB 2.1. ; Added ability to use '/' instead of '.' in date specs. Made ; parsing a little more robust in detecting illegal characters in ; date spec. Now finds time spec if preceded by only month and day ; without final delimiter ('mm/dd' instead of 'mm/dd/'). Now requires ; selection of European ('dd/mm/yy') or American ('mm/dd/yy') date ; format via a public configuration byte in an external module. ; ; Version 1.1 -- February 2, 1990 -- Carson Wilson ; Module ZSPARSDS.Z80 from ZSLIB 2.1. Code shortened, thanks to ; suggestions by Howard Goldstein. ; ; Version 1.0 -- January 21, 1990 -- Carson Wilson ; Purpose: Parse command line datespec. public parsds ; EurDat is an external configuration extrn EurDat ; ..byte -- non-zero selects dd/mm/yy, ; ..zero selects mm/dd/yy extrn isbcdd ; ZSLIB extrn eval10, eval16,isdigit ; SYSLIB MACLIB Z80 ; extended Intel mnemonics ; ; PARSDS - Parse command line datespec. ; ; Entry: HL = address of null-terminated datespec (14 characters or less). ; DE = address of memory buffer (5 bytes), may be initialized with ; default datespec. ; ; Exit: Zero flag set (Z) if memory buffer at DE contains BCD date/time: ; A = 0 if no wildcards or illegal characters encountered. ; A = '*' (2Ah) if wildcards encountered. ; A = character, if illegal character encountered in datespec. ; Zero flag reset (NZ) and A = FFh if entry or parsed datespec was ; invalid (out of range). ; ; Uses: AF. ; ; Notes: If EurDat is non-zero, the command line datespec takes the ; following forms: ; {dd{.mm{.yy{ hh{:mm}}}}} - real time ; or ; {dd{.mm{.yy{ +nnnn}}}} - relative time ; ; If EurDat is zero, the command line datespec takes the ; following forms: ; {mm{/dd{/yy{ hh{:mm}}}}} - real time ; or ; {mm{/dd{/yy{ +nnnn}}}} - relative time ; ; All items in braces are optional. Each date or time item may ; be two ASCII digits or less. If no digits are entered, the ; pre-initialized entry buffer values are checked for validity and ; returned. For example, if '//yy' or '..yy' are entered, only ; the year byte in the entry buffer will be changed. Wildcards ; ("*", "?", or "??") are also allowed. If wildcards are detected, ; they are stored as ASCII "*" (2Ah) and A = 2Ah on return. Your ; application can handle wildcards as you see fit. ; PARSDS: push b push h push d mov b,d mov c,e inx b ; BC --> storage + 1 (month) lda EurDat ora a jrz Skip1 inx b Skip1: dcx h ; prepare for GetNxt ; ; Test month (or day if EurDat) ; call GetNxt ; get next datespec character or abort cpi '.' ; got character, use default month? jrz TestDy ; (yes) cpi '/' jrz TestDy call TstWld ; no, test for wild month jrz TstMon ; (yes) call isdigit ; digit? jnz ErExit ; (no) call eval16 ; must be day spec. SYSLIB evaluate ; ..ASCII hex to binary & pt. HL to next TstMon: stax b ; save value or '*' mov a,m ; get next cpi '.' ; day spec? jrz TestDy cpi '/' jnz Exit ; no, done ; TestDy: lda EurDat ora a jrz Skip2 dcx b jr Skip3 Skip2: inx b ; point to day Skip3: call GetNxt ; get/abort cpi '.' ; got character, use default day? jrz TestYr ; (yes) cpi '/' jrz TestYr call TstWld ; no, wild day? jrz TestD1 ; (yes) call isdigit ; digit? jnz ErExit ; (no) call eval16 ; evaluate day TestD1: stax b ; save value or '*' mov a,m cpi ' ' jrz TestH0 cpi '.' ; got year? jrz TestYr cpi '/' jrnz Exit ; (no, check time) ; TestYr: dcx b ; point to year lda EurDat ora a jrnz Skip4 dcx b Skip4: call GetNxt ; get/abort cpi ' ' ; use default year? jrz TestHr ; (yes) call TstWld ; no, wild year? jrz TestY1 ; (yes) call isdigit ; digit? jrnz ErExit ; (no) call eval16 ; evaluate year TestY1: stax b ; save value or '*' mov a,m cpi ' ' ; got hour? jrnz Exit ; (no, done) ; TestHr: inx b ; point to hour inx b TestH0: inx b TestH1: call GetNxt ; get next command character cpi ' ' ; skip extra spaces jrz TestH1 cpi '+' ; relative time? jrnz TestH2 ; (no) inx h ; point to relative time spec call eval10 ; get +nnnn value to DE setb 7,d ; flag as relative mov a,d stax b ; store value mov a,e inx b stax b ; store value jr Exit ; done with parse ; TestH2: cpi ':' ; use default hour? jrz TestMn ; (yes) call TstWld ; no, wild hour? jrz TestH3 ; (yes) call isdigit ; digit? jrnz Exit ; (no, we must be through) call eval16 ; get hour TestH3: stax b ; save value or '*' mov a,m cpi ':' ; got minute? jrnz Exit ; (no, done) ; TestMn: inx b ; point to minute call GetNxt ; minute or wildcard cpi ' ' jrz Exit call TstWld ; wild minute? jrz TestM1 ; (yes) call isdigit ; digit? jrnz ErExit ; (no) call eval16 ; evaluate minute TestM1: stax b ; save value or '*' ; Exit: pop d ; point to stored date xchg ; check value at HL call isbcdd xchg ; restore DE pop h pop b ret ; return (Z) if date OK. ; ErExit: pop d pop h pop b ret ; ; Subroutines . . . ; ; GetNxt -- get next datespec character ; Entry: HL = address of next datespec position - 1 ; Exit: If null terminator found, quit ; Else: HL incremented ; A = character at HL ; GetNxt: inx h ; next input mov a,m ora a ; done? rnz ; (no) pop d ; yes, remove return address jr Exit ; ..and exit parse ; ; TstWld -- test for wildcard character ("*" or "?") at HL ; Entry: A = character at HL ; BC = address of next datespec storage ; Exit: Zero flag set (Z) if wildcard character found ; A = "*" ; HL = address of next non-wild character ; Zero flag reset (NZ) if not wildcard character ; Uses: A, HL, if wildcard character found; otherwise none. ; TstWld: cpi '*' jrz TestW1 cpi '?' rnz ; (not wildcard) TestW1: call EatWld ; skip consecutive wildcards xra a ; set (Z) for wildcard found mvi a,'*' ret ; EatWld: inx h ; point HL to next non-matching character cmp m jrz EatWld ret ; end