mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
1043 lines
23 KiB
Plaintext
1043 lines
23 KiB
Plaintext
;
|
||
; PROGRAM NAME: SUB
|
||
; AUTHOR: RICHARD CONN (From SuperSUB Ver 1.1 by Ron Fowler)
|
||
; VERSION: 3.0
|
||
; DATE: 18 May 84
|
||
; PREVIOUS VERSIONS: 2.3 (6 Jan 83) - Called SUB2.ASM
|
||
; PREVIOUS VERSIONS: 2.2 (7 DEC 82), 2.1 (14 NOV 82), 2.0 (11 OCT 82)
|
||
; PREVIOUS VERSIONS: 1.4 (10 OCT 81), 1.3 (7 OCT 81)
|
||
; PREVIOUS VERSIONS: 1.2 (5 OCT 81), 1.1 (3 OCT 81), 1.0 (1 OCT 81)
|
||
; NOTE: FOR USE WITH ZCPR3
|
||
;
|
||
VERS EQU 30
|
||
z3env SET 0f400h
|
||
|
||
;
|
||
; SUB is derived from Ron's SuperSUB program; it provides a different
|
||
; format for the command line, a command-search hierarchy like ZCPR3, a
|
||
; resetting of the DMA address, several additional functions, and there are
|
||
; several other additions/changes. Additionally, ZCPR3-specific enhancements,
|
||
; such as appending the rest of the multiple command line to the command file
|
||
; and allowing multiple commands on a single line, are permitted.
|
||
;
|
||
; SuperSUB, VERSION 1.1 (09/13/81) by Ron Fowler
|
||
; 2/18/81 (first written) WESTLAND, MICH.
|
||
;
|
||
;
|
||
; This program is intended as a replacement for the
|
||
; SUBMIT program provided with CP/M. It provides sev-
|
||
; eral new facilities:
|
||
; 1) Nestable SUBMIT runs
|
||
; 2) Interactive entry of SUBMIT job (no need
|
||
; to use an editor for simple SUBMIT runs)
|
||
; 3) Command line entry of small SUBMIT jobs
|
||
; 4) Ability to enter blank lines in an edited
|
||
; SUBMIT file
|
||
; 5) User customization of number of parameters
|
||
; and drive to send $$$.SUB to
|
||
;
|
||
|
||
;
|
||
; DEFINE BOOLEANS
|
||
;
|
||
FALSE EQU 0
|
||
TRUE EQU NOT FALSE
|
||
|
||
;
|
||
; -- User customizable options --
|
||
;
|
||
|
||
FORCE$SUB EQU FALSE ;TRUE IF SUBMITTED FILE MUST BE OF TYPE .SUB
|
||
TIME$CONST EQU 0C000H ;DELAY FOR RINGING BELL
|
||
NPAR EQU 10 ;NUMBER OF ALLOWABLE PARAMETERS
|
||
CPBASE EQU 0 ;SET TO 4200H FOR HEATH CP/M
|
||
OPT EQU '/' ;OPTION DELIMITER CHAR
|
||
PDELIM EQU '$' ;PARAMETER DELIMITER
|
||
|
||
;
|
||
; SYSLIB AND Z3LIB ROUTINES
|
||
;
|
||
EXT Z3INIT,PFIND,GETCL1
|
||
EXT LOGUD,GETUD,PUTUD
|
||
EXT INITFCB
|
||
EXT PSTR,PRINT,QPRINT,COUT,CRLF,CAPS,PHLDC
|
||
EXT CODEND
|
||
|
||
;
|
||
; CP/M DEFINITIONS
|
||
;
|
||
FGCHAR EQU 1 ;GET CHAR FUNCTION
|
||
DIRIOF EQU 6 ;DIRECT CONSOLE I/O
|
||
RDBUF EQU 10 ;READ CONSOLE BUFFER
|
||
LOGIN EQU 14 ;LOG IN DISK
|
||
OPENF EQU 15 ;OPEN FILE FUNCTION
|
||
CLOSEF EQU 16 ;CLOSE FILE FUNCTION
|
||
DELETF EQU 19 ;DELETE FILE FUNCTION
|
||
READF EQU 20 ;READ RECORD FUNCTION
|
||
WRITEF EQU 21 ;WRITE RECORD FUNCTION
|
||
MAKEF EQU 22 ;MAKE (CREATE) FILE FUNCTION
|
||
GETDSK EQU 25 ;RETURN CURRENT DISK
|
||
SETDMA EQU 26 ;SET DMA ADDRESS
|
||
UCODE EQU 32 ;GET/SET USER CODE
|
||
;
|
||
UDFLAG EQU CPBASE+4
|
||
BDOS EQU CPBASE+5
|
||
;
|
||
CURIND EQU '$' ;CURRENT USER/DISK INDICATOR
|
||
FCB EQU 5CH ;DEFAULT FILE CONTROL BLOCK
|
||
FCBEX EQU 12 ;FCB OFFSET TO EXTENT FIELD
|
||
FCBRC EQU 15 ;FCB OFFSET TO RECORD COUNT
|
||
FCBNR EQU 32 ;FCB OFFSET TO NEXT RECORD
|
||
FN EQU 1 ;FCB OFFSET TO FILE NAME
|
||
FT EQU 9 ;FCB OFFSET TO FILE TYPE
|
||
TBUF EQU CPBASE+80H ;DEFAULT BUFFER
|
||
TPA EQU CPBASE+100H ;TRANSIENT PROGRAM AREA
|
||
;
|
||
PUTCNT EQU TBUF ;COUNTER FOR OUTPUT CHARS
|
||
;
|
||
; DEFINE SOME TEXT CHARACTERS
|
||
;
|
||
CTRLC EQU 'C'-'@'
|
||
CTRLZ EQU 'Z'-'@'
|
||
BEL EQU 7 ;RING BELL
|
||
CR EQU 13 ;CARRIAGE RETURN
|
||
LF EQU 10 ;LINE FEED
|
||
TAB EQU 9
|
||
|
||
;
|
||
; 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 IN CASE
|
||
DAD SP ; ONLY HELP REQUESTED
|
||
SHLD SPSAVE ;(NOT OTHERWISE USED)
|
||
CALL PUTUD ;SAVE HOME DIR
|
||
CALL QPRINT
|
||
DB 'SUB Version ',VERS/10+'0','.',(VERS MOD 10)+'0',0
|
||
|
||
CALL CODEND ;SET UP EXTERNAL BUFFERS
|
||
SHLD CLBUF ;SET PTR
|
||
MVI M,128 ;ALLOW 128 CHARS
|
||
LXI D,100H ;FREE SPACE
|
||
DAD D ;PT TO FREE AREA
|
||
SHLD FREMEM ;SET PTR TO FREE MEMORY AREA
|
||
SPHL ;SET STACK PTR
|
||
|
||
LDA FCB+1 ;ANYTHING ON CMD LINE?
|
||
CPI ' '
|
||
JZ HELP ;NO, GO PRINT HELP
|
||
CALL INITVAR ;INITIALIZE THE VARIABLE AREA
|
||
CALL GETPAR ;GET COMMAND LINE PARAMETERS AND EXTRACT OPTION
|
||
CALL ABORT ;PERFORM ABORT IF FLAG SET
|
||
CALL SETUP ;SET UP READ OF SUBMIT FILE
|
||
CALL RDFILE ;READ THE SUBMIT FILE
|
||
CALL WRSET ;SET UP WRITE OF "$$$.SUB"
|
||
CALL WRSUB ;WRITE "$$$.SUB"
|
||
JMP CPBASE ;GO START THE SUBMIT
|
||
;
|
||
; SETUP SETS UP THE FILE CONTROL BLOCK
|
||
; FOR READING IN THE .SUB TEXT FILE
|
||
;
|
||
SETUP:
|
||
LXI H,FCB+FT ;LOOK AT FIRST CHAR OF
|
||
MOV A,M ;FILE TYPE. IF IT IS
|
||
CPI ' ' ;BLANK, THEN GO MOVE
|
||
JZ PUTSUB ;"SUB" INTO FT FIELD
|
||
|
||
IF FORCE$SUB ;FILE TYPE MUST BE OF .SUB
|
||
LXI D,SUBTYP ;FILE TYPE MUST BE .SUB
|
||
MVI B,3 ;3 BYTES
|
||
CALL COMPAR
|
||
JNZ NOTFND ;FILE NOT FOUND IF NO TYPE MATCH
|
||
ENDIF
|
||
|
||
RET ; IF NOT BLANK, THEN ACCEPT ANY FILE TYPE
|
||
;
|
||
; MOVE "SUB" INTO THE FILE TYPE
|
||
;
|
||
PUTSUB:
|
||
XCHG ;BY CONVENTION, MOVE FROM
|
||
LXI H,SUBTYP ; @HL TO @DE
|
||
MVI B,3
|
||
CALL MOVE
|
||
RET
|
||
;
|
||
; MOVE # BYTES IN B REGISTER FROM @HL TO @DE
|
||
;
|
||
MOVE:
|
||
MOV A,M ;PICK UP
|
||
STAX D ;PUT DOWN
|
||
INX H ;I'M SURE
|
||
INX D ; YOU'VE SEEN THIS
|
||
DCR B ; BEFORE...
|
||
JNZ MOVE ;100 TIMES AT LEAST
|
||
RET ;I KNOW I HAVE!
|
||
;
|
||
; GETPAR MOVES THE SUBSTITUTION PARAMETERS SPECIFIED
|
||
; IN THE COMMAND LINE INTO MEMORY, AND STORES THEIR
|
||
; ADDRESSES IN THE PARAMETER TABLE. THIS ALLOWS
|
||
; SUBSTITUTION OF $1, $2, ETC., IN THE SUBMIT COMMANDS
|
||
; WITH THEIR ACTUAL VALUES SPECIFED IN THE COMMAND
|
||
; LINE.
|
||
;
|
||
GETPAR:
|
||
XRA A ;A=0
|
||
STA AFLAG ;TURN OFF ABORT COMMAND
|
||
LXI H,TBUF+1 ;WHERE WE FIND THE COMMAND TAIL
|
||
CALL SCANTO ;SKIP SUBMIT FILE NAME
|
||
STA OPTION ;FIRST CHAR OF CMD LINE IS OPTION
|
||
RC ;LINE ENDED?
|
||
CPI OPT ;NO, CHECK OPTION
|
||
JNZ GLP0 ;NOT KEYBOARD INP, READ FILE
|
||
INX H ;POINT PAST '/'
|
||
MOV A,M ;GET OPTION CHAR
|
||
CPI 'A' ;ABORT COMMAND
|
||
JZ GPARABT
|
||
CPI 'I' ;INTERACTIVE MODE
|
||
RZ ;RETURN IF SO
|
||
JMP HELP ;HELP OTHERWISE
|
||
GPARABT:
|
||
MVI A,0FFH ;TURN ON ABORT FLAG
|
||
STA AFLAG
|
||
INX H ;GET POSSIBLE BELL OPTION
|
||
MOV A,M
|
||
CPI 'B' ;BELL OPTION
|
||
RNZ
|
||
MVI A,0FFH ; SET BELL FLAG
|
||
STA BELL$FLAG
|
||
RET
|
||
GLP0:
|
||
MOV A,M ;INPUT IS FROM A .SUB FILE..THIS
|
||
INX H ; CODE SKIPS OVER THE NAME OF
|
||
ORA A ; THE SUB FILE TO GET TO THE
|
||
RZ ; COMMAND LINE PARAMETERS
|
||
CPI ' '
|
||
JZ GLP
|
||
CPI TAB
|
||
JNZ GLP0
|
||
GLP:
|
||
CALL SCANTO ;PASS UP THE BLANKS
|
||
RC ;CY RETURNED IF END OF CMD LINE
|
||
CALL PUTPAR ;NOW PUT THE PARAMETER INTO MEM
|
||
RC ;CY RETURNED IF END OF CMD LINE
|
||
JMP GLP ;GET THEM ALL
|
||
;
|
||
; SCANTO SCANS PAST BLANKS TO THE FIRST NON-BLANK. IF
|
||
; END OF COMMAND LINE FOUND, RETURNS CARRY SET.
|
||
;
|
||
SCANTO:
|
||
MOV A,M
|
||
INX H
|
||
ORA A ;SET FLAGS ON ZERO
|
||
STC ;IN CASE ZERO FOUND (END OF CMD LIN)
|
||
RZ
|
||
CPI ' '
|
||
JZ SCANTO ;SCAN PAST BLANKS
|
||
CPI TAB ;DO TABS TOO, JUST FOR
|
||
JZ SCANTO ; GOOD MEASURE
|
||
DCX H ;FOUND CHAR, POINT BACK TO IT
|
||
ORA A ;INSURE CARRY CLEAR
|
||
RET
|
||
;
|
||
; PUTPAR PUTS THE PARAMETER POINTED TO BY HL INTO
|
||
; MEMORY POINTED TO BY "TXTPTR". ALSO STORES THE
|
||
; ADDRESS OF THE PARAMETER INTO THE PARAMETER TABLE
|
||
; FOR EASY ACCESS LATER, WHEN WE WRITE $$$.SUB
|
||
;
|
||
PUTPAR:
|
||
PUSH H ;SAVE POINTER TO PARM
|
||
LHLD TXTPTR ;NEXT FREE MEMORY
|
||
XCHG ; INTO DE
|
||
LHLD TBLPTR ;NEXT FREE AREA OF TABLE
|
||
MOV A,M ;NON-ZERO IN TABLE
|
||
ORA A ; INDICATES TABLE
|
||
JNZ PAROVF ; TABLE OVERFLOW (TOO MANY PARMS)
|
||
MOV M,E ;STORE THE PARM ADRS
|
||
INX H
|
||
MOV M,D
|
||
INX H
|
||
SHLD TBLPTR ;SAVE TABLE PNTR FOR NEXT TIME
|
||
POP H ;GET BACK PARM POINTER
|
||
PUSH D ;SAVE FREE MEM POINTER BECAUSE
|
||
; WE WILL HAVE TO HAVE IT BACK
|
||
; LATER TO STORE THE LENGTH
|
||
INX D ;POINT PAST LENGTH STORAGE
|
||
MVI B,0 ;INITIALIZE LENGTH OF PARM
|
||
PPLP:
|
||
MOV A,M ;GET NEXT BYTE OF PARM
|
||
INX H
|
||
ORA A ;TEST FOR END OF CMD LINE
|
||
JZ PP2 ;JUMP IF END
|
||
CPI ' ' ;TEST FOR END OF COMMAND
|
||
JZ PP2
|
||
CPI TAB ;TAB ALSO ENDS COMMAND
|
||
JZ PP2
|
||
STAX D ;PUT PARAMETER BYTE-BY-BYTE
|
||
INX D ;INTO FREE MEMORY
|
||
INR B ;BUMP LENGTH
|
||
JMP PPLP
|
||
PP2:
|
||
XCHG
|
||
SHLD TXTPTR ;NEW FREE MEMORY POINTER
|
||
POP H ;REMEMBER OUR LENGTH POINTER?
|
||
MOV M,B ;STORE THE LENGTH
|
||
XCHG ;HAVE TO RETN HL > CMD LINE
|
||
ORA A ;NOW RETURN END OF LINE FLAG
|
||
STC
|
||
RZ ;RETURN CY IF ZERO (EOL MARK)
|
||
CMC
|
||
RET
|
||
;
|
||
;
|
||
; ABORT CHECKS TO SEE IF THE ABORT FLAG IS SET AND
|
||
; EXECUTES THE ABORT FUNCTION IF SO
|
||
;
|
||
;
|
||
ABORT:
|
||
LDA AFLAG ;GET THE FLAG
|
||
ORA A ;0=NO
|
||
RZ
|
||
CALL PRINT
|
||
DB CR,LF,' Strike ^C to Abort Command File - ',0
|
||
CALL CHARINB ;GET RESPONSE
|
||
CPI CTRLC ;ABORT?
|
||
JNZ ABORT1 ;RETURN TO OPSYS
|
||
ABORT0:
|
||
LXI D,SUBFCB ;DELETE SUBMIT FILE
|
||
MVI C,DELETF
|
||
CALL BDOS
|
||
CALL PRINT
|
||
DB ' ... Aborted',0
|
||
JMP CPBASE ;RETURN TO CP/M
|
||
ABORT1:
|
||
CALL PRINT
|
||
DB ' ... Continuing',0
|
||
JMP CPBASE ; RETURN TO CP/M
|
||
;
|
||
; INPUT CHAR FROM CON:; RING BELL EVERY SO OFTEN IF FLAG SET
|
||
;
|
||
CHARINB:
|
||
LDA BELL$FLAG ; GET FLAG
|
||
ORA A ; 0=NO
|
||
JZ CHARIN
|
||
PUSH H ; SAVE HL
|
||
CHARINB$LOOP:
|
||
LXI H,TIME$CONST ; GET TIME CONSTANT
|
||
CHARINB$LOOP1:
|
||
XTHL ; LONG DELAY
|
||
XTHL
|
||
DCX H ; COUNT DOWN
|
||
MOV A,H
|
||
ORA L
|
||
JNZ CHARINB$LOOP1
|
||
MVI E,0FFH ; REQUEST STATUS
|
||
MVI C,DIRIOF ; DIRECT I/O
|
||
CALL BDOS
|
||
ORA A ; ANY INPUT?
|
||
JNZ CHARINB$DONE
|
||
MVI E,BEL ; RING BELL
|
||
MVI C,DIRIOF
|
||
CALL BDOS
|
||
JMP CHARINB$LOOP
|
||
CHARINB$DONE:
|
||
POP H ; RESTORE HL
|
||
JMP CAPS ; CAPITALIZE CHAR
|
||
|
||
;
|
||
; INPUT CHAR FROM CON:; CAPITALIZE IT AND ECHO <CRLF>
|
||
;
|
||
CHARIN:
|
||
MVI C,FGCHAR ;GET CHAR
|
||
CALL BDOS
|
||
JMP CAPS ;CAPITALIZE
|
||
;
|
||
; RDFILE READS THE .SUB FILE SPECIFIED
|
||
; IN THE SUBMIT COMMAND INTO MEMORY
|
||
;
|
||
RDFILE:
|
||
LXI H,0 ;INIT LINE NUMBER
|
||
SHLD LINNUM
|
||
LDA OPTION ;USING A FILE?
|
||
CPI OPT ;OPT OPTION TELLS
|
||
JNZ RDFILE1 ;JUMP IF NOT
|
||
CALL PRINT
|
||
DB CR,LF,' Input Command Lines',0
|
||
CALL CLFILL ;GET FIRST LINE
|
||
JMP LINE
|
||
RDFILE1:
|
||
CALL PRINT
|
||
DB CR,LF,' Processing SUB File',0
|
||
|
||
; CHECK FOR .SUB FILE IN CURRENT USER/CURRENT DISK
|
||
LXI D,FCB ;WE ARE, OPEN IT
|
||
CALL INITFCB ;INIT FCB
|
||
MVI A,0FFH ;SEARCH CURRENT ALSO
|
||
CALL PFIND ;LOOK FOR FILE
|
||
JZ NOTFND ;FILE NOT FOUND
|
||
CALL LOGUD ;LOG INTO DIRECTORY
|
||
LXI D,FCB ;PT TO FCB
|
||
MVI C,OPENF ;OPEN FILE
|
||
CALL BDOS
|
||
CALL FILL ;READ FIRST BLOCK
|
||
JNZ NOTEXT ;EMPTY FILE
|
||
LINE:
|
||
LHLD LINNUM ;BUMP LINE NUMBER
|
||
INX H
|
||
SHLD LINNUM
|
||
LHLD PREV ;GET PREV PREVIOUS LINE POINTER
|
||
XCHG
|
||
LHLD TXTPTR ;GET CURRENT FREE MEM POINTER
|
||
SHLD PREV ;MAKE IT THE PREV LINE (FOR NXT PASS)
|
||
MOV M,E ;STORE AT BEGIN OF CURRENT LINE,
|
||
INX H ; A POINTER TO THE PREVIOUS
|
||
MOV M,D
|
||
INX H
|
||
PUSH H ;LATER WE WILL PUT LENGTH HERE
|
||
INX H ;SKIP PAST LENGTH
|
||
MVI C,0 ;INITIALIZE LENGTH TO ZERO
|
||
LLP:
|
||
CALL GNB ;GET NEXT BYTE FROM INPUT SOURCE
|
||
CPI CTRLZ ;END OF FILE?
|
||
JZ EOF ;CY SET IF END OF FILE FOUND
|
||
ANI 7FH ;MASK OUT MSB
|
||
CALL CAPS ;CONVERT TO UPPER CASE
|
||
CPI LF ;IGNORE LINEFEEDS
|
||
JZ LLP
|
||
CPI CR ;IF IT'S A CARRIAGE RETURN,
|
||
JZ EOL ; THEN DO END OF LINE
|
||
MOV M,A ;STORE ALL OTHERS INTO MEMORY
|
||
INX H
|
||
CALL SIZE ;MAKE SURE NO MEMORY OVERFLOW
|
||
INR C ;BUMP CHAR COUNT
|
||
JM LENERR ;MAX OF 128 CHARS PER LINE
|
||
JMP LLP ;GO DO NEXT CHAR
|
||
;
|
||
; DO END OF LINE SEQUENCE
|
||
;
|
||
EOL:
|
||
SHLD TXTPTR ;SAVE FREE MEMORY POINTER
|
||
POP H ;CURRENT LINE'S LENGTH POINTER
|
||
MOV M,C ;STORE LENGTH AWAY
|
||
JMP LINE ;GO DO NEXT LINE
|
||
;
|
||
; END OF TEXT FILE
|
||
;
|
||
EOF:
|
||
SHLD TXTPTR ;SAVE FREE MEMORY POINTER
|
||
PUSH B ;SAVE LINE LENGTH
|
||
CALL ZMCL ;LOAD REST OF COMMAND LINE
|
||
POP B ;RESTORE LINE LENGTH
|
||
POP H ;CURRENT LINE'S LENGTH POINTER
|
||
MOV M,C ;STORE LENGTH AWAY
|
||
RET ;ALL DONE READING SUB FILE
|
||
;
|
||
; COPY COMMAND LINE INTO MEMORY BUFFER
|
||
;
|
||
ZMCL:
|
||
CALL GETCL1 ;GET ADDRESS OF COMMAND LINE BUFFER
|
||
MOV A,H ;CHECK FOR ANY
|
||
ORA L
|
||
RZ
|
||
LHLD LINNUM ;BUMP LINE NUMBER
|
||
INX H
|
||
SHLD LINNUM
|
||
LHLD PREV ;GET PREV PREVIOUS LINE POINTER
|
||
XCHG
|
||
LHLD TXTPTR ;GET CURRENT FREE MEM POINTER
|
||
SHLD PREV ;MAKE IT THE PREV LINE (FOR NXT PASS)
|
||
MOV M,E ;STORE AT BEGIN OF CURRENT LINE,
|
||
INX H ; A POINTER TO THE PREVIOUS
|
||
MOV M,D
|
||
INX H
|
||
PUSH H ;LATER WE WILL PUT LENGTH HERE
|
||
INX H ;SKIP PAST LENGTH
|
||
MVI C,0 ;INITIALIZE LENGTH TO ZERO
|
||
XCHG ;DE PTS TO NEXT PLACE TO STORE A BYTE
|
||
CALL GETCL1 ;GET ADDRESS OF COMMAND LINE BUFFER
|
||
MOV A,M ;GET LOW
|
||
INX H
|
||
MOV H,M ;GET HIGH
|
||
MOV L,A ;HL PTS TO FIRST BYTE OF MULTIPLE COMMAND LINE
|
||
MOV B,M ;GET FIRST CHAR IN LINE
|
||
MVI M,0 ;CLEAR LINE
|
||
MOV A,B ;CHECK TO SEE IF FIRST CHAR IS A SEMICOLON (CMD SEP)
|
||
CPI ';'
|
||
JNZ ZMCL0
|
||
INX H ;PT TO 2ND CHAR
|
||
MOV A,M ;FIRST WAS A SEMICOLON, SO GET SECOND
|
||
ZMCL0:
|
||
XCHG ;HL PTS TO NEXT BUFFER SPACE, DE PTS TO MC LINE
|
||
JMP ZMCL1A ;A=FIRST CHAR IN MC LINE
|
||
;
|
||
; MAJOR LOOP TO STORE MULTIPLE COMMAND LINE
|
||
;
|
||
ZMCL1:
|
||
LDAX D ;GET NEXT BYTE FROM MULTIPLE COMMAND LINE
|
||
ZMCL1A:
|
||
ORA A ;0=EOL
|
||
JZ ZMCL2
|
||
ANI 7FH ;MASK OUT MSB
|
||
CALL CAPS ;CONVERT TO UPPER CASE
|
||
MOV M,A ;STORE CHAR INTO MEMORY
|
||
INX H ;PT TO NEXT CHAR
|
||
INX D
|
||
CALL SIZE ;MAKE SURE NO MEMORY OVFL
|
||
INR C ;INCR CHAR COUNT
|
||
JM LENERR ;MAX OF 128 CHARS IN LINE
|
||
JMP ZMCL1
|
||
;
|
||
; DONE WITH INPUT OF MULTIPLE COMMAND LINE -- SAVE CHAR CNT AND SET PTR
|
||
;
|
||
ZMCL2:
|
||
SHLD TXTPTR ;SAVE PTR
|
||
POP H ;PT TO CHAR COUNT POSITION
|
||
MOV M,C ;STORE CHAR COUNT
|
||
RET
|
||
|
||
;
|
||
; GET NEXT BYTE FROM INPUT FILE OR USER
|
||
;
|
||
GNB:
|
||
PUSH H ;DON'T ALTER ANYBODY
|
||
PUSH D
|
||
PUSH B
|
||
LDA OPTION ;INPUT FROM .SUB FILE?
|
||
CPI OPT ;TOLD BY ORIG CMD LINE OPTION
|
||
JNZ GNBDISK ;GET NEXT CHAR FROM DISK BUFFER IF NOT FROM USER
|
||
CALL GNBKBD ;GET A BYTE FROM KBD INPUT
|
||
JMP GNBXIT ;THEN LEAVE
|
||
;
|
||
; GET NEXT BYTE FROM DISK FILE
|
||
;
|
||
GNBDISK:
|
||
LDA IBP ;GET BUFFER POINTER
|
||
CPI 128 ;NEED ANOTHER BLOCK FROM DISK?
|
||
JC GNBD1 ;CONTINUE
|
||
CALL FILL ;GET NEXT BLOCK
|
||
JZ GNBD1 ;CONTINUE IF NOT EMPTY
|
||
CALL GETUD ;RETURN HOME
|
||
MVI A,1AH ;FAKE EOF
|
||
JMP GNBXIT
|
||
GNBD1:
|
||
MOV E,A ;PUT OFFSET IN DE
|
||
MVI D,0
|
||
INR A ;POINT TO NEXT BYTE
|
||
STA IBP ;SAVE FOR NEXT
|
||
LXI H,TBUF ;NOW OFFSET INTO BUFFER
|
||
DAD D
|
||
MOV A,M ;GET CHAR
|
||
GNBXIT:
|
||
POP B ;RESTORE EVERYBODY
|
||
POP D
|
||
POP H
|
||
ORA A ;TURN ON CARRY
|
||
RET
|
||
;
|
||
; FILL INPUT BUFFER FROM DISK
|
||
;
|
||
FILL:
|
||
XRA A ;CLEAR INPUT BUFFER PTR
|
||
STA IBP
|
||
LXI D,FCB ;PT TO FCB
|
||
MVI C,READF ;BDOS READ BLOCK FUNCTION
|
||
CALL BDOS
|
||
ORA A ;RETURN Z IF EOF
|
||
MVI A,0 ;SET PTR TO FIRST CHAR
|
||
RET
|
||
;
|
||
; GET NEXT BYTE FROM USER (KEYBOARD INPUT)
|
||
;
|
||
GNBKBD:
|
||
LHLD CLPTR ;PT TO NEXT CHAR
|
||
MOV A,M ;GET IT
|
||
INX H ;PT TO FOLLOWING
|
||
SHLD CLPTR ;RESET PTR
|
||
CPI CR ;END OF LINE?
|
||
RNZ
|
||
CALL CLFILL ;GET NEW LINE
|
||
JZ GKEND ;EMPTY LINE INPUT - RETURN EOF
|
||
MVI A,CR ;RETURN CR TO INDICATE END OF LINE
|
||
RET
|
||
GKEND:
|
||
MVI A,1AH ;RETURN EOF
|
||
RET
|
||
;
|
||
; FILL THE COMMAND LINE FROM THE USER
|
||
;
|
||
CLFILL:
|
||
CALL PRINT
|
||
DB CR,LF,' Command Line? ',0
|
||
LHLD CLBUF ;NOW FILL THE BUFFER
|
||
XCHG ;...DE PTS TO IT
|
||
MVI C,RDBUF
|
||
CALL BDOS
|
||
LHLD CLBUF ;PT TO COMMAND LINE BUFFER
|
||
INX H
|
||
MOV A,M ;GET CHAR COUNT
|
||
INX H
|
||
SHLD CLPTR ;RESET THE COMMAND LINE PTR
|
||
ORA A ;SET ZERO FLAG
|
||
PUSH PSW ;SAVE A
|
||
ADD L ;PT TO AFTER LAST CHAR
|
||
MOV L,A
|
||
MOV A,H
|
||
ACI 0
|
||
MOV H,A
|
||
MVI M,CR ;SET EOL CHAR
|
||
POP PSW ;GET CHAR COUNT
|
||
RET
|
||
;
|
||
; MAKE SURE NO MEMORY OVERFLOW
|
||
;
|
||
SIZE:
|
||
LDA BDOS+2 ;HIGHEST PAGE POINTER
|
||
SUI 9 ;MAKE IT BE UNDER CCP
|
||
CMP H ;CHECK IT AGAINST CURRENT PAGE
|
||
RNC ;NC=ALL OKAY
|
||
JMP MEMERR ;OTHERWISE ABORT
|
||
;
|
||
; SET UP THE $$$.SUB FILE
|
||
; FOR WRITING
|
||
;
|
||
WRSET:
|
||
CALL PRINT
|
||
DB CR,LF,' Writing Command File to Disk',0
|
||
LXI D,SUBFCB
|
||
MVI C,OPENF
|
||
CALL BDOS ;OPEN THE FILE
|
||
INR A ;CHECK CPM RETURN
|
||
JZ NONE1 ;NONE EXISTS ALREADY
|
||
;
|
||
; $$$.SUB EXISTS, SO SET
|
||
; FCB TO APPEND TO IT
|
||
;
|
||
LDA SUBFCB+FCBRC ;GET RECORD COUNT
|
||
STA SUBFCB+FCBNR ;MAKE NEXT RECORD
|
||
RET
|
||
;
|
||
; COME HERE WHEN NO $$$.SUB EXISTS
|
||
;
|
||
NONE1:
|
||
LXI D,SUBFCB
|
||
MVI C,MAKEF
|
||
CALL BDOS
|
||
INR A
|
||
JZ NOMAKE ;0FFH=CAN'T CREATE FILE
|
||
RET
|
||
;
|
||
; WRITE THE "$$$.SUB" FILE
|
||
;
|
||
WRSUB:
|
||
LHLD PREV ;THIS CODE SCANS BACKWARD
|
||
MOV A,H ; THRU THE FILE STORED IN
|
||
ORA L ; MEMORY TO THE FIRST NON-
|
||
JZ NOTEXT ; NULL LINE. IF NONE IS
|
||
MOV E,M ; FOUND, ABORTS
|
||
INX H
|
||
MOV D,M ;HERE, WE PICK UP PNTR TO PREV LINE
|
||
INX H ;NOW WE POINT TO LENGTH
|
||
XCHG ;WE NEED TO STORE AWAY
|
||
SHLD PREV ; POINTER TO PREV LINE
|
||
XCHG
|
||
MOV A,M ;NOW PICK UP THE LENGTH
|
||
ORA A ;SET Z FLAG ON LENGTH
|
||
JNZ WRNTRY ;GOT LINE W/LENGTH: GO DO IT
|
||
LHLD LINNUM ;NOTHING HERE, FIX LINE NUMBER
|
||
DCX H ;(WORKING BACKWARD NOW)
|
||
SHLD LINNUM
|
||
JMP WRSUB
|
||
WRLOP:
|
||
LHLD PREV ;GET PREV LINE POINTER
|
||
MOV A,H
|
||
ORA L ;IF THERE IS NO PREV LINE
|
||
JZ CLOSE ; THEN WE ARE DONE
|
||
MOV E,M ;ELSE SET UP PREV FOR NEXT
|
||
INX H ; PASS THRU HERE
|
||
MOV D,M
|
||
INX H
|
||
XCHG ;NOW STORE IT AWAY
|
||
SHLD PREV
|
||
XCHG
|
||
WRNTRY:
|
||
CALL PUTLIN ;WRITE THE LINE TO THE FILE
|
||
LHLD LINNUM ;BUMP THE LINE NUMBER
|
||
DCX H ;DOWN (WORKING BACK NOW)
|
||
SHLD LINNUM
|
||
JMP WRLOP
|
||
;
|
||
; $$$.SUB IS WRITTEN, CLOSE THE FILE
|
||
;
|
||
CLOSE:
|
||
LXI D,SUBFCB
|
||
MVI C,CLOSEF
|
||
JMP BDOS
|
||
;
|
||
; THIS SUBROUTINE WRITES A LINE
|
||
; TO THE $$$.SUB FILE BUFFER,
|
||
; AND FLUSHES THE BUFFER AFTER
|
||
; THE LINE IS WRITTEN.
|
||
;
|
||
PUTLIN:
|
||
MOV A,M ;PICK UP LENGTH BYTE
|
||
INX H ;POINT PAST IT
|
||
STA GETCNT ;MAKE A COUNT FOR "GET"
|
||
SHLD GETPTR ;MAKE A POINTER FOR "GET"
|
||
LXI H,TBUF+1 ;TEXT GOES AFTER LENGTH
|
||
SHLD PUTPTR ;MAKE POINTER FOR "PUT"
|
||
XRA A ;INITIALIZE PUT COUNT
|
||
STA PUTCNT
|
||
MOV B,L ;COUNT FOR CLEAR LOOP
|
||
CLR:
|
||
MOV M,A ;ZERO OUT BUFFER LOC
|
||
INX H
|
||
INR B ;COUNT
|
||
JNZ CLR
|
||
;
|
||
; THIS LOOP COLLECTS CHARACTERS
|
||
; FROM THE LINE STORED IN MEMORY
|
||
; AND WRITES THEM TO THE FILE.
|
||
; IF THE "$" PARAMETER SPECIFIER
|
||
; IS ENCOUNTERED, PARAMETER SUB-
|
||
; STITUTION IS DONE
|
||
;
|
||
PUTLP:
|
||
CALL GETCHR ;PICK UP A CHARACTER
|
||
JC FLUSH ;CY = NO MORE CHAR IN LINE
|
||
CPI '^' ;CONTROL-CHAR TRANSLATE PREFIX?
|
||
JNZ NOTCX
|
||
CALL GETCHR ;YES, GET THE NEXT
|
||
JC CCERR ;ERROR: EARLY END OF INPUT
|
||
SUI '@' ;MAKE IT A CONTROL-CHAR
|
||
JC CCERR ;ERROR: TOO SMALL
|
||
CPI ' '
|
||
JNC CCERR ;ERROR: TOO LARGE
|
||
NOTCX:
|
||
CPI PDELIM ;PARAMETER SPECIFIER?
|
||
JNZ STOBYT ;IF NOT, JUST WRITE CHAR
|
||
LDA OPTION ;CHECK OPTION: '$' DOESN'T
|
||
CPI OPT ; COUNT IN OPT MODE
|
||
MVI A,PDELIM ;(RESTORE THE '$')
|
||
JZ STOBYT
|
||
CALL LKAHED ;PEEK AT NEXT CHAR
|
||
JC PARERR ;LINE ENDING MEANS PARAM ERR
|
||
CPI PDELIM ;ANOTHER "$"?
|
||
JNZ SUBS ;IF NOT THEN GO DO SUBSTITUTION
|
||
CALL GETCHR ;GET THE 2ND "$" (WE ONLY LOOKED
|
||
; AHEAD BEFORE)
|
||
STOBYT:
|
||
CALL PUTCHR ;WRITE CHAR TO FILE
|
||
JMP PUTLP
|
||
;
|
||
; PARAMETER SUBSTITUTION...LOOKS UP THE
|
||
; PARAMETER # AFTER THE "$" AND PLUGS IT
|
||
; IN IF IT EXISTS.
|
||
;
|
||
SUBS:
|
||
CALL NUMTST ;IT BETTER BE A NUMBER
|
||
JC PARERR ; OTHERWISE PARAM ERROR
|
||
MVI B,0 ;INITIALIZE PARM #
|
||
JMP LPNTRY ;WE JOIN LOOP IN PROGRESS...
|
||
SUBLP:
|
||
CALL LKAHED ;LOOK AT NEXT CHAR
|
||
JC DOSUBS ;IF LINE EMPTY, THEN PLUG IN PARM
|
||
CALL NUMTST ;CHECK FOR NUMERIC
|
||
JC DOSUBS ;DONE IF NOT
|
||
LPNTRY:
|
||
CALL GETCHR ;NOW REMOVE THE CHAR FROM INPUT STREAM
|
||
SUI '0' ;REMOVE ASCII BIAS
|
||
MOV C,A ;SAVE IT
|
||
MOV A,B ;OUR ACCUMULATED COUNT
|
||
ADD A ;MULTIPLY BY TEN
|
||
ADD A
|
||
ADD B
|
||
ADD A
|
||
ADD C ;THEN ADD IN NEW DIGIT
|
||
MOV B,A ;RESTORE COUNT
|
||
JMP SUBLP
|
||
;
|
||
; PERFORM THE SUBSTITUTION
|
||
;
|
||
DOSUBS:
|
||
MOV A,B ;GET PARM #
|
||
DCR A ;MAKE ZERO RELATIVE
|
||
JM PARERR ;OOPS
|
||
CALL LOOKUP ;LOOK IT UP IN PARM TABLE
|
||
JC PARERR ;IT'S NOT THERE
|
||
MOV B,A ;LENGTH IN B
|
||
SUBLP1:
|
||
INR B ;TEST B FOR ZERO
|
||
DCR B
|
||
JZ PUTLP ;DONE
|
||
MOV A,M ;GET CHAR OF REAL PARAMETER
|
||
INX H ;POINT PAST FOR NEXT TIME
|
||
PUSH H ;SAVE REAL PARM POINTER
|
||
CALL PUTCHR ;PUT IT IN THE FILE
|
||
POP H ;GET BACK REAL PARM POINTER
|
||
DCR B ;COUNTDOWN
|
||
JMP SUBLP1
|
||
;
|
||
; COME HERE WHEN A LINE IS FINISHED,
|
||
; AND WE NEED TO WRITE THE BUFFER TO DISK
|
||
;
|
||
FLUSH:
|
||
LXI D,SUBFCB
|
||
MVI C,WRITEF
|
||
CALL BDOS
|
||
ORA A
|
||
JNZ WRERR ;CPM RETURNED A WRITE ERROR
|
||
RET
|
||
;
|
||
; GETCHR GETS ONE CHAR FROM
|
||
; LINE STORED IN MEMORY
|
||
;
|
||
GETCHR:
|
||
LXI H,GETCNT
|
||
MOV A,M ;PICK UP COUNT
|
||
DCR A ;REMOVE THIS CHAR
|
||
STC ;PRESET ERROR
|
||
RM ;RETURN CY IF OUT OF CHARS
|
||
MOV M,A ;UPDATE COUNT
|
||
LHLD GETPTR ;CURRENT CHAR POINTER
|
||
MOV A,M ;PICK UP CHAR
|
||
INX H ;BUMP POINTER
|
||
SHLD GETPTR ;PUT IT BACK
|
||
CMC ;TURN CARRY OFF
|
||
RET
|
||
;
|
||
; PUTCHR PUTS ONE CHAR TO
|
||
; THE OUTPUT BUFFER
|
||
;
|
||
PUTCHR:
|
||
LXI H,PUTCNT
|
||
INR M ;INCREMENT COUNT
|
||
JM LENERR ;LINE WENT TO > 128 CHARS
|
||
LHLD PUTPTR ;GET BUFFER POINTER
|
||
ANI 7FH ;MASK OUT MSB
|
||
MOV M,A ;PUT CHAR THERE
|
||
INX H ;BUMP POINTER
|
||
SHLD PUTPTR ;PUT IT BACK
|
||
RET ;ALL DONE
|
||
;
|
||
; LOOK AHEAD ONE CHAR IN
|
||
; THE INPUT STREAM. SET
|
||
; CARRY IF NONE LEFT.
|
||
;
|
||
LKAHED:
|
||
LDA GETCNT
|
||
ORA A ;SEE IF COUNT IS DOWN TO ZERO
|
||
STC ;PRE SET INDICATOR
|
||
RZ
|
||
MOV A,M ;PICK UP CHAR
|
||
CMC ;TURN OFF CARRY FLAG
|
||
RET
|
||
;
|
||
; LOOK UP PARAMETER WITH NUMBER IN
|
||
; A REG. RETURN A=LENGTH OF PARM,
|
||
; AND HL => PARAMETER
|
||
;
|
||
LOOKUP:
|
||
CPI NPAR
|
||
JNC PAROVF ;PARM # TOO HIGH
|
||
MOV L,A
|
||
MVI H,0 ;NOW HAVE 16 BIT NUMBER
|
||
DAD H ;DOUBLE FOR WORD OFFSET
|
||
LXI D,TABLE
|
||
DAD D ;DO THE OFFSET
|
||
MOV E,M ;GET ADDRESS OF PARM
|
||
INX H
|
||
MOV D,M
|
||
MOV A,D ;ANYTHING THERE?
|
||
ORA E
|
||
JNZ LKUPOK
|
||
XRA A ;NO, ZERO LENGTH
|
||
RET
|
||
LKUPOK:
|
||
XCHG ;NOW IN DE
|
||
MOV A,M ;PICK UP LENGTH
|
||
INX H ;POINT PAST LENGTH
|
||
RET
|
||
;
|
||
; UTILITY COMPARE SUBROUTINE
|
||
;
|
||
COMPAR:
|
||
LDAX D
|
||
CMP M
|
||
RNZ
|
||
INX H
|
||
INX D
|
||
DCR B
|
||
JNZ COMPAR
|
||
RET
|
||
;
|
||
; NUMERIC TEST UTILITY SUBROUTINE
|
||
;
|
||
NUMTST:
|
||
CPI '0'
|
||
RC
|
||
CPI '9'+1
|
||
CMC
|
||
RET
|
||
;
|
||
; ERROR HANDLERS
|
||
;
|
||
WRERR:
|
||
CALL ERRXIT
|
||
DB 'Disk Full',0
|
||
NOMAKE:
|
||
CALL ERRXIT
|
||
DB 'Dir Full',0
|
||
MEMERR:
|
||
CALL ERRXIT
|
||
DB 'Mem Full',0
|
||
NOTFND:
|
||
CALL ERRXIT
|
||
DB 'SUB File Not Found',0
|
||
PARERR:
|
||
CALL ERRXIT
|
||
DB 'Param',0
|
||
PAROVF:
|
||
CALL ERRXIT
|
||
DB 'Too Many Params',0
|
||
LENERR:
|
||
CALL ERRXIT
|
||
DB 'Line too Long',0
|
||
NOTEXT:
|
||
CALL ERRXIT
|
||
DB 'SUB File Empty',0
|
||
CCERR:
|
||
CALL ERRXIT
|
||
DB 'Ctrl Char',0
|
||
ERRXIT:
|
||
CALL CRLF ;NEW LINE
|
||
POP H
|
||
CALL PSTR ;PRINT MESSAGE
|
||
CALL PRINT
|
||
DB ' Error on Line ',0
|
||
LHLD LINNUM ;TELL LINE NUMBER
|
||
CALL PHLDC
|
||
CALL CRLF
|
||
LXI D,SUBFCB ;DELETE THE $$$.SUB FILE
|
||
MVI C,DELETF
|
||
CALL BDOS
|
||
JMP CPBASE
|
||
;
|
||
; INITIALIZE ALL VARIABLES
|
||
;
|
||
INITVAR:
|
||
LXI H,VAR
|
||
LXI B,ENDVAR-VAR
|
||
INITLP:
|
||
MVI M,0 ;ZERO ENTIRE VAR AREA
|
||
INX H
|
||
DCX B
|
||
MOV A,B
|
||
ORA C
|
||
JNZ INITLP
|
||
LXI H,TABLE ;INIT PARM TABLE POINTER
|
||
SHLD TBLPTR
|
||
LXI H,0FFFFH ;MARK END OF TABLE
|
||
SHLD ENDTBL
|
||
LHLD FREMEM ;FREE MEMORY STARTS TXT AREA
|
||
SHLD TXTPTR
|
||
RET
|
||
;
|
||
; PRINT HELP WITH PROGRAM OPTIONS
|
||
;
|
||
HELP:
|
||
CALL PRINT
|
||
DB CR,LF,'Syntax:'
|
||
DB CR,LF,' SUB - Print this HELP Message'
|
||
DB CR,LF,' SUB /A <text> - Abort of SUBMIT File'
|
||
DB CR,LF,' SUB /AB <text> - Abort and Ring Bell'
|
||
DB CR,LF,' SUB /I<CR> - Go into Interactive mode'
|
||
DB CR,LF,' SUB <FILE> <PARMS> - Standard SUB File'
|
||
DB 0
|
||
LHLD SPSAVE ;RETURN TO OPSYS
|
||
SPHL
|
||
RET
|
||
;
|
||
; VARIABLE STORAGE
|
||
;
|
||
VAR EQU $
|
||
;
|
||
AFLAG:
|
||
DB 0 ;ABORT FLAG (0=NO)
|
||
TXTPTR:
|
||
DW 0 ;FREE MEMORY POINTER
|
||
TBLPTR:
|
||
DW 0 ;POINTER TO PARM TABLE
|
||
DUSER:
|
||
DB 0 ;DEFAULT USER NUMBER
|
||
LINNUM:
|
||
DW 0 ;CURRENT LINE NUMBER
|
||
PREV:
|
||
DW 0 ;POINTER TO PREV LINE
|
||
GETCNT:
|
||
DB 0 ;COUNTER FOR 'GET'
|
||
GETPTR:
|
||
DW 0 ;POINTER FOR 'GET'
|
||
PUTPTR:
|
||
DW 0 ;POINTER FOR 'PUT'
|
||
IBP:
|
||
DB 0 ;INPUT BUFFER POINTER
|
||
CLPTR:
|
||
DW 0 ;COMMAND LINE POINTER
|
||
BELL$FLAG:
|
||
DB 0 ;RING BELL ON ABORT FLAG
|
||
OPTION:
|
||
DB 0 ;OPT OPTION FLAG STORE
|
||
TABLE:
|
||
DS NPAR*3 ;PARAMETER TABLE
|
||
ENDTBL:
|
||
DW 0FFFFH ;END OF PARAMETER TABLE
|
||
;
|
||
ENDVAR EQU $
|
||
SPSAVE:
|
||
DW 0 ;STACK POINTER SAVE
|
||
;
|
||
;
|
||
; FCB FOR $$$.SUB
|
||
;
|
||
SUBFCB:
|
||
DB 1 ;DRIVE SPECIFIER (A SELECTED)
|
||
DB '$$$ '
|
||
SUBTYP:
|
||
DB 'SUB'
|
||
DW 0,0,0,0 ;INITIALIZE REST OF FCB
|
||
DW 0,0,0,0
|
||
DW 0,0,0,0
|
||
;
|
||
CLBUF: DS 2 ;PTR TO COMMAND LINE BUFFER
|
||
FREMEM: DS 2 ;PTR TO FREE MEMORY AREA
|
||
;
|
||
END
|
||
|
||
|