home *** CD-ROM | disk | FTP | other *** search
- ; RESOLVE.MAC RESOLVE ZCPR3 COMMAND LINE
- ;
- ;
- ; This utility will resolve a multiple-command line passed to it and place
- ; that command line in the Multiple-Command Line Buffer in memory.
- ; It will resolve references to shell variables, registers, and System
- ; File names. Each of these is signalled by a flag as follows.
- ;
- ; Flag Meaning
- ; ---- -------
- ; %<text> Shell variable name.
- ; $R<n> Register number. (n = 0-31)
- ; $D Current disk letter.
- ; $U Current user number.
- ; $F<n> System File name. (n = 1-4)
- ; $N<n> System File name, chars 1-8 only. (n = 1-4)
- ; $T<n> System File name, extension only. (n = 1-4)
- ; $| Substitute multiple-command separator.
- ;
- ; The QUIET flag is adhered to; the program will not print its sign-on
- ; message or error messages if the QUIET flag is set.
- ;
- ; If there is no room for the command-line generated, the ERROR flag will
- ; be set, and an error message may be printed, depending upon the state
- ; of the QUIET flag. Uninterpretable '$' parameters will also cause the
- ; error flag to be set.
- ;
- ; Author: Dreas Nielsen
- ;
- ; Shell variable file manipulation routines are adapted from Richard Conn's
- ; 'SH.MAC'
- ;
- ; History --
- ; Version Date Comment
- ; ------- ---- -------
- ; 1.0 3/2/86 Up and running -- RDN
- ; 1.1 1/13/87 Fixed error in which a shell variable reference
- ; in the first character of another shell
- ; variable wasn't being expanded. Also changed
- ; so that a single '$', when followed by an
- ; unrecognized flag, is not dropped.
- ; 1.2 2/6/89 Fixed register expansion so it doesn't clobber
- ; nesting depth stored in B.
- ; 1.2 2/11/89 Changed program banner to read "1.2"
- ; 1.3 3/5/89 Changed to allow register references up to
- ; register 32 (0-31).
- ; 1.4 8/03/89 Removed all checking of quiet flag.
- ; Program banner now only displayed when
- ; help requested. Error handler is now
- ; invoked on command line overflow.
- ; Error flag now set on unresolved shell
- ; variables and the leading '%' is no
- ; longer returned in that case. Editing
- ; on register numbers for the $r flag has
- ; been tightened up. Code cleaned up
- ; somewhat; now requires version 4 SYSLIB
- ; and Z3LIB. This is now a type 3 program
- ; but I do not recommend linking it for
- ; high-memory execution since the Z3VARLIB
- ; routines don't check for top of TPA.
- ; Howard Goldstein
- ;
- ;
- VERS EQU 14
- ;
- ;
- PARMFL EQU '/' ; flag indicating parameter follows
- SUBCH EQU '%' ; shell-variable reference flag
- SYSFLG EQU '$' ; System File reference flag
- SUBSEP EQU '|'
- CMDSEP EQU ';'
- LECNT EQU 20 ;number of pointers on String Ptr Stack
- CTRLZ EQU 1AH ;^Z for EOF
- FCB EQU 5CH
- TBUFF EQU 80H
- BDOS EQU 5
- CR EQU 0DH
- LF EQU 0AH
- ;
- CMDLIN EQU 80H ; CP/M's command line buffer
- ;
- ;
- ; SYSLIB and Z3LIB routines
- ;
- EXT Z3INIT,PUTER2,GETREG,PUTCL,GETFNX,INVERROR
- EXT SKSP,MAFDC,FILLB,ISALNUM
- EXT CAPS,PRINT,CODEND
- ;
- ; Z3VARS routines
- ;
- EXT VARLOAD, VARDEF
- ;
- ;
- ; Program beginning
- ;
- ; TYPE 3 HEADER
-
- ; Code modified as suggested by Charles Irvine to function correctly with
- ; interrupts enabled. Program will abort with an error message when not
- ; loaded to the correct address (attempt to run it under CP/M or Z30).
-
- entry:
- jr start0 ; Must use relative jump
- DB VERS ;embed version number
- db 'Z3ENV',3 ; Type-3 environment
- z3eadr:
- dw 0 ; Filled in by Z33
- dw entry ; Intended load address
-
- start0:
- ld hl,0 ; Point to warmboot entry
- ld a,(hl) ; Save the byte there
- di ; Protect against interrupts
- ld (hl),0c9h ; Replace warmboot with a return opcode
- rst 0 ; Call address 0, pushing RETADDR
- ; Onto stack
- retaddr:
- ld (hl),a ; Restore byte at 0
- dec sp ; Get stack pointer to point
- dec sp ; To the value of RETADDR
- pop hl ; Get it into HL and restore stack
- ei ; We can allow interrupts again
- ld de,retaddr ; This is where we should be
- xor a ; Clear carry flag
- push hl ; Save address again
- sbc hl,de ; Subtract -- we should have 0 now
- pop hl ; Restore value of RETADDR
- jr z,start ; If addresses matched, begin real code
-
- ld de,notz33msg-retaddr; Offset to message
- add hl,de
- ex de,hl ; Switch pointer to message into DE
- ld c,9
- jp 0005h ; Return via BDOS print string function
- notz33msg:
- db 'Not Z33+$' ; Abort message if not Z33-compatible
-
- ;
- ; Initialize environment for Z3 routines
- START: LD HL,(Z3EADR)
- CALL Z3INIT
- ;
- ; Reset error flag
- XOR A
- CALL PUTER2
- ;
- ; Save stack and set new one
- LD (SAVESP),SP
- LD SP,STACK
- ;
- ; Set Pointers
- CALL CODEND ;find scratch area
- LD (INTLINE),HL ;set ptr to internal line buffer
- LD DE,200H ;reserve 200H bytes
- ADD HL,DE
- LD (VARLIST),HL ;set ptr to variable list
- ;
- ; Fill buffer of line to be built with zeroes to ensure that it remains
- ; null-terminated.
- LD HL,(INTLINE)
- LD D,H
- LD E,L
- INC DE
- LD BC,1FFH
- LD (HL),0
- LDIR
- ;
- ; Point to CP/M's command line
- LD HL,CMDLIN
- ;
- ; Quit if no command line passed
- LD A,(HL)
- OR A
- JP Z,HELP
- ;
- ; Now parse command line.
- ; First look for option character. Only option is help, which is exclusive.
- LD HL,CMDLIN+1
- CALL SKSP
- LD A,PARMFL
- CP (HL)
- JR NZ,EXPAND
- INC HL
- CP (HL)
- JP Z,HELP
- DEC HL
- ;
- ; Expand Command Line pointed to by HL, performing variable
- ; substitutions
- ;
- ; On exit, Z=command line overflow and Line Pted to by HL
- ;
- EXPAND:
- EX DE,HL ;DE pts to line
- ;
- ; Init String Pointer Stack
- ;
- LD A,LECNT ;set local element count
- LD (LOCELT),A
- LD HL,LOCSTK ;set local stack
- LD (LOCADR),HL
- LD HL,0 ;set done code on stack
- CALL LOCPUSH ;push HL
- ;
- ; Set Ptrs
- ;
- LD HL,(INTLINE) ;pt to internal line
- EX DE,HL ;DE pts to internal line, HL pt next char
- LD B,0 ;256 chars max
- ;
- ; Analyze Next Char
- ;
- EXP1:
- LD A,(HL) ;get next char
- CP SYSFLG ;system file or directory substitution?
- JR NZ,TEST2
- CALL SYSFIL
- DEC C
- JR Z,EXP1 ;no error on return
- JR EXP2 ;error on return - store offending char in CL
- ;
- TEST2:
- CP SUBCH ;substitution char?
- JR NZ,EXP2
- ;
- ; Process Shell Variable
- ;
- CALL EXPVAR ;resolve variable
- DEC C ;error?
- JR Z,EXP1 ;resume if none
- ;
- ;
- ; Store Next Char
- ;
- EXP2:
- LD (DE),A ;store char
- INC HL ;point to next
- INC DE
- DEC B ;count down
- JR Z,EXPERR ;error if at 0
- ;
- OR A ;done? (was last char stored a null?)
- JR NZ,EXP1
- INC B ;increment count (not counting last 0)
- DEC DE ;pt to null in case another string to analyze
- ;
- ; Pop String Ptr Stack and Check for Analysis Complete
- ;
- CALL LOCPOP ;get ptr to previous string
- LD A,H ;done?
- OR L
- JR NZ,EXP1 ;resume
- DEC A ;set NZ
- ;
- ; Expansion Complete
- ; On entry, Z Flag is Set Accordingly (Z=Error)
- ;
- EXPERR: JR Z,EXPERR1
- LD HL,(INTLINE) ;pt to internal line
- CALL PUTCL
- JR NZ,EXIT
- ;
- ; Print overflow message and set error flag
- EXPERR1:
- CALL PRINT
- DB CR,LF,'Command Line Overflow',CR,LF,0
- LD A,0FFH ; indicate external error
- LD B,13 ;error code
- CALL INVERROR ;set up to invoke error handler
- ;
- ; Return to ZCPR3
- ;
- EXIT:
- LD HL,(SAVESP)
- LD SP,HL
- RET
- ;
- ; Expand Variable
- ; Return with HL pting to next char, A=char, C=1 if OK, C=2 if error
- ;
- EXPVAR:
- LD (VARPTR),HL ;save ptr to variable
- INC HL ;get next char
- LD C,2 ;prep for error return
- LD A,(HL) ;get it
- OR A ;EOL?
- RET Z
- CP SUBCH ;double sub char?
- RET Z ;place one sub char in line if so
- ;
- ; Place Variable Into SHVAR
- ;
- PUSH BC ;save counter
- PUSH DE ;save ptr to next char
- PUSH HL ;save ptr to shell variable
- LD HL,SHVAR ;pt to shell variable buffer
- LD B,8 ;8 chars max
- LD A,' ' ;space fill
- CALL FILLB
- EX DE,HL ;DE pts to shell variable buffer
- POP HL ;pt to shell variable
- LD B,8 ;8 chars max
- ;
- ; Place Shell Variable into Buffer
- ;
- EXPV1:
- LD A,(HL) ;get char
- CALL DELCK ;check for delimiter
- JR NZ,EXPV3 ;done if delimiter
- LD (DE),A ;save char
- INC HL ;pt to next
- INC DE
- DJNZ EXPV1
- ;
- ; Flush Overflow of Shell Variable
- ;
- EXPV2:
- LD A,(HL) ;get char
- INC HL ;pt to next
- CALL DELCK ;check for delimiter
- JR Z,EXPV2
- DEC HL ;pt to delimiter
- ;
- ; Shell Variable in buffer SHVAR
- ; HL pts to delimiter after variable in user line
- ;
- EXPV3:
- CALL LOCPUSH ;stack ptr to next char in current string
- JR Z,EXPV4 ;error in stack
- LD HL,(VARLIST)
- CALL VARLOAD ;load shell variable list
- JR NZ,EXPV4 ;failure
- LD HL,SHVAR
- CALL VARDEF ;resolve named variable reference
- JR Z,EXPV5 ;name found - resolve
- ;
- ; Shell Variable Not Resolved - Restore Ptr to It
- ;
- EXPV4:
- CALL LOCPOP ;restore ptr
- POP DE
- POP BC
- LD C,2 ;error
- LD HL,(VARPTR) ;pt to variable
- INC HL ;point past '%'
- CALL SETERR
- LD A,(HL)
- RET
- ;
- ; Entry Point for OK Return
- ;
- EXPV5:
- LD A,(HL) ;get char
- POP DE ;pt to target
- POP BC ;get counter
- LD C,1
- RET
-
- ;
- ; Push HL onto String Ptr Stack
- ; Return with Z if Stack Overflow
- ;
- LOCPUSH:
- LD A,(LOCELT) ;get count
- DEC A ;full?
- RET Z
- LD (LOCELT),A ;set count
- PUSH DE ;save DE
- EX DE,HL ;DE pts to old string
- LD HL,(LOCADR) ;get ptr to top of stack
- LD (HL),E ;store low
- INC HL
- LD (HL),D ;store high
- INC HL ;pt to next
- LD (LOCADR),HL
- EX DE,HL ;restore HL
- POP DE ;restore DE
- XOR A ;return NZ
- DEC A
- RET
- ;
- ; Pop HL from String Ptr Stack
- ;
- LOCPOP:
- PUSH DE
- LD A,(LOCELT) ;increment element count
- INC A
- LD (LOCELT),A
- LD HL,(LOCADR) ;get address
- DEC HL ;pt to high
- LD D,(HL) ;get high
- DEC HL ;pt to low
- LD E,(HL) ;get low
- LD (LOCADR),HL ;set address
- EX DE,HL ;restore ptr
- POP DE
- RET
- ;
- ; Check to see if char in A is a delimiter
- ; Return with Z if so
- ;
- DELCK:
- CALL CAPS ;capitalize char
- JP ISALNUM
- ;
- ;
- ; Print help message and exit.
- HELP: CALL PRINT
- ; DB 'RESOLVE v. ',(VERS/10)+'0','.',(VERS MOD 10)+'0',CR,LF
- DB 'RESOLVE v. ',[VERS/10]+'0','.',[VERS MOD 10]+'0',CR,LF
- DB 'Resolve command line -- the following flags are '
- DB 'interpreted:',CR,LF
- DB ' Flag Meaning',CR,LF
- DB ' ---- -------',CR,LF
- DB ' %<text> Shell variable name.',CR,LF
- DB ' $R<n> Register number. (n = 1-31)',CR,LF
- DB ' $D Current drive letter.',CR,LF
- DB ' $U Current user number.',CR,LF
- DB ' $F<n> System File name. (n = 1-4)',CR,LF
- DB ' $N<n> System File, name only.',CR,LF
- DB ' $T<n> System File, extension only.',CR,LF
- DB ' $| Substitute command separator (;)',CR,LF
- DB 0
- JP EXIT
- ;
- ;
- ; EXPANSION ROUTINES
- ; The following routines each expand a particular kind of reference.
- ; Inputs : HL contains a pointer to the command line being interpreted;
- ; DE points to the string being built.
- ; Outputs: C contains an error flag: 2=error, 1=OK
- ; HL points to the next char in the CL to interpret if no error (C=1)
- ; points to last char interpreted if error (C=2)
- ; DE points to the next location to fill in the CL being built
- ; If any of the flags are followed by incorrect parameters, the entire
- ; token, INCLUDING the leading dollar sign, is copied to the command line
- ; being built.
- ;
- SYSFIL:
- INC HL ;point to next character
- LD C,1 ;prepare for no-error return
- LD A,(HL) ;get character
- OR A ;end of line?
- JR NZ,SYSF2
- INC C ;indicate error
- DEC HL
- CALL SETERR
- LD A,(HL)
- RET
- ;
- SYSF2: CP 'F' ;full filename?
- JR Z,FFNAME
- CP 'N' ;just the name?
- JR Z,FFNAME
- CP 'T' ;just the type?
- JR Z,FFNAME
- CP 'D' ;current drive?
- JP Z,CDRIV
- CP 'U' ;current useer?
- JP Z,CUSR
- CP 'R' ;register number?
- JP Z,REGR
- CP SUBSEP
- JP Z,SUBCHR
- CALL SETERR ;otherwise, set Z3 error byte
- DEC HL ;point back to sysflg
- LD A,(HL)
- INC C ;and return with error indicator
- RET
- ;
- ; Character is one of the 3 system file flags. Get number of filename,
- ; then get full file name or appropriate part and insert in command line.
- ;
- FFNAME:
- LD (FNFLG),A ;store flag
- INC HL ;get number
- LD A,(HL)
- OR A
- JR Z,FFERR
- ;
- FFNAM2: CALL FNCHEK ;check that number is in range 1-4
- JR Z,FFERR ;quit if not
- ;
- SUB 30H ;convert to binary 1-4
- PUSH HL
- CALL GETFNX ;get address of filename in HL
- LD A,(HL) ;check for defined name
- CP ' '
- JR NZ,FFNAM4
- ;
- POP HL
- INC HL
- LD C,1 ;don't store char on return
- RET
- ;
- FFNAM4: PUSH BC
- LD A,(FNFLG) ;what do we want?
- CP 'T' ;type only?
- JR NZ,FFNAM5
- PUSH DE ;save dest address
- LD DE,8
- ADD HL,DE ;point to type
- POP DE
- JR FFNAM6
- FFNAM5: CALL TRANS8 ;transfer 1st 8 chars of filename
- ;
- LD A,(FNFLG) ;again, what do we want?
- CP 'N' ;name only?
- JR Z,FFNAM7
- LD A,'.' ;name transferred, now do period
- LD (DE),A
- INC DE
- ;
- FFNAM6: CALL TRANS3 ;transfer filetype
- FFNAM7: POP BC
- POP HL
- INC HL
- LD C,1 ;indicate all OK
- RET
- ;
- FFERR: ;erroneous file number
- dec hl
- DEC HL ;point to SYSFLG
- LD A,(HL)
- LD C,2 ;store char on return
- RET
- ;
- ;
- ; ================ FILENAME TRANSFER UTILITIES ================
- ;
- ;
- ; Check whether char in A is in ASCII range '1'-'4'. Set the error flag and
- ; return with Z set if out of range.
- ;
- FNCHEK: CP '1' ;less than one?
- JR C,FNERR
- CP '5' ; greater than four?
- JR NC,FNERR
- OR A ;force NZ
- RET
- ;
- FNERR: CALL SETERR
- CP A ;set Z without disturbing A
- RET
- ;
- ; Transfer 8 characters of filename from (HL) to (DE). If fewer than 8 chars,
- ; increment HL to point past eighth anyway. BC also used, not saved.
- ;
- TRANS8: LD B,8 ;# of chars in name
- TR82: LD A,(HL)
- CP ' '
- JR Z,TR83
- LD (DE),A
- INC HL
- INC DE
- DJNZ TR82
- TR83: LD A,B ;were 8 chars transferred?
- OR A
- RET Z
- TR84: INC HL
- DJNZ TR84
- RET
- ;
-
- ; Transfer 3 characters of filename from (HL) to (DE). BC is also used,
- ; not saved. HL is NOT incremented past filename.
- ;
- TRANS3: LD B,3 ;transfer filetype
- TR32: LD A,(HL)
- CP ' '
- RET Z
- LD (DE),A
- INC HL
- INC DE
- DJNZ TR32
- RET
- ; ================ END OF FILENAME TRANSFER UTILITIES ================
- ;
- ;
- ; Character is substitute command-line separator. If next character is the
- ; same, preserve one of them. Otherwise, replace it with the real command
- ; separator.
- ;
- SUBCHR: LD C,2 ;prepare for 'error' return
- INC HL ;get next char
- LD A,(HL)
- OR A ;premature end of CL?
- RET Z
- ;
- SUBCH2: CP SUBSEP ;also sub. cmd. sep?
- RET Z ;if so, return it
- DEC HL ;else point before it
- LD A,CMDSEP ;and return the real cmd. sep.
- RET ;('error' status will have it stored)
- ;
- ; Return current drive.
- ;
- CDRIV: PUSH HL
- PUSH DE
- LD C,19H
- CALL BDOS
- ADD A,'A'
- POP DE
- POP HL
- LD C,2 ;use char in A
- RET
- ;
- ; Return current user #.
- ;
- CUSR: PUSH HL
- PUSH DE
- LD C,20H
- LD E,0FFH
- CALL BDOS ;user # in A
- POP DE
- CALL MAFDC ;up to 3 dec. digits stored at DE
- POP HL
- INC HL
- LD C,1
- RET
- ;
- ; Get register #.
- ;
- REGR: LD C,2 ;prepare for error
- INC HL
- LD A,(HL) ;get reg #
- ;
- REGR2: SUB '0'
- CP 10 ;check for 0-9
- JR NC,REGERR
- PUSH DE ;save dest. addr., to use reg for mult.
- LD D,A
- INC HL
- LD A,(HL)
- SUB '0'
- CP 10
- JR C,REGR3
- DEC HL
- LD A,D
- JR REGR4
- REGR3: LD E,A
- LD A,D ;multiply 1st digit by 10
- ADD A,A ;x2
- ADD A,A ;x4
- ADD A,D ;x5
- ADD A,A ;x10
- ADD A,E ;add second digit
- CP 32 ;check range -- 0-31
- JR C,REGR4
- DEC HL
- POP DE
- REGERR: DEC HL ;point back to '$'
- DEC HL
- CALL SETERR
- LD A,(HL)
- RET
- REGR4: POP DE ;get destination addr back
- PUSH BC
- LD B,A ;register # in B
- PUSH HL
- CALL GETREG ;register value now in A
- CALL MAFDC ;up to 3 dec. digits stored at DE
- POP HL
- INC HL
- POP BC
- LD C,1
- RET
- ;
- ;
- ; Set transient error code byte.
- ;
- SETERR: PUSH AF
- XOR A
- DEC A
- CALL PUTER2
- POP AF
- RET
- ;
- ;
- ; Buffers
- ;
- DSEG
- ;
- SAVESP: DS 2
- DS 48
- STACK: DS 2
- SHVAR: DS 8
- LOCELT:
- DS 1 ;string stack element count
- LOCADR:
- DS 2 ;ptr to next entry on stack
- LOCSTK:
- DS LECNT*2 ;string ptr stack
- VARPTR:
- DS 2 ;ptr to current variable in line
- FNFLG: DS 1
- INTLINE:
- DS 2 ;ptr internal expansion line
- VARLIST:
- DS 2 ;list of shell variables.
-
- END START
-