home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol067
/
sub.asm
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
22KB
|
885 lines
;
;
;************************************************
;* EXTENDED SUBMIT FOR *
;* CP/M AND MP/M *
;************************************************
;
; REVISED 12/22/81 :added code to so supersub would work under mp/m
; and cp/m. George Gary
;
; REVISED 09/13/81 (RGF): added control character translation
; fixed bug in line number reporting
;
; VERSION 1.1 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
;
; For full details along with examples, see the ac-
; companying documentation file.
; --Ron Fowler
;
;
; DEFINE BOOLEANS
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
;************************************************************
;
; -- User customizable options --
;
NPAR EQU 10 ;NUMBER OF ALLOWABLE PARAMETERS
SUBDRV EQU 1 ;MAKE 0 FOR DFLT, 1,2,3,ETC FOR A,B,C
QUIET EQU FALSE ;SET TO TRUE TO ELIMATE SIGN-ON MSG
CPBASE EQU 0 ;SET TO 4200H FOR HEATH CP/M
;
;
;
;************************************************************
;
; CP/M DEFINITIONS
;
FPCHAR EQU 2 ;PRINT CHAR FUNCTION
PRINTF EQU 9 ;PRINT STRING FUNCTION
RDBUF EQU 10 ;READ CONSOLE BUFFER
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
;
BDOS EQU CPBASE+5
;
FCB EQU 5CH ;DEFAULT FILE CONTROL BLOCK
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
;
CR EQU 13 ;CARRIAGE RETURN
LF EQU 10 ;LINE FEED
TAB EQU 9
;
; START OF PROGRAM CODE
;
ORG TPA
;
; GET THE BALL ROLLING
;
SUBMIT: LXI H,0 ;SAVE STACK IN CASE
DAD SP ; ONLY HELP REQUESTED
SHLD SPSAVE ;(NOT OTHERWISE USED)
LXI SP,STACK
CALL START
;
; SIGN ON MESSAGE
;
IF NOT QUIET
DB 'SuperSUB V1.1'
ENDIF
;
DB CR,LF,'$' ;NEWLINE EVEN IF QUIET
;
START:
POP D ;RETRIEVE STRING POINTER
MVI C,PRINTF
LDA FCB+1 ;ANYTHING ON CMD LINE?
CPI ' '
JZ HELP ;NO, GO PRINT HELP
CALL BDOS ;PRINT THE SIGN-ON
CALL INITVAR ;INITIALIZE THE VARIABLE AREA
CALL GETPAR ;GET COMMAND LINE PARAMETERS
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
LXI D,SUBTYP ;IT'S NOT BLANK SO MAKE
MVI B,3 ; SURE IT'S ALREADY
CALL COMPAR ; "SUB"
JNZ NOTFND ;IF NOT, IT'S AN ERROR
RET
;
; 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: 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 '/' ;NO, CHECK OPTION
JNZ GLP0 ;NOT KEYBOARD INP, READ FILE
INX H ;POINT PAST '/'
SLSCAN: SHLD CLPTR ;SAVE CMD LINE PTR
MOV A,M ;KBD IS SOURCE, GET EOL FLAG
STA CLFLAG ;SAVE AS EOL FLAG
CPI ' ' ;ALLOW SPACES AFTER '/'
RNZ ;GOT NON-BLANK, DONE
INX H ;ELSE CONTINUE SCAN
JMP SLSCAN
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
;
; 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 '/' ;'/' OPTION TELLS
JZ LINE ;JUMP IF NOT
LXI D,FCB ;WE ARE, OPEN IT
MVI C,OPENF
CALL BDOS
INR A ;IF 0FFH RETURNED,
JZ NOTFND ; THEN FILE NOT FOUND
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
JC EOF ;CY SET IF END OF FILE FOUND
CALL UCASE ;CONVERT TO UPPER CASE
CPI 1AH ;SEE IF CPM END OF FILE INDICATOR
JZ EOF
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
POP H ;CURRENT LINE'S LENGTH POINTER
MOV M,C ;STORE LENGTH AWAY
RET ;ALL DONE READING SUB FILE
;
; GET NEXT BYTE FROM INPUT FILE
;
GNB: PUSH H ;DON'T ALTER ANYBODY
PUSH D
PUSH B
LDA OPTION ;INPUT FROM .SUB FILE?
CPI '/' ;TOLD BY ORIG CMD LINE OPTION
JNZ NSLASH ;JUMP IF WE ARE
CALL GNBKBD ;NO, GET A BYTE FROM KBD INPUT
JMP GNBXIT ;THEN LEAVE
NSLASH: LDA IBP ;GET BUFFER POINTER
ORA A ;PAST END?
CM FILL ;WRAPPED AROUND
JNC GNB1 ;NO END OF FILE
MVI A,1AH ;FAKE EOF
GNB1: MOV E,A ;PUT IN DE
MVI D,0
INR A ;POINT TO NEXT
STA IBP ;PUT AWAY
LXI H,TBUF ;NOW OFFSET INTO BUFR
DAD D
MOV A,M ;GET CHAR THERE
GNBXIT: POP B ;RESTORE EVERYBODY
POP D
POP H
ORA A ;TURN ON CARRY
RET
;
; FILL INPUT BUFFER
;
FILL: MVI C,READF
LXI D,FCB
CALL BDOS
ORA A ;GOT GOOD READ?
MVI A,0 ;(NEW BUF PTR)
STC
RNZ ;RETN CY=EOF
CMC ;NO EOF, NO CY
RET
;
; COME HERE TO GET A .SUB CHARACTER WHEN
; WE'RE NOT USING A .SUB FILE ("/" OPTION)
;
GNBKBD: LDA CLFLAG ;USE CP/M CMD LINE?
ORA A
JNZ GNBCL ;THEN GO DO IT
LDA CLCNT ;NOT, CHECK LOCAL
ORA A ; CMD LINE CHAR COUNT
CM CLFILL ;REFILL WHEN IT WRAPS BACK
JC GKEND ;GOT CARRY (FROM CLFILL), RETURN EOF
DCR A ;COUNT DOWN
STA CLCNT
JP GNBCL ;IF PLUS, BUFFER NOT EMPTY
MVI A,CR ;OUT OF CHARS, RETURN A CR
RET
GKEND: MVI A,1AH ;RETURN EOF
RET
;
; GET NEXT BYTE OF INPUT FROM CMD LINE @CLPTR
;
GNBCL: LHLD CLPTR ;LOAD THE POINTER
MOV A,M ;GET THE CHAR
INX H ;BUMP POINTER FOR NEXT TIME
SHLD CLPTR
CPI ';' ;LOGICAL END-OF-LINE?
JNZ NSEMI ;JUMP IF NOT
MVI A,CR ;YES, TRANSLATE IT
RET
NSEMI: ORA A ;PHYSICAL END-OF-LINE
RNZ ;THIS ONLY NEEDED WHEN INPUT
; SOURCE IS ORIG CPM CMD LINE
MVI A,1AH ;TRANSLATE THAT TO END OF FILE
RET
;
; SUBROUTINE TO RE-FILL THE LOCAL COMMAND LINE
;
CLFILL: LXI D,PROMPT ;PRINT A PROMPT
MVI C,PRINTF ;USE CP/M FUNCT 9
CALL BDOS
LXI D,CLBUF ;NOW FILL THE BUFFER
MVI C,RDBUF
CALL BDOS
LDA CLCNT ;RETURN WITH COUNT IN A
LXI H,CLTEXT ;RESET THE CMD LINE POINTER
SHLD CLPTR
ORA A ;SET CY ON LEN NZ
STC
RZ
CMC
RET
;
; MAKE SURE NO MEMORY OVERFLOW
;
SIZE: LDA BDOS+2 ;HIGHEST PAGE POINTER
DCR A ;MAKE IT BE UNDER BDOS
CMP H ;CHECK IT AGAINST CURRENT PAGE
RNC ;NC=ALL OKAY
JMP MEMERR ;OTHERWISE ABORT
;
; SET UP THE $$$.SUB FILE
; FOR WRITING
;
WRSET: CALL ISMPM ;ADDED BY GAG TO CHECK FOR MP/M OPERATING SYSTEM
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 '$' ;PARAMETER SPECIFIER?
JNZ STOBYT ;IF NOT, JUST WRITE CHAR
LDA OPTION ;CHECK OPTION: '$' DOESN'T
CPI '/' ; COUNT IN '/' MODE
MVI A,'$' ;(RESTORE THE '$')
JZ STOBYT
CALL LKAHED ;PEEK AT NEXT CHAR
JC PARERR ;LINE ENDING MEANS PARAM ERR
CPI '$' ;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
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
;
;DECIMAL OUTPUT ROUTINE
;
DECOUT: PUSH B
PUSH D
PUSH H
LXI B,-10
LXI D,-1
;
DECOU2: DAD B
INX D
JC DECOU2
LXI B,10
DAD B
XCHG
MOV A,H
ORA L
CNZ DECOUT
MOV A,E
ADI '0'
CALL TYPE
POP H
POP D
POP B
RET
;
; PRINT CR, LF ON CONSOLE
;
CRLF: MVI A,CR
CALL TYPE
MVI A,LF
;
; PRINT CHAR IN A ON CONSOLE
;
TYPE: PUSH H ;SAVE REGS
PUSH D
PUSH B
MOV E,A ;PUT IN E FOR CP/M
MVI C,FPCHAR
CALL BDOS ;PRINT IT
POP B ;RESTORE ALL
POP D
POP H
RET
;
; CONVERT CHAR IN A TO UPPER CASE
;
UCASE: CPI 'a' ;VALIDATE CASE
RC
CPI 'z'+1
RNC
ANI 5FH ;GOT LC, CONV TO UC
RET
;
; ERROR HANDLERS
;
WRERR: CALL ERRXIT
DB 'Disk full$'
NOMAKE: CALL ERRXIT
DB 'Directory full$'
MEMERR: CALL ERRXIT
DB 'Memory full$'
NOTFND: CALL ERRXIT
DB 'Submit file not found$'
PARERR: CALL ERRXIT
DB 'Parameter$'
PAROVF: CALL ERRXIT
DB 'Too many parameters:$'
LENERR: CALL ERRXIT
DB 'Line too long:$'
NOTEXT: CALL ERRXIT
DB 'Submit file empty$'
CCERR: CALL ERRXIT
DB 'Control character$'
ERRXIT: POP D
MVI C,PRINTF
CALL BDOS
LXI D,ERRMSG ;PRINT 2ND HALF MSG
MVI C,PRINTF
CALL BDOS
LHLD LINNUM ;TELL LINE NUMBER
CALL DECOUT
CALL CRLF
LXI D,SUBFCB ;DELETE THE $$$.SUB FILE
MVI C,DELETF
CALL BDOS
JMP CPBASE
;
ERRMSG: DB ' error on line number: $'
;
; PROMPT FOR COMMAND LINE INPUT
;
PROMPT: DB CR,LF,'*$'
;
; 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
LXI H,FREMEM ;FREE MEMORY STARTS TXT AREA
SHLD TXTPTR
MVI A,80H ;FORCE READ
STA IBP
STA CLCNT ;FORCE CONSOLE READ
RET
;THIS ROUTINE CHECKS FOR MP/M OPERATING SYSTEM. IF IT'S CP/M THEN IT RETURNS
;IF ITS MP/M IT FINDS THE CONSOLE NO FROM THE SYSTEM AND INSERTS IT IN THE
;SECOND CHARACTER POSITION OF THE FILE TYPE IN THE FCB FOR THE SUBMIT FILE
;AND SETS A FLAG IN THE MP/M SYSTEM TO TELL IT THERE'S A SUBMIT FILE TO
;EXECUTE WHEN THE NEXT WARM BOOT OCCURRS. GAG
ISMPM: PUSH PSW
PUSH B
PUSH D
PUSH H
MVI C,0CH ;GET VERSION NUMBER IN HL
CALL 005H
XRA A
CMP H ;IS IT CP/M?
JZ RSET ;ZERO MEANS CP/M. DON'T NEED ANYTHING ELSE
MPM: MVI C,9AH ;GET SYSTEM DATA ADDRESS IN HL
CALL 005H
LXI D,80H
DAD D ;ADD 128 TO IT TO FIND SUBMIT FLAGS
PUSH H ;SAVE POINTER TO SUBMIT FLAGS
MVI C,99H ;GET CONSOLE NUMBER IN A
CALL 005H
MVI D,0
MOV E,A ;DE = A
ADI 30H ;PUT ASCII OF CONSOLE NO IN FCB
LXI H,CONSOL ;SECOND LETTER IN FILE TYPE IN FCB
MOV M,A ;PUT ASCII OF CONSOLE NO IN FCB
POP H ;RESTORE POINTER TO SUBMIT FLAGS
DAD D ;CONSOLE SUBMIT FLAG = PTR + CON NO.
MVI M,0FFH ;SET CON SUBMIT FLAG TO TRUE
RSET: POP H ;RETURN TO MAIN PROGRAM
POP D
POP B
POP PSW
RET
;
; PRINT HELP WITH PROGRAM OPTIONS
;
HELP: LXI D,HLPMSG ;PRINT THE HELP STUFF
MVI C,PRINTF
CALL BDOS
LHLD SPSAVE ;THEN RETURN W/NO WARM-BOOT
SPHL
RET
;
HLPMSG: DB CR,LF,'How to use SUPERSUB:',CR,LF
DB CR,LF,'SUPERSUB<CR> :print this HELP message'
DB CR,LF,'SUPERSUB /<CR> :go into interactive mode'
DB CR,LF,'SUPERSUB /<cmd lines> :use SUMMARY mode'
DB CR,LF,'SUPERSUB <FILE> <PARMS> :as in standard SUBMIT.COM'
DB CR,LF
DB CR,LF,'In "/" (interactive) mode, SUPERSUB will prompt you'
DB CR,LF,'a line at a time for the SUBMIT job input...logical'
DB CR,LF,'lines may be combined on the same input line by sep-'
DB CR,LF,'erating them with semicolons. Example:'
DB CR,LF,' A>SUPERSUB /STAT;DIR'
DB CR,LF,'specifies two commands on the same input line.',CR,LF
DB CR,LF,'Submitted jobs may be nested...SUPERSUB does not erase'
DB CR,LF,'any existing submit job (appends to them instead).'
DB CR,LF
DB CR,LF,'To insert a control character into the output, pre-'
DB CR,LF,'fix it with a "^" (works in any mode).'
DB CR,LF,'$'
;
; VARIABLE STORAGE
;
VAR EQU $
;
TXTPTR: DW 0 ;FREE MEMORY POINTER
TBLPTR: DW 0 ;POINTER TO PARM TABLE
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
CLFLAG: DB 0 ;USE CP/M CMD LINE FLAG
OPTION: DB 0 ;'/' OPTION FLAG STORE
TABLE: DS NPAR*3 ;PARAMETER TABLE
ENDTBL: DW 0FFFFH ;END OF PARAMETER TABLE
;
ENDVAR EQU $
;
; COMMAND LINE BUFFER...NOT INITIALIZED
;
CLBUF: DB 128 ;BUFFER LENGTH
CLCNT: DB 0 ;CHARACTER COUNTER
CLTEXT: DS 128 ;THE BUFFER ITSELF
;
SPSAVE: DW 0 ;STACK POINTER SAVE
;
;
; FCB FOR $$$.SUB
;
SUBFCB: DB SUBDRV ;DRIVE SPECIFIER
DB '$'
CONSOL: DB '$' ; IF MPM THEN PUT ASCII OF CONSOLE NO HERE.
DB '$ '
SUBTYP: DB 'SUB'
DW 0,0,0,0 ;INITIALIZE REST OF FCB
DW 0,0,0,0
DW 0,0
;
; STACK AREA
;
DS 200 ;WHY NOT?
STACK EQU $
FREMEM EQU $
;
END SUBMIT