;PWD syntax, suggested by Jay Sage ; ; PWD [D:] [mask] [/o...] ; ;This uses 3 optional arguments, identified as follows: ; ; : terminator indicates drive selection list ; ; / means option (P for password is the only one so far) ; ; anything else is a DIR selection mask, of which ; first 8 char are used. ; ; and /o are terminated by whitespace ;AEH additions: ; D: may be followed by whitespace ; whitespace is spc, tab, comma, and CR after last argument ; D may be a list ; the list may include a range like B-F ; a tilde causes subsequent members of the range to be excluded ; arguments may be in any order, and may be repeated if separated ; by whitespace. example: A-P: ~lmno ;------------------------------------------ ;from Z3LIB ext getwhl ;from fs machine module ext stm_x,fsmach ; ext docase ;from PWD module ext sema4,stack,dvector,dohelp ext incvector,negvector ;from BITS module ext arsetbit ;for PWD module public fsinit,inictp,fsm1data,mskbuf public s04arg ;------------------------------------------ include sysdef ;standard ascii, system equates ;these are default values for the sake of independent ;assembly. They are used in the argument list of STAT04, ;and these two characters are replaced by default values ;from the main configuration block in PWD during program ;initialization by the SETUP routine. nchr equ '~' ;the negation character rchr equ '-' ;separator in range expression ;where B-G := BCDEFG ;bit positions in the SEMA4 flag byte ;bit: position: meaning when set: negbit equ 0 ; exclude named drives from display pwbit equ 1 ; display passwords to wheel hpw equ 2 ; don't show pw dirnames to non-wheel ;----------------------------------------- ;routines used by PWD to interpret the case ;tables and to fetch characters for FSMACH ;----------------------------------------- ; this routine interprets a finite state ; table. Other routines may be used ; depending on the structure of the state ; table. This routine interprets a state table ; whose structure is: ; ds 1 ;number of cases ; ds 1 ;selector for default case ; ds n-1 ;n=number of cases. This is a list ; ;of selectors corresponding to cases. ; there are n records, each of the structure: ; ds 2 ;address of an ACTION routine ; ds 2 ;address of the next state table to use ;entry: HL -> state table address ; BC -> entry to this routine ; A = input byte ; (sp+2) = state machine STM_00 address ;exit: DE = address of action routine ; BC = address of next state table ; (sp+2) data is preserved docase:: push hl ; address of nstate data stru ld e,(hl) ; get current state tbl address inc hl ; ..preserving the input byte ld h,(hl) ld l,e ld c,(hl) ;get number of entries inc hl ld b,0 ld (hl),a ;hl->first byte of option list ;the first byte is the 'other' case add hl,bc ;->case argument list push hl ;save for indexing dec hl ;->ast char of option list cpdr ;search for the char in A pop hl ;->argument list add hl,bc add hl,bc add hl,bc add hl,bc ld e,(hl) ;addr of action routine inc hl ld d,(hl) inc hl ld c,(hl) ;addr of next state table entry inc hl ld b,(hl) ;hl is now meaningless pop hl ; -> FSMACH pointer structure at NSTATE ld (hl),c ; store the next state address inc hl ; for use on the next iteration ld (hl),b ret ;bc=next state, de=action ;----------------------------------------- ;routine to initialize input buffer pointer ;and test for an empty command tail inictp:: ld hl,mskbuf ;initialize the ld (mbufpt),hl ;buffer pointer ld (hl),0 ;mark the buffer empty ld hl,tbuf ld c,(hl) ;length of tail inc hl ;->first char (normally space) xor a ;make null and reset cy for the sbc ld b,a add hl,bc ld (hl),a ;install terminating null sbc hl,bc ;recover pointer to cmd tail or c ;see if zero length jr z,setctp ;skip if so inc hl setctp: ld (ctcptr),hl ;save cmd tail pointer ret ;Z=no cmd tail, else something is there ;----------------------------------------- ;routine to get the next byte from the ;command tail. getnext:: ld hl,(ctcptr) ld a,(hl) inc hl ld (ctcptr),hl or a ;test for null ret ;----------------------------------------- ;data structure passed to FSMACH to define ;the tasks performed by the machine. The ;structure is passed by means of its ;address (fsm1data) in the HL register. fsm1data:: dw stat01 ;initial state table dw getnext ;routine to get next byte dw docase ;table interpreter ;----------------------------------------- ;The state tables and routines unique to ;this application of the finite state machine ;------------------------------------------ ;State 1 - initial state, processes a group of ;1 or more characters as a drive list, drive mask, ;or as an option. stat01:: db s01dat-s01arg ;number of cases s01arg: ds 1 ;input selector db null,spc,tab,',' ;selector case list db ':','/' s01dat: dw dolist, stat01 ;add others to the list dw mask_x, 0 ;cr - make dir mask & exit dw mask_i, stat01 ;spc- make dir mask & continue dw mask_i, stat01 ;tab - same as spc dw mask_i, stat01 ;comma - same as spc dw do_drv, stat01 ;colon - set drive bits per the list dw nihil, stat02 ;'/' - ignore and look for option char ;State 2 - process character(s) after '/' stat02:: db s02dat-s02arg ;number of cases s02arg: ds 1 ;input selector db 'P' ;selector case (the only one) s02dat: dw help, 0 ;anything else gets help & abort dw setpw, stat03 ;PW option ;STATE 3 - process character(s) after '/P' stat03:: db s03dat-s03arg ;number of cases s03arg: ds 1 ;input selector db spc,tab,',',null ;selector case list s03dat: dw nihil, stat03 ;ignore all but delimiters dw fsinit, stat01 ;spc - look for another argument dw fsinit, stat01 ;tab - same as space dw fsinit, stat01 ;comma - same as space dw stm_x, 0 ;CR - exit the FS machine ;state 4 - The initial state used by DO_DRV routine ;to process a list of characters ending with ':' stat04:: db s04dat-s04arg ;number of cases s04arg: ds 1 ;input selector db 0,nchr,rchr ;selector case list s04dat: dw setdrive,stat04 ;default case dw fsinix, 0 ;null inits buffer, exits dw negate, stat04 ;negation character dw set1st, stat05 ;range character ;state 5 - used by DO_DRV for the terminal ;character of a range expression (for example, b-g:) ;Any input character is processed. stat05:: db s05dat-s05arg ;number of cases s05arg: ds 1 ;input selector s05dat: dw range, stat04 ;default case ;------------------------------------------ RANGE:: ; evaluates 'x-y' where x is the first and y is ; the last drive letter. (B-G := BCDEFG) ; All drives in the set are enabled for display. ; (or disabled, if negate was used) ; if A >= char =< P then REND = char ; else REND = P ; endif ; Set drive bit for each drive in range ; for j=(rstart...REND), call setdrive(j) ld b,'P' ;default end of range cp 'A' jr c,range0 ;use default if <'A' cp 'P'+1 jr nc,range0 ;.. or if >'P' ld b,a ;else use the char in A range0: ld a,(rstart) ;get first one in range ld c,a ;..in C ld a,b ;end of range sub c ;range end - start inc a ;count the last one! ld b,a ;number of drive letters in range range1: ld a,c push bc call setdrive ;adjust a bit in drive vector pop bc ;recover counter inc c ;next drive letter djnz range1 ret ;------------------------------------------ DO_DRV:: ;process the one or more drives indicated ;by a trailing colon (the current character). ;The list is stored in the list buffer. LD HL,DRPTRS CALL fsmach ;recursive call JP FSINIT ;------------------------------------------ RDLIST:: ;returns the next byte from the ;list buffer. Returns 00 if no more. ld hl,(listps) ld a,(hl) or a ret z inc hl ld (listps),hl RET ;------------------------------------------ ;initialize the list buffer to bin 0 and ;scratch listpointer to start of buffer. ;Set last character pointer to (buffer-1) ;because the pointer is pre-incremented ;as characters are added to the buffer. initlb:: ld hl,listml ld b,(hl) ;buffer size in B ld hl,listbf ;start of buffer ld (listps),hl dec hl ld (listpl),hl ;one less than buffer start inc b zlbuf: ld (hl),0 ;fill buffer with bin zero inc hl djnz zlbuf ret ;------------------------------------------ SETDRIVE:: ; AND the Set or Reset drive bit corresponding ; to the drive letter in A with the bit in ; dvector. DVECTOR already contains bits set ; for those drives for which the names may be ; displayed. This masking process further limits ; the dir names to display. ; if not neg ; Set drive bit for drive in A. ; else ; reset drive bit ; endif ;entry: A = Upper Case ASCII Drive letter sub 'A' ;make binary (0...15) ret c ;do nothing if P ld b,a ;save for bit3 test and 7 ;remove bits 3-7 ld c,a ;save for logic below ld hl,incvector bit negbit,(ix) ;negated? jr z,setdr1 inc hl inc hl ;->negvector setdr1: bit 3,b jr z,setdr2 inc hl ;->high byte setdr2: ld a,c jp arsetbit ;set the bit in the ;use or exclude vector ;------------------------------------------ ;pointers used for the recursive call in DO_DRV drptrs:: dw stat04 dw rdlist dw docase ;------------------------------------------ FSINIX:: ; initialize list buffer, then exit FSMACH ld hl,stm_x ;set up return push hl ;to EXIT routine ;fall through to do initialization ;------------------------------------------ FSINIT:: call initlb ; initialize list buffer to empty res negbit,(ix) ; reset negate flag ld a,'A' ; reset rstart, rend variables to A,P ld (rstart),a ld a,'P' ld (rend),a or a ; ensure CY is reset ret ;------------------------------------------ DOLIST:: ; adds the current character to the list ; in the list buffer. Keeps count of the ; number of items in the list. ld hl,(listpl) inc hl ;pre-incr to next free location ld (hl),a ld (listpl),hl NIHIL:: ret ;NIHIL is a do-nothing function ;used to ignore a byte, and ;continue with the next ;------------------------------------------ SET1ST:: ; (rstart) <- last char in list buffer ld hl,(listps) dec hl ;-> '-' dec hl ;-> range start ;if the '-' was the first character in the buffer, ;then HL-> (listbf-1) which is initialized to 00h. ld a,(hl) or a ;null? ret z ;if so, leave rstart as is: 'A' ld (rstart),a ;else set specified range start ret ;------------------------------------------ NEGATE:: set negbit,(ix) ; set negate flag ret ;------------------------------------------ SETPW:: ;this assumes that the wheel byte is 0ffh ;when set. call getwhl and 1 shl pwbit ; use the PW bit position xor (ix) ; invert PW bit if wheel ld (ix),a ; toggles the PW flag if wheel ret ;------------------------------------------ MASK_X:: ; MASK routine with exit call mask jp stm_x ;------------------------------------------ MASK_I:: ; MASK routine with init call mask jp fsinit ;------------------------------------------ MASK:: ; The contents of the list buffer is a ; directory name mask for initial characters ; of directory names to display. ; Transfers 8 characters from the list buffer ; to the mask buffer. Any trailing nulls ; serve as wildcard characters. ld hl,listbf ld de,(mbufpt) ld bc,8 ldir ld (mbufpt),de or a ;reset cy ret ;------------------------------------------ ;STM_X routine is associated with fsmach. ;If fsmach is external, STM_X is also. ;------------------------------------------ HELP:: ; display help screen, then abort the pgm call dohelp ;returns cy set jp stm_x ;preserves flags ;------------------------------------------ argblen equ 32 ;argument buffer length msklen equ 8 ;size of a dir mask listml:: db argblen ;maximum size of an argument listpl:: ds 2 ;pointer to last list entry listps:: ds 2 ;scratch pointer for list processing listiv:: ds 1 ;initial value of 'last char' listbf:: ds argblen ;buffer for current argument ctcptr:: ds 2 ;pointer to next Command Tail Character mskbuf:: ds msklen*4 ;storage for 4 dir name masks mbufpt:: dw mskbuf ;pointer to next free loc in mskbuf rstart:: ds 1 ;initial char of a range argument rend:: ds 1 ;final char in a range ;------------------------------------------ end