home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
ZCPR33
/
A-R
/
LX19.LBR
/
LX19.ZZ0
/
LX19.Z80
Wrap
Text File
|
2000-06-30
|
26KB
|
982 lines
title 'LX VERSION 1.8 - RUN PROGRAM FROM COMMAND.LBR'
; PROGRAM: LX
; AUTHOR: RICHARD CONN
; VERSION: 1.0
; DATE: 10 Aug 85
; PREVIOUS VERSIONS: None
vers equ 19 ; Corrected help screen, safety header added,
; restored Royce Shofner's wheel byte idea in
; a simpler way. An option byte at 102h
; controls LX19's wheel byte response. If it
; is patched to a zero (0FFh in distributed
; COM/CIM files), LX19 will test the wheel
; byte and use ROOT:USERCMD.LBR instead of
; ROOT:COMMAND.LBR if not wheel (wheel byte
; is reset, zeroed). Otherwise LX19 will
; work like LX18 did - very nicely. Both
; Default LBR names remain patchable to
; preference.
; April 1, 1988 Bruce Morgen
;vers equ 18 ; Rewrote the ADJCML routine. IT NOW ADJUSTS
; THE COMMAND LINE PROPERLY WHEN A LIBRARY
; NAME WAS INCLUDED IN THE COMMAND.
;
; Howard Goldstein, November 29, 1987
;vers equ 17 ; Added code to parse file names via
; resident CPR code if ZCPR33 is present.
; This makes LX completely Z33 compatible.
; Removed Bruce Morgen's in-line PUTER3
; ; code since Z33LIB's version works properly
; now.
;
; Howard Goldstein, November 21, 1987
;vers equ 16 ; Deleted vestigial buffer set-up code via
; DSEGed buffer definitions. LX now does
; a better simulation of the 3.3 CPR by
; passing the environment descriptor pointer
; in HL as well as poking ORG+9 in Z3 tools.
; Added detection code for LX running under
; WordStar. A new alternate syntax has been
; introduced especially for chaining to LX
; from ARUNZ's "default alias" feature:
; :DEFAULT [dir or du:]LX / $0 $*
; Under that condition, or whenever LX is
; called with the intervening "/" parameter,
; LX will declare itself an ECP and, if there
; is an error, adjust the command line to
; eliminate its own verb. If running under
; Z33, LX follows the CPR's DUFIRST flag.
; All errors (except under WordStar) now abort
; to the error handler with the ECP bit set
; on return to the CPR. While we were at it,
; replaced the internal COUT routine with a
; simple JP to BOUT to accomodate BIOS's
; that (legitimately) do not bother to preserve
; the HL register through CONOUT calls. The
; BOUT approach ALWAYS (famous last words)
; works, and is shorter to "bout" (grin). The
; reason there is a hand-coded PUTER3 routine
; in LX is that Z33LIB's fails to preserve the
; incoming A register against GETMSG's return.
; In other words, it doesn't work.
;
; Bruce Morgen @23:55:56 June 4, 1987
;vers equ 15 ; Adapted to coexist as an ECP with error
; handling under ZCPR 3.3 and BGii 1.13 or
; later. Also extended Michael's auto-
; install code to properly initialize the
; copy routine for Z33 type 2 COMfiles
; (origin other than 100H). Bumped versions
; past 1.3 & 1.4, which seem to be of interest
; mainly to Z-Node sysops (no offense, Royce,
; just a personal opinion - b/m). Note that
; there is a problem regarding SYSLIB's
; CODEND routine and the use of DSEG as
; recommended for the upcoming Z80 versions
; of the Conn *LIBs. The old approach (the
; $MEMRY buffer in CSEG) has been recommended
; to the LIBs revision team. All modifiable
; LX data buffers are now in DSEG, including
; the (now runtime-initialized) ARGV argument
; table. While I was at it, I got rid of the
; unecessary self-modifying code at COPY$CODE.
; Remember, we won't be able to get away with
; such kludges with the Z280, so we might as
; well start getting rid of our bad habits now.
; Note that LX now carries its own COUT routine
; to enable showing an error or a help screen
; under the WordStar "R" command without
; crashing anyone's system to a fare-thee-well.
; Bruce Morgen @15:03:03 April 24, 1987
;vers equ 12 ; Auto-installs ZCPR3 utilities. There is no
; need to run Z3INS on utilities run by LX
; since, after loading and before executing,
; LX looks for "Z3ENV" at the beginning. If
; present, LX inserts the address of the
; environment descriptor. Both concept and
; code are based on Jay Sage's experimental CCP.
; 3 September 1986 - Michael Bate
;vers equ 11 ; Extracted ARGV from syslib36 and included
; it here, modified so that '=' is also an
; argument delimiter if it occurs after
; a non-space (sknsp:). 27 Feb 86 jww
;vers equ 10 ; Release version
z3env defl 0fe00h ; My Z3 environment location
; LX is like the old LRUN tools in that it looks at its arguments
; as a command line to be executed. LX locks onto a library file, searches
; for the command verb COM file in it, extracts the COM file into memory
; at 100H, and sets up the various buffers to look like the COM file was
; executed by the ZCPR3 command processor.
; Unlike the other LRUN tools I've seen and heard of (with the
; possible exception of LRUNZ), LX truly acts as the ZCPR3 command
; processor, parsing the command line as ZCPR3 itself would. Named
; directory references are allowed, the External FCB is loaded if
; available, etc. Any ZCPR3 tool executed by LX sees the environment
; as it would if ZCPR3 itself executed the tool.
; For security, no directory references are allowed (they are
; ignored) for any arguments if the wheel byte is not set.
public cout ; b/m, April 24, 1987
; Externals
extrn z3init,codend
extrn eprint,retud,putud,logud,getud;,pfn1
extrn initfcb,f$exist
extrn getefcb,zprsfn,z3log,pfind,getwhl
extrn luinit,luopen,luread
extrn getcst,putcst ; b/m April 24, 1987
extrn getcl1,clrcl,putcl,getquiet,bout,pfn2 ; b/m June 3, 1987
extrn z33chk,geter3,getmsg; Z33LIB, etc. b/m June 4, 1987
extrn z33fname,puter3; h/g Nov. 21, 1987
; Equates
cr equ 0dh
lf equ 0ah
bdose equ 5
fcb1 equ 5ch
fcb2 equ 6ch
tbuff equ 80h
tpa equ 100h
lnsize equ 22 ; Number of chars allowed for library name
; External ZCPR3 Environment Descriptor
; 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
option: db 0ffh ; Make zero for wheel byte
; control of default LBR
z3ename:
db 'Z3ENV',3 ; Type-3 environment
z3eadr:
dw z3env ; 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
; Names of Library Files
libnam1:
db 'ROOT:COMMAND.LBR',0
ds lnsize-[$-libnam1]
libnam2:
db 'ROOT:USERCMD.LBR',0
ds lnsize-[$-libnam2]
; Beginning of code; set buffer definitions here
start:
ld hl,(z3eadr) ; Pt to zcpr3 environment
call z3init ; Init zcpr3 environment
start1:
ld a,(bdose+2) ; Get bdos base page
sub a,9 ; 9 pages below bdos is 1 page below ccp
ld (tpaend),a ; Set end of tpa
call codend ; Get free space ptr
ld (scratch),hl ; Free space ptr
ld hl,tpa ; Default COMfile starting addr.
ld (cpytpa),hl
ld hl,argv2 ; Usual command tail start ptr.
ld (tailst),hl
ld hl,libnam1
ld a,(option)
or a
call z,getwhl
jr nz,nogwhl
ld hl,libnam2
nogwhl: ld (libname),hl
ld de,clineb ; Point to local buffer for MCL.
ld a,(1) ; Test for WordStar BIOS table.
sub a,3
jr nz,savocl ; Skip MCL if WS is running.
ld (de),a ; Init. local MCL buffer to 0.
ld b,a ; Make sure B=0.
call getcst ; Get Command Status Flag.
bit 2,a ; Test ECP bit.
jr nz,savocl ; Skip MCL stuff if we're ECP.
ld a,'/' ; Check for help and forced ECP.
ld hl,(fcb1+1) ; Help "/" in H, ECP "/" in L.
cp h ; Test for help query
jr z,help
sub l ; Test for forced ECP request.
jr nz,savocl
call getcl1 ; Find MCL buffer (B=0).
ld c,a ; MCL size is now in BC.
ld a,l ; Test for no MCL buffer.
or h
jr z,savocl ; No MCL? Then branch ahead...
inc hl ; Otherwise bump to MCL start.
inc hl
inc hl
inc hl
ldir ; Move MCL to local buffer.
; Save original command line
savocl: ld hl,tbuff+1 ; Copy from tbuff
ld de,cmdline
ld bc,128 ; 128 bytes
ldir
; Save home directory
call putud
; First parse of command line to determine if help needed, name of library
ld hl,cmdline ; Pt to command line
ld de,args ; Pt to argument table
ld a,5 ; Init. for five arguments
ld (de),a ; so table can be in DSEG
xor a ; Do not delimit tokens (A=0)
call argv ; Generate vector
ld a,(argc) ; Check count
ld b,a ; Save arg count in b
or a ; Help if no args
jr z,help
ld hl,(argv1) ; Get ptr to first arg
ld a,(hl) ; Get first char of first arg
cp '/'
jp nz,go1 ; Skip help if not /
djnz goecp ; Should ALWAYS jump, but W.T.H.
; Print Help Message
help:
call eprint
db 'LX, Version '
db [vers/10]+'0','.',[vers mod 10]+'0'
db cr,lf,' Syntax: LX [/] [-[dir:]library] command_line'
db cr,lf,' (Use "/" option when chaining from ARUNZ'
db ' default alias)',0
ret
; Adjust vectors for forced-ECP mode
goecp: ld de,argv2
ld hl,argv3
ld (tailst),hl
ld hl,(argv2)
ld a,(hl)
jr goecp1
; Continue processing; check for and process library reference
go1:
ld de,argv1 ; Set pointer for first token
goecp1:
cp '-' ; Library reference?
jr nz,go2
dec b ; Reduce argument count by 1
jp z,help ; Library name by itself is not enough
; Extract and store library reference
push bc ; Save arg count
ld de,(libname) ; Set library name
push de ; Save on stack
inc hl ; Pt to name
ld bc,lnsize ; Size of buffer
ldir ; BC=00
pop hl ; Terminate name with zero
lnscan:
ld a,(hl) ; Get next char
cp ' ' ; Done?
jr z,lnscan1
or a
jr z,lnscan1
inc hl ; Pt to next
jr lnscan
lnscan1:
ld (hl),b ; B=0
ld de,(tailst) ; Set ptr to first token
pop bc ; Get arg count
; DE pts to first token of command line
; Store command line (next token) into TBUFF
go2:
push de ; Save ptr to first token
djnz go3 ; See if any tokens follow the command name
; If no more tokens, then zero gbuff
ld hl,gbuff ; Store empty command line into gbuff
ld (hl),b ; B=0.
inc hl
ld (hl),b
jr gcline
; Save command line tail into GBUFF
go3:
inc de ; Pt to next token
inc de
ld a,(de) ; Get address
ld l,a
inc de
ld a,(de)
ld h,a ; Hl pts to first token of command line tail
ld de,gbuff+1 ; Pt to command line buffer (char after)
ld a,' '
ld (de),a ; Store leading space
inc de
ld b,1 ; Set char count to 1
cltsave:
ld a,(hl) ; Get next char
ld (de),a ; Store it
or a ; Eol?
jr z,cltsdone
inc hl ; Pt to next
inc de
inc b ; Increment count
jr cltsave
cltsdone:
ld a,b ; Get count
ld (gbuff),a ; Set count in local buffer.
gcline:
call retud ; C=current user
call getefcb ; Clear external fcb
call nz,clrfcb
ld hl,fcb1 ; Clear fcb1
call clrfcb
ld hl,fcb2 ; Clear fcb2
call clrfcb
pop hl ; Get ptr to first token
ld a,(hl) ; Get address
inc hl
ld h,(hl)
ld l,a ; Hl pts to first token
ld de,args ; Use same argument vector table
ld a,0ffh ; Null-terminate arguments
call argv
ld c,0 ; Up to 3 tokens to obtain
ld de,argv1 ; Pt to first token
ld a,(argc) ; Get argument count
cp 4 ; Range?
jr c,go4
ld a,3 ; Set 3 tokens
go4:
ld b,a ; In c
; There are three tokens (max) to be extracted:
; Program name (external FCB)
; FCB 1
; FCB 2
go5:
push bc ; Save counters
call namebld ; Build token
pop bc ; Get counters
inc c ; Increment token id
djnz go5
call getefcb ; Set file type to com for external fcb
jr z,go6 ; No external fcb
ld de,9 ; Offset
add hl,de
ld de,comtyp ; File type
ex de,hl
ld bc,3 ; 3 bytes
ldir
; Locate LBR file
go6:
call find$lf
jr nz,chekws ; Abort if not found
; Load Command from Library into Memory Above LRUN
call loadcom ; Extract and load to high RAM.
jr nz,autoin ; Do Z3 install if successful.
chekws: ld a,(1) ; Test for the WordStar kludge.
cp 3
jp nz,getud ; Reassert orig. DU and exit.
ld hl,clineb ; Point at local MCL copy start.
ld a,(hl) ; Get first character.
or a ; Were we forced ECP (/)?
jr nz,adjmcl ; Then adjust MCL bffr.
call getcst ; Get Command Status Flag.
ld b,a
bit 2,a ; Real ECP?
jr nz,exterr ; Then just set CSF error bit.
call z33chk ; Running ZCPR 3.3?
jr nz,goter3 ; Then just set ECP, error bits.
set 3,b ; Otherwise external source...
call geter3 ; Get current Z33 error #.
cp 7 ; Higher than "default" (#6)?
jr nc,goter3 ; Then use it.
ld a,10 ; Otherwise set error #10.
call puter3 ; Stuff it.
goter3: ld a,b ; Get back CSF.
jr errext ; Set ECP, error bits and stuff.
adjmcl: ld de,args ; Pt to ARGV table
xor a ; Don't delimit tokens
call argv ; Get vector of tokens in MCL
ld hl,(argv3) ; Pt to 3rd token
ld a,(hl) ; Get first char
cp '-' ; '-' means LBR name
jr nz,foundl ; If not, MCL begins here
ld hl,(argv4) ; else, get next token
foundl: call clrcl ; Otherwise clear it.
call putcl ; Replace it, sans the LX verb and
; ..possible LBR name.
call getcst ; Get Cmd. Status Flag (again).
errext: set 2,a ; Set ECP bit.
exterr: set 1,a ; Set error bit.
jp putcst ; Put 'em in CSF and we're done,
; return via Z3LIB routine
; Perform Auto-Install if this is a ZCPR3 utility
autoin: ld ix,(scratch)
ld de,z3ename ; DE -> "Z3ENV" in this program
ld b,5 ; compare 5 bytes
instal0:
ld a,(de) ; Compare "Z3ENV" with location in
cp (ix+3) ; the loaded program that would have it
jr nz,install ; jump if no match - NOT a ZCPR3 utility
inc de
inc ix ; index through the 5 bytes
djnz instal0
ld de,(z3eadr) ; This is a ZCPR3 utility
ld (ix+4),e ; Store the environment address
ld (ix+5),d
ld a,(ix+3) ; Get environment type byte
cp 3 ; Check for type < 2
jr c,install ; Branch if standard-TPA tool
ld e,(ix+6) ; Runtime address into DE
ld d,(ix+7)
ld (cpytpa),de ; Initialize data for copy
; routine and fall through
install:
; Set up TBUFF area
push hl ; save address of next block after load
ld hl,gbuff ; Ptr to local buffer
ld de,tbuff ; Ptr to tbuff
ld bc,128 ; 128 bytes
ldir
pop de ; Get address of next block after load
; Set up to Copy command down and execute
; DE = next block after load
call copyset ; Place copy routine in high memory
call getud ; Return to home directory
ld hl,tbuff ; Set default dma address
call setdma
; Ready to copy program down and transfer to it
; The original return address is on the top of the stack
ld a,(tpaend) ; Get address in hl
ld h,a
ld l,0
jp (hl) ; Process copy command
; Clear FCB pted to by HL
; Current user area is in C
clrfcb:
ld (hl),0 ; Current disk
inc hl ; Pt to name
ld b,11 ; 11 bytes
ld a,' ' ; Space fill
call fill
ld (hl),0 ; Null
inc hl
ld (hl),c ; User area (byte 13)
inc hl
ld b,4 ; Number of bytes
xor a ; Fill with zeroes and
; fall through to FILL
; Fill B bytes pted to by HL with A
fill:
ld (hl),a ; Fill
inc hl ; Pt to next
djnz fill
ret
; Build name of token whose address is pted to by DE
; On input, C=flag:
; 0 Name of program
; 1 FCB 1
; 2 FCB 2
namebld:
ld a,(de) ; Get address of token in hl
ld l,a
inc de
ld a,(de)
ld h,a
inc de
push de ; Save ptr to next
ld a,c ; Check flag
cp 1 ; Middle value
jr c,namexfcb ; External fcb if 0
ld de,fcb1 ; Assume fcb
jr z,nameb1 ; Fcb 1 if 1
ld de,fcb2 ; Else fcb2
jr nameb1
namexfcb:
ex de,hl ; Save hl
call getefcb ; Get ptr to external fcb
ex de,hl ; Hl pts to token, de pts to external fcb
jr nz,nameb1 ; Proceed if external fcb exists
pop de ; External fcb does not exist, so quit
ret
; DE pts to FCB to build into, HL pts to token
nameb1:
push de ; Save fcb ptr
ld de,lfcb ; Pt to local fcb
call parse ; Parse into local fcb
call getwhl ; Check wheel byte
jr nz,nameb2 ; Continue with name build if wheel
; User is not a wheel, so force all directory references to current dir
call retud ; Get current user in c
ld hl,lfcb ; Pt to fcb
ld (hl),0 ; Set current disk
ld de,13 ; Offset to user
add hl,de
ld (hl),c ; Set current user into lfcb
; Store FCB data into FCB
nameb2:
pop de ; Get ptr to target fcb
ld hl,lfcb ; Pt to fcb
ld bc,17 ; Copy 17 bytes
ldir
pop de ; Get ptr to next token
ret
; Place copy routine in high memory
; COM file runs from (SCRATCH) to DE
copyset:
ld hl,(scratch) ; Get start
ex de,hl
or a ; Clear carry
sbc hl,de ; Hl=hl-de=size of load
ld (copy$count),hl ; Set count for copy routine
ld a,(tpaend) ; Set de to location of copy routine
ld d,a
ld e,0 ; Page boundary
ld hl,copy$code ; Copy code
ld bc,copy$size ; Number of bytes
ldir ; Place copy routine
ret
; Copy routine - this will be placed in High Memory
; The 2-byte values at COPY$STRT, COPY$DEST, COPY$COUNT
; and COPY$TPA are set by COPYSET (above) and AUTOIN
copy$code:
ld hl,(z3eadr)
push hl
ld hl,(scratch) ; Start address
ld de,(cpytpa) ; Destination address
push de
pop ix
ld bc,(copy$count) ; Number of bytes
ldir ; Do copy
pop hl ; Environment pointer in HL.
jp (ix) ; Jump to the program.
copy$size equ $-copy$code
; Locate Library File
; On exit, A=0 if library file found
find$lf:
ld hl,(libname) ; Parse library file name
ld de,lud$fcb
call parse
ld de,lud$fcb+9 ; Set library file type
ld hl,lbrtyp ; Default file type
ld bc,3 ; 3 bytes
ldir
; Set specified directory as default
ld de,lud$fcb ; Pt to fcb
call z3log ; Log into it for default
; Look into directory pted to by user (or current if user did not spec one)
ld de,lud$fcb ; Pt to fcb
call initfcb ; Reset fcb
call retud ; Get home location
call f$exist ; Is file there?
jr nz,find$lf2
; Look along path from current dir (not including current)
ld de,lud$fcb ; Pt to fcb
xor a ; Don't search current dir also
call pfind ; Search for file
jr nz,find$lf2 ; File found, so process
; File not found
find$lf1:
call getquiet ; Are we muzzled?
ret nz ; Return NZ if so (A=FFh).
call eprint
db ' Library File ',0
ld de,lud$fcb+1 ; Print file name
call pfn2;1
call eprint
db ' Not Found',0
or 0ffh ; Error code (NZ & A=FFh)
ret
; File found
find$lf2:
call logud ; Log into directory
ld de,lud ; Pt to lud
call luinit ; Read to use library
jr nz,find$lf1 ; Error
ret
; Load COM file into memory
; on exit, NZ if OK and HL = next block
loadcom:
ld de,argv1 ; Pt to command name string
ld a,(de) ; Get address in hl
ld l,a
inc de
ld a,(de)
ld h,a
ld de,lfcb ; Pt to fcb
call parse ; Parse into fcb
ld hl,9 ; Set type of file to 'com'
add hl,de
ld de,comtyp ; File type
ex de,hl
ld bc,3 ; 3 bytes
ldir
ld de,lud ; Pt to lud
ld hl,lfcb ; Pt to fcb
inc hl ; Pt to file name
call luopen ; Open file
ld hl,(scratch) ; Pt to buffer
jr z,lcom ; Load command if no error
call getquiet ; Muzzled?
jr nz,noprnt ; Skip msg. if so
call eprint ; Otherwise fall through
db ' File ',0
ld de,lfcb+1 ; Pt to FBC's file name ASCII.
call pfn2
call eprint
db ' Not Found in Library ',0
ld de,lud$fcb+1 ; Pt to library file name
call pfn2
noprnt: xor a ; Error
ret
lcom:
call setdma ; Set dma address
ld a,(tpaend) ; Check against end page of tpa
cp h ; If at same page, yes
jr z,lcomerror
ld de,lud ; Pt to lud
call luread ; Read block
ret nz
ld de,128 ; Pt to next block
add hl,de
jr lcom
lcomerror:
call getquiet
jr nz,qlcom
call eprint
db ' Memory Full',0
qlcom: call z33chk
jr nz,notz33
ld a,12
call puter3
notz33: xor a ; Error code
ret
; Set DMA Address to that pted to by HL
;
setdma:
push hl ; Save hl
ex de,hl
ld c,26 ; Set dma function
call bdose
pop hl ; Restore hl
ret
; SYSLIB Module Name: SARGV
; Author: Richard Conn
; SYSLIB Version Number: 3.6
; Module Version Number: 1.1
; public argv
; ARGV is a UNIX-style ARGC/ARGV string parser. It is passed
; a null-terminated string in HL and the address of a token pointer
; table in DE as follows:
; LXI H,STRING
; LXI D,ARGV$TABLE
; MVI A,0 ; do not mark token end
; CALL ARGV
; JNZ TOKEN$OVFL ; indicates more tokens than allowed
; ...
; ARGV$TABLE:
; DB MAX$ENT ; max number of entries permitted
; DS 1 ; number of entries stored by ARGV
; DS 2 ; pointer to token 1
; DS 2 ; pointer to token 2
; ...
; DS 2 ; pointer to token MAX$ENT
; Tokens are delimited by spaces and tabs.
; As well as '='. 27 Feb 86 jww
; On input, if A=0, the end of each token is not marked with a null.
; If A<>0, a null is placed after the last byte of each token.
; If all went well, return with A=0 and Zero Flag set. If there
; are possibly more tokens than pointers, return with A=0FFH and NZ.
argv:
push bc ; save regs
push de
push hl
ld c,a ; save mark flag
ex de,hl
ld b,(hl) ; get max entry count
push hl ; save address of max entry count
inc hl ; pt to token count
inc hl ; pt to first pointer
; On each loop, DE = address of next char in string and HL = address of
; next pointer buffer; B = number of pointer buffers remaining and C =
; mark flag (0 = no mark)
loop:
call sksp ; skip spaces and tabs in string pted to by DE
or a ; end of string?
jr z,done
ld (hl),e ; store low
inc hl
ld (hl),d ; store high
inc hl
dec b ; count down
jr z,loop2
call sknsp ; skip until end of token
or a ; done?
jr z,done
ld a,c ; get mark flag
or a ; 0=no mark
jr z,loop1
xor a ; mark with null
ld (de),a ; store null
inc de ; pt to next char
loop1:
ld a,b ; check count
or a
jr nz,loop ; continue on
loop2:
call sknsp ; skip over token
call sksp ; any tokens left?
or a
jr z,done ; none if EOL
or 0ffh ; make A = 0FFH to indicate more to come
done:
pop hl ; get address of max token count
push af ; save return flags
ld a,(hl) ; get max token count
sub b ; subtract counter
inc hl ; pt to return count
ld (hl),a ; set return count
pop af ; get return flag
pop hl ; restore regs
pop de
pop bc
ret
; Skip over space or tab characters
sksp:
ld a,(de) ; get char
and 7fh ; mask
inc de ; pt to next
cp ' ' ; continue if space
jr z,sksp
cp 9 ; continue if tab
jr z,sksp
dec de ; pt to character
ret
; Skip over non-space and non-tab characters
; Added '=' so that A:=B: construct yields two arguments. v1.1 jww
sknsp:
ld a,(de) ; get char
and 7fh ; mask
ret z ; done if null
cp ' '
ret z ; done if space
cp 9
ret z ; done if tab
cp '='
ret z ; new delimiter
inc de ; pt to next
jr sknsp
; end
; End of argv inclusion
; Console character output "routine".
; Unlike SYSLIB's COUT, this one will
; work under WordStar's "R" option.
; b/m, June 3, 1987
cout: jp bout ; PUBLIC label for EPRINT, etc.
; Parses token pointed to by HL into FCB pointed to
; by DE. If Z33 running, uses resident CPR code, otherwise
; uses ZPRSFN. This ensures full ZCPR33 compatibility.
parse: call z33chk
ld a,0 ; DIR first for ZPRSFN
jp nz,zprsfn
jp z33fname
; Filetype strings
lbrtyp:
db 'LBR' ; Default lbr file type
comtyp:
db 'COM' ; Default com file type
; Data Area
dseg ; To minimize COMfile size
args: ; ARGV argument table
; db 4
ds 1 ; Will init. to allow up to 4
argc:
ds 1 ; Argument count
argv1:
ds 2 ; First argument
argv2:
ds 2 ; Second argument
argv3:
ds 2 ; Third argument
argv4:
ds 2*3 ; 3 more arguments
tailst:
ds 2 ; Start of actual command tail
lud:
ds 6 ; Dummy used by lu* routines
ds 11 ; Not of concern here
lud$fcb:
ds 36 ; Fcb containing library file data
; General-purpose LX Buffers & Pointers.
tpaend:
ds 1 ; Top page of tpa (msb)
gbuff:
ds 128 ; Command line save area
lfcb:
ds 36 ; Local fcb
cmdline:
ds 128 ; Saved command line buffer
clineb: ds 256 ; Saved MCL buffer
scratch:
ds 2 ; Free space start
libname:
ds 2
; For relocated COPY$CODE routine
cpytpa:
ds 2 ; COMfile runtime origin
copy$count:
ds 2 ; COMfile length in bytes
end