; ; PROGRAM: PATH ; VERSION: 3.0 ; AUTHOR: RICHARD CONN ; DATE: 12 Apr 84 ; PREVIOUS VERSIONS: NONE ; DERIVATION: PATH, Version 1.0 (for ZCPR2) of 12 Jan 83 ; VERS EQU 30 z3env SET 0f400h ; ; PATH allows the user to do two things -- display the current path ; and set a new path. Named directories may be used in the definition of ; the new path. ; ; PATH is invoked by the following forms: ; PATH <-- Display Path ; PATH path-expression <-- Set Path ; PATH // <-- Print Help ; ; ; CP/M Constants ; cpm equ 0 ;base fcb equ cpm+5ch tbuff equ cpm+80h cr equ 0dh lf equ 0ah ; ; SYSLIB Routines ; ext z3init,eprint,codend,dirtdu,dutdir ext cout,epstr,pafdc,retud ext getpath,getmdisk,getmuser,getwhl ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Env and the VLIB Env lxi h,0 ;save stack ptr dad sp shld strtstack ; save ptr to original stack lxi h,tbuff+1 ; pt to command line input shld cmdline ; save ptr to command line call retud ; get current disk and user ; ; Print Banner ; call eprint db 'PATH Version ' db vers/10+'0','.',(vers mod 10)+'0',0 ; ; Check for Help ; lda fcb+1 ; get first char cpi '/' ; help? jnz start1 call eprint db cr,lf,'Syntax:' db cr,lf,' PATH <-- Display Path' db cr,lf,' PATH expr <-- Set Path' db 0 ret ; ; Check for Error and Continue if not ; start1: call getpath ; external path available? mov a,h ; HL=0 if none ora l jnz start2 call eprint db ' - Abort: No Path',0 ret start2: call getwhl ; check for wheel jnz start3 call eprint db ' - Abort: No Wheel',0 ret start3: lhld cmdline ; check command line for text call sblank ; skip to non-blank shld cmdline ; set ptr to next element ora a ; EOL=display function jz pdisp call codend ; set temporary path shld pathptr ; point to it ; ; **** Set New Path **** ; CMDLINE pts to next element ; pbuild: lhld cmdline ; pt to next element call sblank ; skip to non-blank mov a,m ; get first char of next element ora a ; EOL? jz pbdone ; done if so, store path and display shld token ; save ptr to first byte mov a,m ; get first char cpi '$' ; is it current? jz pbdu ; DU: form sui 'A' ; convert to number jc pbdir ; DIR: form mov b,a ; save number call getmdisk ; get max disk number mov c,a mov a,b cmp c ; in range? jnc pbdir ; DIR: form if not inx h ; pt to next char -- may be DU or DIR mov a,m ; get next part of element cpi '$' ; current? jz pbdu ; is a DU: form digtst: cpi ':' ; colon ends it jz pbdu ; is a DU: form cpi ' ' ; space ends it jz pbdu ora a ; EOL ends it jz pbdu cpi '0' ; must be a digit jc pbdir ; DIR: form if not in range cpi '9'+1 jnc pbdir inx h ; pt to next mov a,m ; get it jmp digtst ; ; It is a DU: form ; pbdu: lhld pathptr ; pt to path entry xchg ; ... in DE lhld token ; pt to token mov a,m ; current? cpi '$' jz pbdu1 sui 'A'-1 ; convert to number from 1 to n pbdu1: stax d ; save disk element inx h ; pt to next inx d mov a,m ; current user? inx h ; pt to after user in case of match to current cpi '$' ; current? jz pbdu2 dcx h ; pt to first digit push d ; save ptr to path call eval10 ; convert to number in C jc rangerr call getmuser ; check for max user inr a mov b,a ; place max in B mov a,c ; value in A cmp b jnc rangerr pop d ; get ptr to path pbdu2: stax d ; store user number inx d mov a,m ; ending with colon? cpi ':' jnz pbdu3 inx h ; skip over colon pbdu3: shld cmdline ; save ptr to next command line entry xchg shld pathptr ; save ptr to next path entry jmp pbuild ; continue processing ; ; Build DIR: form ; pbdir: lhld token ; pt to name call dirtdu ; convert to DU in BC jnz gotud ; process new DU ; ; Entry not found ; rangerr: call eprint db cr,lf,'Bad Expression at ',0 lhld token ; print string starting at token call epstr lhld strtstack ; get original stack sphl ; set stack ptr ret ; ; Got User and Disk -- Store in Path ; gotud: lhld pathptr ; get ptr to path inr b ; disk A = 1 mov m,b ; store disk inx h mov m,c ; store user inx h ; pt to next shld pathptr lhld token ; skip over token gotud1: mov a,m ; skip to space or EOL inx h ; pt to next ora a ; EOL? jz gotud2 cpi ' ' ; space? jnz gotud1 gotud2: dcx h ; pt to EOL or space shld cmdline ; set ptr to next element jmp pbuild ; continue building ; ; Path Building is Done -- CODEND contains new path ; pbdone: lhld pathptr ; store ending zero in path mvi m,0 call getpath ; pt to path xchg ; ... in DE call codend ; copy temp path into external path pcopy: mov a,m ; get disk stax d ; put disk ora a ; end of path? jz pdisp ; done if so and display inx h ; pt to user inx d mov a,m ; get user stax d ; put user inx h ; pt to next disk inx d jmp pcopy ; ; **** Display Path Function **** ; pdisp: call eprint db cr,lf,' Symbolic Form: ',0 call getpath ; pt to external path pdisp1: mov a,m ; get disk ora a ; done? jz adisp cpi '$' ; current? jz pdisp2 adi '@' ; convert to letter pdisp2: call cout ; print disk letter inx h ; pt to user mov a,m ; get user number cpi '$' ; current? jnz pdisp3 call cout ; print current indicator jmp pdisp4 pdisp3: call pafdc ; print user number pdisp4: call colon inx h ; pt to next element mov a,m ; done? ora a ; 0=yes cnz arrow jmp pdisp1 ; ; Print Absolute Path ; adisp: call eprint db cr,lf,' DU Form: ',0 call retud ; get current user/disk call getpath ; pt to path adisp1: mov a,m ; get disk ora a ; done? jz ndisp cpi '$' ; current? jnz adisp2 mov a,b ; get current disk inr a ; adjust to 1 to n adisp2: adi '@' ; convert to letter call cout ; print disk letter inx h ; pt to user mov a,m ; get user cpi '$' ; current? jnz adisp3 mov a,c ; get current user adisp3: call pafdc ; print user call colon inx h ; pt to next mov a,m ; done? ora a cnz arrow jmp adisp1 ; ; Print Named Path ; ndisp: call eprint db cr,lf,' DIR Form: ',0 call getpath ; pt to external path ndisp1: call retud ; get current user and disk in C and B mov a,m ; get disk ora a ; done? rz cpi '$' ; current? jz ndisp2 mov b,a ; disk in B dcr b ; adjust to 0 to n-1 ndisp2: inx h ; pt to user mov a,m ; get it cpi '$' ; current? jz ndisp3 mov c,a ; user in C ndisp3: inx h ; pt to next push h ; save ptr call udscan ; scan dirs for user/disk and print its name pop h ; get ptr call colon mov a,m ; done? ora a cnz arrow jmp ndisp1 ; ; **** Utilities **** ; ; ; Convert Chars pted to by HL to Number in C ; Return with Carry Set if Overflow ; If OK, Value in C and HL pts to character after last digit ; eval10: mvi c,0 ; set value eval1: mov a,m ; get first digit sui '0' ; convert to binary jc evalx ; done with value in C cpi 10 ; range? jnc evalx ; done with value in C mov b,a ; digit in B mov a,c ; multiply by 10 add a ; *2 rc ; error abort add a ; *4 rc add c ; *5 rc add a ; *10 rc add b ; add value rc mov c,a ; value in C inx h ; pt to next jmp eval1 evalx: ora a ; clear carry flag ret ; ; Print Colon ; colon: mvi a,':' ; print colon jmp cout ; ; Print Arrow ; arrow: call eprint db ' --> ',0 ret ; ; Skip to non-blank ; sblank: mov a,m ; get char inx h ; pt to next cpi ' ' ; space? jz sblank dcx h ; pt to non-blank ret ; ; Scan directories for user and disk in C and B ; Print name if found or "Noname" if not ; udscan: call dutdir ; convert to name jz udscan1 ; error return if no name mvi b,8 ; 8 chars max udsprn: mov a,m ; get name char cpi ' ' ; done? rz call cout ; print char inx h ; pt to next dcr b ; count down jnz udsprn ret udscan1: call eprint db 'Noname',0 ret ; ; Buffers ; cmdline: ds 2 ; ptr to next char in command line token: ds 2 ; ptr to current token pathptr: ds 2 ; ptr to next path entry strtstack: ds 2 ; ptr to original stack end