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 / SUBMIT / SUB.LBR / SUB.AQM / SUB.ASM
Assembly Source File  |  2000-06-30  |  26KB  |  1,203 lines

  1. * PROGRAM NAME:  SUB
  2. * AUTHOR:  RICHARD CONN (From SuperSUB Ver 1.1 by Ron Fowler)
  3. * VERSION:  1.4
  4. * DATE:  10 OCT 81
  5. * PREVIOUS VERSIONS:  1.3 (7 OCT 81)
  6. * PREVIOUS VERSIONS:  1.2 (5 OCT 81), 1.1 (3 OCT 81), 1.0 (1 OCT 81)
  7.  
  8. VERS    EQU    14    ; Version Number
  9.  
  10. ;
  11. ;
  12. ;************************************************
  13. ;*        EXTENDED SUBMIT FOR        *
  14. ;*             CP/M            *
  15. ;************************************************
  16. ;
  17. ;    SUB is derived from Ron's SuperSUB program; it provides a different
  18. ; format for the command line, a command-search hierarchy like CCPZ, a
  19. ; resetting of the DMA address, several additional functions, and there are
  20. ; several other additions/changes.
  21. ;
  22. ; REVISED 09/13/81 (RGF): added control character translation
  23. ;              fixed bug in line number reporting
  24. ;
  25. ;    VERSION 1.1         by Ron Fowler
  26. ;    2/18/81 (first written)     WESTLAND, MICH.
  27. ;
  28. ;
  29. ; This program is intended as a replacement for the
  30. ; SUBMIT program provided with CP/M.  It provides sev-
  31. ; eral new facilities:
  32. ;    1) Nestable SUBMIT runs
  33. ;    2) Interactive entry of SUBMIT job (no need
  34. ;       to use an editor for simple SUBMIT runs)
  35. ;    3) Command line entry of small SUBMIT jobs
  36. ;    4) Ability to enter blank lines in an edited
  37. ;       SUBMIT file
  38. ;    5) User customization of number of parameters
  39. ;       and drive to send $$$.SUB to
  40. ;
  41. ; For full details along with examples, see the ac-
  42. ; companying documentation file.
  43. ;            --Ron Fowler
  44. ;
  45. ;
  46. ; DEFINE BOOLEANS
  47. ;
  48. FALSE    EQU    0
  49. TRUE    EQU    NOT FALSE
  50. ;
  51. ;************************************************************
  52. ;
  53. ;        --  User customizable options --
  54. ;
  55. FORCE$SUB    EQU    FALSE    ;TRUE IF SUBMITTED FILE MUST BE OF TYPE .SUB
  56. TIME$CONST    EQU    0C000H    ;DELAY FOR RINGING BELL
  57. DFLT$USER    EQU    0    ;DEFAULT USER NUMBER TO SEARCH FOR .SUB FILE
  58. DFLT$DISK    EQU    0    ;DEFAULT DISK TO SEARCH FOR .SUB FILE (0=A)
  59. NPAR        EQU    20    ;NUMBER OF ALLOWABLE PARAMETERS
  60. SUBDRV        EQU    1    ;MAKE 0 FOR DFLT, 1,2,3,ETC FOR A,B,C
  61. QUIET        EQU    FALSE    ;SET TO TRUE TO ELIMATE SIGN-ON MSG
  62. CPBASE        EQU    0    ;SET TO 4200H FOR HEATH CP/M
  63. OPT        EQU    '/'    ;OPTION DELIMITER CHAR
  64. PDELIM        EQU    '$'    ;PARAMETER DELIMITER
  65. ;
  66. ;
  67. ;
  68. ;************************************************************
  69. ;
  70. ; CP/M DEFINITIONS
  71. ;
  72. FGCHAR    EQU    1    ;GET CHAR FUNCTION
  73. FPCHAR    EQU    2    ;PRINT CHAR FUNCTION
  74. DIRIOF    EQU    6    ;DIRECT CONSOLE I/O
  75. PRINTF    EQU    9    ;PRINT STRING FUNCTION
  76. RDBUF    EQU    10    ;READ CONSOLE BUFFER
  77. DETVERS    EQU    12    ;GET VERSION NUMBER
  78. LOGIN    EQU    14    ;LOG IN DISK
  79. OPENF    EQU    15    ;OPEN FILE FUNCTION
  80. CLOSEF    EQU    16    ;CLOSE FILE FUNCTION
  81. DELETF    EQU    19    ;DELETE FILE FUNCTION
  82. READF    EQU    20    ;READ RECORD FUNCTION
  83. WRITEF    EQU    21    ;WRITE RECORD FUNCTION
  84. MAKEF    EQU    22    ;MAKE (CREATE) FILE FUNCTION
  85. GETDSK    EQU    25    ;RETURN CURRENT DISK
  86. SETDMA    EQU    26    ;SET DMA ADDRESS
  87. UCODE    EQU    32    ;GET/SET USER CODE
  88. ;
  89. BDOS    EQU    CPBASE+5
  90. ;
  91. FCB    EQU    5CH    ;DEFAULT FILE CONTROL BLOCK
  92. FCBEX    EQU    12    ;FCB OFFSET TO EXTENT FIELD
  93. FCBRC    EQU    15    ;FCB OFFSET TO RECORD COUNT
  94. FCBNR    EQU    32    ;FCB OFFSET TO NEXT RECORD
  95. FN    EQU    1    ;FCB OFFSET TO FILE NAME
  96. FT    EQU    9    ;FCB OFFSET TO FILE TYPE
  97. TBUF    EQU    CPBASE+80H    ;DEFAULT BUFFER
  98. TPA    EQU    CPBASE+100H    ;TRANSIENT PROGRAM AREA
  99. ;
  100. PUTCNT    EQU    TBUF    ;COUNTER FOR OUTPUT CHARS
  101. ;
  102. ; DEFINE SOME TEXT CHARACTERS
  103. ;
  104. CTRLC    EQU    3    ;^C
  105. BEL    EQU    7    ;RING BELL
  106. CR    EQU    13    ;CARRIAGE RETURN
  107. LF    EQU    10    ;LINE FEED
  108. TAB    EQU    9
  109. ;
  110. ; START OF PROGRAM CODE
  111. ;
  112.     ORG    TPA
  113. ;
  114. ;    Begin Execution of SUB.COM
  115. ;
  116. SUBMIT:
  117.     LXI    H,0    ;SAVE STACK IN CASE
  118.     DAD    SP    ;  ONLY HELP REQUESTED
  119.     SHLD    SPSAVE    ;(NOT OTHERWISE USED)
  120.     LXI    SP,STACK
  121.     MVI    C,SETDMA    ;SET DMA ADDRESS
  122.     LXI    D,TBUF    ;SET DMA TO TBUF
  123.     CALL    BDOS
  124.     CALL    START
  125. ;
  126. ;    SIGN ON MESSAGE
  127. ;
  128.     IF    NOT QUIET
  129.     DB    'SUB Version ',VERS/10+'0','.',(VERS MOD 10)+'0'
  130.     DB    ' -- Extended Indirect Command File Facility$'
  131.     ENDIF
  132. ;
  133. START:
  134.     POP    D    ;RETRIEVE STRING POINTER
  135.     MVI    C,PRINTF
  136.     CALL    BDOS    ;PRINT THE SIGN-ON
  137.     LDA    FCB+1    ;ANYTHING ON CMD LINE?
  138.     CPI    ' '
  139.     JZ    HELP    ;NO, GO PRINT HELP
  140.     CALL    INITVAR    ;INITIALIZE THE VARIABLE AREA
  141.     CALL    GETPAR    ;GET COMMAND LINE PARAMETERS AND EXTRACT OPTION
  142.     CALL    ABORT    ;PERFORM ABORT IF FLAG SET
  143.     CALL    SETUP    ;SET UP READ OF SUBMIT FILE
  144.     CALL    RDFILE    ;READ THE SUBMIT FILE
  145.     CALL    WRSET    ;SET UP WRITE OF "$$$.SUB"
  146.     CALL    WRSUB    ;WRITE "$$$.SUB"
  147.     JMP    CPBASE    ;GO START THE SUBMIT
  148. ;
  149. ;
  150. ;    SETUP SETS UP THE FILE CONTROL BLOCK
  151. ;    FOR READING IN THE .SUB TEXT FILE
  152. ;
  153. SETUP:
  154.     LXI    H,FCB+FT    ;LOOK AT FIRST CHAR OF
  155.     MOV    A,M        ;FILE TYPE.  IF IT IS
  156.     CPI    ' '        ;BLANK, THEN GO MOVE
  157.     JZ    PUTSUB        ;"SUB" INTO FT FIELD
  158.  
  159.     IF    FORCE$SUB    ;FILE TYPE MUST BE OF .SUB
  160.     LXI    D,SUBTYP    ;FILE TYPE MUST BE .SUB
  161.     MVI    B,3        ;3 BYTES
  162.     CALL    COMPAR
  163.     JNZ    NOTFND    ;FILE NOT FOUND IF NO TYPE MATCH
  164.     ENDIF
  165.  
  166.     RET        ;  IF NOT BLANK, THEN ACCEPT ANY FILE TYPE
  167. ;
  168. ;    MOVE "SUB" INTO THE FILE TYPE
  169. ;
  170. PUTSUB:
  171.     XCHG        ;BY CONVENTION, MOVE FROM
  172.     LXI    H,SUBTYP    ; @HL TO @DE
  173.     MVI    B,3
  174.     CALL    MOVE
  175.     RET
  176. ;
  177. ; MOVE # BYTES IN B REGISTER FROM @HL TO @DE
  178. ;
  179. MOVE:
  180.     MOV    A,M    ;PICK UP
  181.     STAX    D    ;PUT DOWN
  182.     INX    H    ;I'M SURE
  183.     INX    D    ; YOU'VE SEEN THIS
  184.     DCR    B    ; BEFORE...
  185.     JNZ    MOVE    ;100 TIMES AT LEAST
  186.     RET        ;I KNOW I HAVE!
  187. ;
  188. ; GETPAR MOVES THE SUBSTITUTION PARAMETERS SPECIFIED
  189. ; IN THE COMMAND LINE INTO MEMORY, AND STORES THEIR
  190. ; ADDRESSES IN THE PARAMETER TABLE.  THIS ALLOWS
  191. ; SUBSTITUTION OF $1, $2, ETC., IN THE SUBMIT COMMANDS
  192. ; WITH THEIR ACTUAL VALUES SPECIFED IN THE COMMAND
  193. ; LINE.
  194. ;
  195. GETPAR:
  196.     XRA    A    ;A=0
  197.     STA    AFLAG    ;TURN OFF ABORT COMMAND
  198.     LXI    H,TBUF+1    ;WHERE WE FIND THE COMMAND TAIL
  199.     CALL    SCANTO    ;SKIP SUBMIT FILE NAME
  200.     STA    OPTION    ;FIRST CHAR OF CMD LINE IS OPTION
  201.     RC        ;LINE ENDED?
  202.     CPI    OPT    ;NO, CHECK OPTION
  203.     JNZ    GLP0    ;NOT KEYBOARD INP, READ FILE
  204.     INX    H    ;POINT PAST '/'
  205.     MOV    A,M    ;GET OPTION CHAR
  206.     CPI    'A'    ;ABORT COMMAND
  207.     JZ    GPARABT
  208.     CPI    'D'    ;DO COMMAND
  209.     JZ    GPARDO
  210.     CPI    'I'    ;INTERACTIVE MODE
  211.     JZ    GPARINT    ;SKIP TO EOL AND RETURN
  212.     JMP    HELP    ;HELP OTHERWISE
  213. GPARABT:
  214.     MVI    A,0FFH    ;TURN ON ABORT FLAG
  215.     STA    AFLAG
  216.     INX    H    ;GET POSSIBLE BELL OPTION
  217.     MOV    A,M
  218.     CPI    'B'    ;BELL OPTION
  219.     RNZ
  220.     MVI    A,0FFH    ; SET BELL FLAG
  221.     STA    BELL$FLAG
  222.     RET
  223. GPARINT:
  224.     XRA    A    ;TURN OFF COMMAND LINE INPUT
  225.     STA    CLFLAG
  226.     RET
  227. GPARDO:
  228.     INX    H    ;SKIP TO <SP>
  229.     MOV    A,M    ;GET CHAR
  230.     CPI    ' '+1    ;LOOK FOR <SP> OR LESS
  231.     JNC    GPARDO
  232. SLSCAN:
  233.     SHLD    CLPTR    ;SAVE CMD LINE PTR
  234.     MOV    A,M    ;KBD IS SOURCE, GET EOL FLAG
  235.     STA    CLFLAG    ;SAVE AS EOL FLAG
  236.     CPI    ' '    ;ALLOW SPACES AFTER '/'
  237.     RNZ        ;GOT NON-BLANK, DONE
  238.     INX    H    ;ELSE CONTINUE SCAN
  239.     JMP    SLSCAN
  240. GLP0:
  241.     MOV    A,M    ;INPUT IS FROM A .SUB FILE..THIS
  242.     INX    H    ;  CODE SKIPS OVER THE NAME OF
  243.     ORA    A    ;  THE SUB FILE TO GET TO THE
  244.     RZ        ;  COMMAND LINE PARAMETERS
  245.     CPI    ' '
  246.     JZ    GLP
  247.     CPI    TAB
  248.     JNZ    GLP0
  249. GLP:
  250.     CALL    SCANTO    ;PASS UP THE BLANKS
  251.     RC        ;CY RETURNED IF END OF CMD LINE
  252.     CALL    PUTPAR    ;NOW PUT THE PARAMETER INTO MEM
  253.     RC        ;CY RETURNED IF END OF CMD LINE
  254.     JMP    GLP    ;GET THEM ALL
  255. ;
  256. ; SCANTO SCANS PAST BLANKS TO THE FIRST NON-BLANK. IF
  257. ; END OF COMMAND LINE FOUND, RETURNS CARRY SET.
  258. ;
  259. SCANTO:
  260.     MOV    A,M
  261.     INX    H
  262.     ORA    A    ;SET FLAGS ON ZERO
  263.     STC        ;IN CASE ZERO FOUND (END OF CMD LIN)
  264.     RZ
  265.     CPI    ' '
  266.     JZ    SCANTO    ;SCAN PAST BLANKS
  267.     CPI    TAB    ;DO TABS TOO, JUST FOR
  268.     JZ    SCANTO    ;  GOOD MEASURE
  269.     DCX    H    ;FOUND CHAR, POINT BACK TO IT
  270.     ORA    A    ;INSURE CARRY CLEAR
  271.     RET
  272. ;
  273. ; PUTPAR PUTS THE PARAMETER POINTED TO BY HL INTO
  274. ; MEMORY POINTED TO BY "TXTPTR".  ALSO STORES THE
  275. ; ADDRESS OF THE PARAMETER INTO THE PARAMETER TABLE
  276. ; FOR EASY ACCESS LATER, WHEN WE WRITE $$$.SUB
  277. ;
  278. PUTPAR:
  279.     PUSH    H    ;SAVE POINTER TO PARM
  280.     LHLD    TXTPTR    ;NEXT FREE MEMORY
  281.     XCHG        ;  INTO DE
  282.     LHLD    TBLPTR    ;NEXT FREE AREA OF TABLE
  283.     MOV    A,M    ;NON-ZERO IN TABLE
  284.     ORA    A    ; INDICATES TABLE
  285.     JNZ    PAROVF    ; TABLE OVERFLOW (TOO MANY PARMS)
  286.     MOV    M,E    ;STORE THE PARM ADRS
  287.     INX    H
  288.     MOV    M,D
  289.     INX    H
  290.     SHLD    TBLPTR    ;SAVE TABLE PNTR FOR NEXT TIME
  291.     POP    H    ;GET BACK PARM POINTER
  292.     PUSH    D    ;SAVE FREE MEM POINTER BECAUSE
  293.             ;  WE WILL HAVE TO HAVE IT BACK
  294.             ;  LATER TO STORE THE LENGTH
  295.     INX    D    ;POINT PAST LENGTH STORAGE
  296.     MVI    B,0    ;INITIALIZE LENGTH OF PARM
  297. PPLP:
  298.     MOV    A,M    ;GET NEXT BYTE OF PARM
  299.     INX    H
  300.     ORA    A    ;TEST FOR END OF CMD LINE
  301.     JZ    PP2    ;JUMP IF END
  302.     CPI    ' '    ;TEST FOR END OF COMMAND
  303.     JZ    PP2
  304.     CPI    TAB    ;TAB ALSO ENDS COMMAND
  305.     JZ    PP2
  306.     STAX    D    ;PUT PARAMETER BYTE-BY-BYTE
  307.     INX    D    ;INTO FREE MEMORY
  308.     INR    B    ;BUMP LENGTH
  309.     JMP    PPLP
  310. PP2:
  311.     XCHG
  312.     SHLD    TXTPTR    ;NEW FREE MEMORY POINTER
  313.     POP    H    ;REMEMBER OUR LENGTH POINTER?
  314.     MOV    M,B    ;STORE THE LENGTH
  315.     XCHG        ;HAVE TO RETN HL > CMD LINE
  316.     ORA    A    ;NOW RETURN END OF LINE FLAG
  317.     STC
  318.     RZ        ;RETURN CY IF ZERO (EOL MARK)
  319.     CMC
  320.     RET
  321. ;
  322. ;
  323. ;    ABORT CHECKS TO SEE IF THE ABORT FLAG IS SET AND
  324. ;    EXECUTES THE ABORT FUNCTION IF SO
  325. ;
  326. ;
  327. ABORT:
  328.     LDA    AFLAG    ;GET THE FLAG
  329.     ORA    A    ;0=NO
  330.     RZ
  331.     LXI    D,ABMSG    ;PRINT ABORT MESSAGE
  332.     MVI    C,PRINTF
  333.     CALL    BDOS
  334.     CALL    CHARINB    ;GET RESPONSE
  335.     CPI    'A'    ;ABORT?
  336.     JZ    ABORT0    ;RETURN TO CP/M
  337.     CPI    CTRLC    ;ABORT?
  338.     JNZ    ABORT1    ;RETURN TO CP/M
  339. ABORT0:
  340.     LXI    D,SUBFCB    ;DELETE SUBMIT FILE
  341.     MVI    C,DELETF
  342.     CALL    BDOS
  343.     LXI    D,ABMSG1    ;PRINT DONE MESSAGE
  344.     MVI    C,PRINTF
  345.     CALL    BDOS
  346.     JMP    CPBASE    ;RETURN TO CP/M
  347. ABORT1:
  348.     LXI    D,ABMSG2    ;PRINT CONTINUATION MESSAGE
  349.     MVI    C,PRINTF
  350.     CALL    BDOS
  351.     JMP    CPBASE    ; RETURN TO CP/M
  352. ABMSG:
  353.     DB    CR,LF,'Abort SUBMIT File'
  354.     DB    CR,LF,'Do you wish to abort execution?'
  355.     DB    CR,LF,'  Enter A or ^C to Abort or anything else to '
  356.     DB    'continue - $'
  357. ABMSG1:
  358.     DB    'Execution Aborted$'
  359. ABMSG2:
  360.     DB    'Continuing Execution$'
  361. ;
  362. ;    INPUT CHAR FROM CON:; RING BELL EVERY SO OFTEN IF FLAG SET
  363. ;
  364. CHARINB:
  365.     LDA    BELL$FLAG    ; GET FLAG
  366.     ORA    A        ; 0=NO
  367.     JZ    CHARIN
  368.     PUSH    H        ; SAVE HL
  369. CHARINB$LOOP:
  370.     LXI    H,TIME$CONST    ; GET TIME CONSTANT
  371. CHARINB$LOOP1:
  372.     DCX    H        ; COUNT DOWN
  373.     MOV    A,H
  374.     ORA    L
  375.     JNZ    CHARINB$LOOP1
  376.     MVI    E,0FFH        ; REQUEST STATUS
  377.     MVI    C,DIRIOF    ; DIRECT I/O
  378.     CALL    BDOS
  379.     ORA    A        ; ANY INPUT?
  380.     JNZ    CHARINB$DONE
  381.     MVI    E,BEL        ; RING BELL
  382.     MVI    C,2        ; OUTPUT TO CON:
  383.     CALL    BDOS
  384.     JMP    CHARINB$LOOP
  385. CHARINB$DONE:
  386.     POP    H        ; RESTORE HL
  387.     JMP    CHARIN1
  388.  
  389. ;
  390. ;    INPUT CHAR FROM CON:; CAPITALIZE IT AND ECHO <CRLF>
  391. ;
  392. CHARIN:
  393.     MVI    C,FGCHAR    ;GET CHAR
  394.     CALL    BDOS
  395. CHARIN1:
  396.     CALL    UCASE        ;CAPITALIZE
  397.     PUSH    PSW        ;SAVE IT
  398.     CALL    CRLF        ;NEW LINE
  399.     POP    PSW        ;GET IT
  400.     RET
  401. ;
  402. ;    RDFILE READS THE .SUB FILE SPECIFIED
  403. ;    IN THE SUBMIT COMMAND INTO MEMORY
  404. ;
  405. RDFILE:
  406.     MVI    A,0FFH    ;SET NO DISK/USER CHANGE
  407.     STA    DDISK
  408.     STA    DUSER
  409.     LXI    H,0    ;INIT LINE NUMBER
  410.     SHLD    LINNUM
  411.     LDA    OPTION    ;USING A FILE?
  412.     CPI    OPT    ;OPT OPTION TELLS
  413.     JNZ    RDFILE1    ;JUMP IF NOT
  414.     LXI    D,RDLMSG    ;READING LINE MESSAGE
  415.     MVI    C,PRINTF
  416.     CALL    BDOS
  417.     JMP    LINE
  418. RDFILE1:
  419.     LXI    D,RDFMSG    ;READING FILE MESSAGE
  420.     MVI    C,PRINTF
  421.     CALL    BDOS
  422.  
  423. *  CHECK FOR .SUB FILE IN CURRENT USER/CURRENT DISK
  424.     LXI    D,FCB    ;WE ARE, OPEN IT
  425.     CALL    INITFCB    ;INIT FCB
  426.     MVI    C,OPENF
  427.     CALL    BDOS
  428.     INR    A    ;IF 0FFH RETURNED, THEN FILE NOT FOUND
  429.     JNZ    LINE    ;CONTINUE IF FOUND
  430.  
  431. *  DETERMINE IF CP/M 1.4 AND SKIP USER NUMBER CHANGE IF SO
  432.     MVI    C,DETVERS
  433.     CALL    BDOS
  434.     MOV    A,H    ;GET RETURNED VALUE
  435.     ORA    L
  436.     JZ    LOG$DEF    ;LOG IN DRIVE A:
  437.  
  438. *  GET CURRENT DISK FOR LATER
  439.     MVI    C,GETDSK    ;BDOS FCT
  440.     CALL    BDOS
  441.     STA    DDISK    ;DEFAULT DISK
  442.  
  443. *  DETERMINE IF CP/M 1.4 AND SKIP USER NUMBER PROCESSING IF SO
  444.     MVI    C,DETVERS    ;GET VERSION NUMBER IN HL
  445.     CALL    BDOS
  446.     MOV    A,H    ;CHECK FOR 0
  447.     ORA    L
  448.     JZ    LOG$DEF    ;LOG IN DRIVE A: IF NOT ALREADY LOGGED IN
  449.  
  450. *  GET CURRENT USER NUMBER FOR LATER
  451.     MVI    E,0FFH    ;GET USER CODE
  452.     MVI    C,UCODE    ;BDOS FCT
  453.     CALL    BDOS
  454.     STA    DUSER    ;DEFAULT USER
  455.     CPI    DFLT$USER    ;SAME AS DEFAULT?
  456.     JZ    LOG$DEF    ;GO AHEAD AND GET DEFAULT DRIVE IF SO
  457.  
  458. *  LOOK FOR .SUB FILE IN DEFAULT USER/CURRENT DISK
  459.     MVI    E,DFLT$USER    ;SET DEFAULT USER
  460.     MVI    C,UCODE    ;SET USER CODE
  461.     CALL    BDOS
  462.     LXI    D,FCB    ;OPEN .SUB FILE
  463.     CALL    INITFCB    ;RESET FCB
  464.     MVI    C,OPENF
  465.     CALL    BDOS
  466.     INR    A    ;IF 0FFH RETURN, THEN FILE NOT FOUND
  467.     JNZ    LINE    ;CONTINUE IF FOUND
  468.  
  469. *  LOOK FOR .SUB FILE IN DEFAULT USER/DEFAULT DISK
  470. LOG$DEF:
  471.     LDA    DDISK    ;ON DEFAULT DISK?
  472.     CPI    DFLT$DISK
  473.     JZ    NOTFND    ;NOT FOUND IF SO
  474.     MVI    E,DFLT$DISK    ;LOG IN DEFAULT DISK
  475.     MVI    C,LOGIN
  476.     CALL    BDOS
  477.     LXI    D,FCB    ;OPEN .SUB FILE
  478.     CALL    INITFCB    ;INIT FCB
  479.     MVI    C,OPENF
  480.     CALL    BDOS
  481.     INR    A    ;IF 0FFH RETURN, THEN FILE NOT FOUND
  482.     JZ    NOTFND    ;FILE NOT FOUND
  483. LINE:
  484.     LHLD    LINNUM    ;BUMP LINE NUMBER
  485.     INX    H
  486.     SHLD    LINNUM
  487.     LHLD    PREV    ;GET PREV PREVIOUS LINE POINTER
  488.     XCHG
  489.     LHLD    TXTPTR    ;GET CURRENT FREE MEM POINTER
  490.     SHLD    PREV    ;MAKE IT THE PREV LINE (FOR NXT PASS)
  491.     MOV    M,E    ;STORE AT BEGIN OF CURRENT LINE,
  492.     INX    H    ;  A POINTER TO THE PREVIOUS
  493.     MOV    M,D
  494.     INX    H
  495.     PUSH    H    ;LATER WE WILL PUT LENGTH HERE
  496.     INX    H    ;SKIP PAST LENGTH
  497.     MVI    C,0    ;INITIALIZE LENGTH TO ZERO
  498. LLP:
  499.     CALL    GNB    ;GET NEXT BYTE FROM INPUT SOURCE
  500.     JC    EOF    ;CY SET IF END OF FILE FOUND
  501.     ANI    7FH    ;MASK OUT MSB
  502.     CALL    UCASE    ;CONVERT TO UPPER CASE
  503.     CPI    1AH    ;SEE IF CPM END OF FILE INDICATOR
  504.     JZ    EOF
  505.     CPI    LF    ;IGNORE LINEFEEDS
  506.     JZ    LLP
  507.     CPI    CR    ;IF IT'S A CARRIAGE RETURN,
  508.     JZ    EOL    ;  THEN DO END OF LINE
  509.     MOV    M,A    ;STORE ALL OTHERS INTO MEMORY
  510.     INX    H
  511.     CALL    SIZE    ;MAKE SURE NO MEMORY OVERFLOW
  512.     INR    C    ;BUMP CHAR COUNT
  513.     JM    LENERR    ;MAX OF 128 CHARS PER LINE
  514.     JMP    LLP    ;GO DO NEXT CHAR
  515. RDFMSG:
  516.     DB    CR,LF,'Process SUBMIT File$'
  517. RDLMSG:
  518.     DB    CR,LF,'Input SUBMIT File Command Lines$'
  519. ;
  520. ;    DO END OF LINE SEQUENCE
  521. ;
  522. EOL:
  523.     SHLD    TXTPTR    ;SAVE FREE MEMORY POINTER
  524.     POP    H    ;CURRENT LINE'S LENGTH POINTER
  525.     MOV    M,C    ;STORE LENGTH AWAY
  526.     JMP    LINE    ;GO DO NEXT LINE
  527. ;
  528. ;    END OF TEXT FILE
  529. ;
  530. EOF:
  531.     SHLD    TXTPTR    ;SAVE FREE MEMORY POINTER
  532.     POP    H    ;CURRENT LINE'S LENGTH POINTER
  533.     MOV    M,C    ;STORE LENGTH AWAY
  534.     RET        ;ALL DONE READING SUB FILE
  535. ;
  536. ;    INITIALIZE KEY FIELDS OF FCB PTED TO BY DE
  537. ;
  538. INITFCB:
  539.     PUSH    H    ;SAVE HL
  540.     XRA    A    ;A=0
  541.     STAX    D    ;SET DEFAULT DRIVE
  542.     LXI    H,FCBEX    ;PT TO EX FIELD
  543.     DAD    D
  544.     MOV    M,A    ;SET EX FIELD TO ZERO
  545.     LXI    H,FCBNR    ;PT TO CR FIELD
  546.     DAD    D
  547.     MOV    M,A    ;SET CR FIELD TO ZERO
  548.     POP    H    ;RESTORE HL
  549.     RET
  550. ;
  551. ;    GET NEXT BYTE FROM INPUT FILE
  552. ;
  553. GNB:
  554.     PUSH    H    ;DON'T ALTER ANYBODY
  555.     PUSH    D
  556.     PUSH    B
  557.     LDA    OPTION    ;INPUT FROM .SUB FILE?
  558.     CPI    OPT    ;TOLD BY ORIG CMD LINE OPTION
  559.     JNZ    NSLASH    ;JUMP IF WE ARE
  560.     CALL    GNBKBD    ;NO, GET A BYTE FROM KBD INPUT
  561.     JMP    GNBXIT    ;THEN LEAVE
  562. NSLASH:
  563.     LDA    IBP    ;GET BUFFER POINTER
  564.     ORA    A    ;PAST END?
  565.     CM    FILL    ;WRAPPED AROUND
  566.     JNC    GNB1    ;NO END OF FILE
  567.  
  568. *  RESTORE CURRENT USER/DISK IF CHANGED
  569.     LDA    DDISK    ;RESTORE CURRENT DISK
  570.     MOV    E,A
  571.     MVI    C,LOGIN    ;BDOS FCT
  572.     CPI    0FFH    ;IF FFH, NO CHANGE
  573.     CNZ    BDOS
  574.     LDA    DUSER    ;RESTORE CURRENT USER
  575.     MOV    E,A
  576.     MVI    C,UCODE    ;BDOS FCT
  577.     CPI    0FFH    ;IF FFH, NO CHANGE
  578.     CNZ    BDOS
  579.  
  580.     MVI    A,1AH    ;FAKE EOF
  581. GNB1:
  582.     MOV    E,A    ;PUT IN DE
  583.     MVI    D,0
  584.     INR    A    ;POINT TO NEXT
  585.     STA    IBP    ;PUT AWAY
  586.     LXI    H,TBUF    ;NOW OFFSET INTO BUFR
  587.     DAD    D
  588.     MOV    A,M    ;GET CHAR THERE
  589. GNBXIT:
  590.     POP    B    ;RESTORE EVERYBODY
  591.     POP    D
  592.     POP    H
  593.     ORA    A    ;TURN ON CARRY
  594.     RET
  595. ;
  596. ;    FILL INPUT BUFFER
  597. ;
  598. FILL:
  599.     MVI    C,READF
  600.     LXI    D,FCB
  601.     CALL    BDOS
  602.     ORA    A    ;GOT GOOD READ?
  603.     MVI    A,0    ;(NEW BUF PTR)
  604.     STC
  605.     RNZ        ;RETN CY=EOF
  606.     CMC        ;NO EOF, NO CY
  607.     RET
  608. ;
  609. ; COME HERE TO GET A .SUB CHARACTER WHEN
  610. ; WE'RE NOT USING A .SUB FILE ("/" OPTION)
  611. ;
  612. GNBKBD:
  613.     LDA    CLFLAG    ;USE CP/M CMD LINE?
  614.     ORA    A
  615.     JNZ    GNBCL    ;THEN GO DO IT
  616.     LDA    CLCNT    ;NOT, CHECK LOCAL
  617.     ORA    A    ;  CMD LINE CHAR COUNT
  618.     CM    CLFILL    ;REFILL WHEN IT WRAPS BACK
  619.     JC    GKEND    ;GOT CARRY (FROM CLFILL), RETURN EOF
  620.     DCR    A    ;COUNT DOWN
  621.     STA    CLCNT
  622.     JP    GNBCL    ;IF PLUS, BUFFER NOT EMPTY
  623.     MVI    A,CR    ;OUT OF CHARS, RETURN A CR
  624.     RET
  625. GKEND:
  626.     MVI    A,1AH    ;RETURN EOF
  627.     RET
  628. ;
  629. ; GET NEXT BYTE OF INPUT FROM CMD LINE @CLPTR
  630. ;
  631. GNBCL:
  632.     LHLD    CLPTR    ;LOAD THE POINTER
  633.     MOV    A,M    ;GET THE CHAR
  634.     INX    H    ;BUMP POINTER FOR NEXT TIME
  635.     SHLD    CLPTR
  636.     CPI    ';'    ;LOGICAL END-OF-LINE?
  637.     JNZ    NSEMI    ;JUMP IF NOT
  638.     MVI    A,CR    ;YES, TRANSLATE IT
  639.     RET
  640. NSEMI:
  641.     ORA    A    ;PHYSICAL END-OF-LINE
  642.     RNZ        ;THIS ONLY NEEDED WHEN INPUT
  643.             ;  SOURCE IS ORIG CPM CMD LINE
  644.     MVI    A,1AH    ;TRANSLATE THAT TO END OF FILE
  645.     RET
  646. ;
  647. ; SUBROUTINE TO RE-FILL THE LOCAL COMMAND LINE
  648. ;
  649. CLFILL:
  650.     LXI    D,PROMPT    ;PRINT A PROMPT
  651.     MVI    C,PRINTF    ;USE CP/M FUNCT 9
  652.     CALL    BDOS
  653.     LXI    D,CLBUF ;NOW FILL THE BUFFER
  654.     MVI    C,RDBUF
  655.     CALL    BDOS
  656.     LDA    CLCNT    ;RETURN WITH COUNT IN A
  657.     LXI    H,CLTEXT    ;RESET THE CMD LINE POINTER
  658.     SHLD    CLPTR
  659.     ORA    A    ;SET CY ON LEN NZ
  660.     STC
  661.     RZ
  662.     CMC
  663.     RET
  664. ;
  665. ;    MAKE SURE NO MEMORY OVERFLOW
  666. ;
  667. SIZE:
  668.     LDA    BDOS+2    ;HIGHEST PAGE POINTER
  669.     DCR    A    ;MAKE IT BE UNDER BDOS
  670.     CMP    H    ;CHECK IT AGAINST CURRENT PAGE
  671.     RNC        ;NC=ALL OKAY
  672.     JMP    MEMERR    ;OTHERWISE ABORT
  673. ;
  674. ;    SET UP THE $$$.SUB FILE
  675. ;    FOR WRITING
  676. ;
  677. WRSET:
  678.     LXI    D,WRSUBMSG
  679.     MVI    C,PRINTF
  680.     CALL    BDOS
  681.     LXI    D,SUBFCB
  682.     MVI    C,OPENF
  683.     CALL    BDOS    ;OPEN THE FILE
  684.     INR    A    ;CHECK CPM RETURN
  685.     JZ    NONE1    ;NONE EXISTS ALREADY
  686. ;
  687. ;    $$$.SUB EXISTS, SO SET
  688. ;    FCB TO APPEND TO IT
  689. ;
  690.     LDA    SUBFCB+FCBRC    ;GET RECORD COUNT
  691.     STA    SUBFCB+FCBNR    ;MAKE NEXT RECORD
  692.     RET
  693. ;
  694. ;    COME HERE WHEN NO $$$.SUB EXISTS
  695. ;
  696. NONE1:
  697.     LXI    D,SUBFCB
  698.     MVI    C,MAKEF
  699.     CALL    BDOS
  700.     INR    A
  701.     JZ    NOMAKE    ;0FFH=CAN'T CREATE FILE
  702.     RET
  703. ;
  704. WRSUBMSG:
  705.     DB    CR,LF,'Writing SUBMIT Execution File to Disk$'
  706. ;
  707. ;    WRITE THE "$$$.SUB" FILE
  708. ;
  709. WRSUB:
  710.     LHLD    PREV    ;THIS CODE SCANS BACKWARD
  711.     MOV    A,H    ;  THRU THE FILE STORED IN
  712.     ORA    L    ;  MEMORY TO THE FIRST NON-
  713.     JZ    NOTEXT    ;  NULL LINE.  IF NONE IS
  714.     MOV    E,M    ;  FOUND, ABORTS
  715.     INX    H
  716.     MOV    D,M    ;HERE, WE PICK UP PNTR TO PREV LINE
  717.     INX    H    ;NOW WE POINT TO LENGTH
  718.     XCHG        ;WE NEED TO STORE AWAY
  719.     SHLD    PREV    ;  POINTER TO PREV LINE
  720.     XCHG
  721.     MOV    A,M    ;NOW PICK UP THE LENGTH
  722.     ORA    A    ;SET Z FLAG ON LENGTH
  723.     JNZ    WRNTRY    ;GOT LINE W/LENGTH: GO DO IT
  724.     LHLD    LINNUM    ;NOTHING HERE, FIX LINE NUMBER
  725.     DCX    H    ;(WORKING BACKWARD NOW)
  726.     SHLD    LINNUM
  727.     JMP    WRSUB
  728. WRLOP:
  729.     LHLD    PREV    ;GET PREV LINE POINTER
  730.     MOV    A,H
  731.     ORA    L    ;IF THERE IS NO PREV LINE
  732.     JZ    CLOSE    ;  THEN WE ARE DONE
  733.     MOV    E,M    ;ELSE SET UP PREV FOR NEXT
  734.     INX    H    ;  PASS THRU HERE
  735.     MOV    D,M
  736.     INX    H
  737.     XCHG        ;NOW STORE IT AWAY
  738.     SHLD    PREV
  739.     XCHG
  740. WRNTRY:
  741.     CALL    PUTLIN    ;WRITE THE LINE TO THE FILE
  742.     LHLD    LINNUM    ;BUMP THE LINE NUMBER
  743.     DCX    H    ;DOWN (WORKING BACK NOW)
  744.     SHLD    LINNUM
  745.     JMP    WRLOP
  746. ;
  747. ;    $$$.SUB IS WRITTEN, CLOSE THE FILE
  748. ;
  749. CLOSE:
  750.     LXI    D,SUBFCB
  751.     MVI    C,CLOSEF
  752.     JMP    BDOS
  753. ;
  754. ;    THIS SUBROUTINE WRITES A LINE
  755. ;    TO THE $$$.SUB FILE BUFFER,
  756. ;    AND FLUSHES THE BUFFER AFTER
  757. ;    THE LINE IS WRITTEN.
  758. ;
  759. PUTLIN:
  760.     MOV    A,M    ;PICK UP LENGTH BYTE
  761.     INX    H    ;POINT PAST IT
  762.     STA    GETCNT    ;MAKE A COUNT FOR "GET"
  763.     SHLD    GETPTR    ;MAKE A POINTER FOR "GET"
  764.     LXI    H,TBUF+1    ;TEXT GOES AFTER LENGTH
  765.     SHLD    PUTPTR    ;MAKE POINTER FOR "PUT"
  766.     XRA    A    ;INITIALIZE PUT COUNT
  767.     STA    PUTCNT
  768.     MOV    B,L    ;COUNT FOR CLEAR LOOP
  769. CLR:
  770.     MOV    M,A    ;ZERO OUT BUFFER LOC
  771.     INX    H
  772.     INR    B    ;COUNT
  773.     JNZ    CLR
  774. ;
  775. ;    THIS LOOP COLLECTS CHARACTERS
  776. ;    FROM THE LINE STORED IN MEMORY
  777. ;    AND WRITES THEM TO THE FILE.
  778. ;    IF THE "$" PARAMETER SPECIFIER
  779. ;    IS ENCOUNTERED, PARAMETER SUB-
  780. ;    STITUTION IS DONE
  781. ;
  782. PUTLP:
  783.     CALL    GETCHR    ;PICK UP A CHARACTER
  784.     JC    FLUSH    ;CY = NO MORE CHAR IN LINE
  785.     CPI    '^'    ;CONTROL-CHAR TRANSLATE PREFIX?
  786.     JNZ    NOTCX
  787.     CALL    GETCHR    ;YES, GET THE NEXT
  788.     JC    CCERR    ;ERROR: EARLY END OF INPUT
  789.     SUI    '@'    ;MAKE IT A CONTROL-CHAR
  790.     JC    CCERR    ;ERROR: TOO SMALL
  791.     CPI    ' '
  792.     JNC    CCERR    ;ERROR: TOO LARGE
  793. NOTCX:
  794.     CPI    PDELIM    ;PARAMETER SPECIFIER?
  795.     JNZ    STOBYT    ;IF NOT, JUST WRITE CHAR
  796.     LDA    OPTION    ;CHECK OPTION: '$' DOESN'T
  797.     CPI    OPT    ;  COUNT IN OPT MODE
  798.     MVI    A,PDELIM    ;(RESTORE THE '$')
  799.     JZ    STOBYT
  800.     CALL    LKAHED    ;PEEK AT NEXT CHAR
  801.     JC    PARERR    ;LINE ENDING MEANS PARAM ERR
  802.     CPI    PDELIM    ;ANOTHER "$"?
  803.     JNZ    SUBS    ;IF NOT THEN GO DO SUBSTITUTION
  804.     CALL    GETCHR    ;GET THE 2ND "$" (WE ONLY LOOKED
  805.             ;  AHEAD BEFORE)
  806. STOBYT:
  807.     CALL    PUTCHR    ;WRITE CHAR TO FILE
  808.     JMP    PUTLP
  809. ;
  810. ;    PARAMETER SUBSTITUTION...LOOKS UP THE
  811. ;    PARAMETER # AFTER THE "$" AND PLUGS IT
  812. ;    IN IF IT EXISTS.
  813. ;
  814. SUBS:
  815.     CALL    NUMTST    ;IT BETTER BE A NUMBER
  816.     JC    PARERR    ;  OTHERWISE PARAM ERROR
  817.     MVI    B,0    ;INITIALIZE PARM #
  818.     JMP    LPNTRY    ;WE JOIN LOOP IN PROGRESS...
  819. SUBLP:
  820.     CALL    LKAHED    ;LOOK AT NEXT CHAR
  821.     JC    DOSUBS    ;IF LINE EMPTY, THEN PLUG IN PARM
  822.     CALL    NUMTST    ;CHECK FOR NUMERIC
  823.     JC    DOSUBS    ;DONE IF NOT
  824. LPNTRY:
  825.     CALL    GETCHR    ;NOW REMOVE THE CHAR FROM INPUT STREAM
  826.     SUI    '0'    ;REMOVE ASCII BIAS
  827.     MOV    C,A    ;SAVE IT
  828.     MOV    A,B    ;OUR ACCUMULATED COUNT
  829.     ADD    A    ;MULTIPLY  BY TEN
  830.     ADD    A
  831.     ADD    B
  832.     ADD    A
  833.     ADD    C    ;THEN ADD IN NEW DIGIT
  834.     MOV    B,A    ;RESTORE COUNT
  835.     JMP    SUBLP
  836. ;
  837. ;    PERFORM THE SUBSTITUTION
  838. ;
  839. DOSUBS:
  840.     MOV    A,B    ;GET PARM #
  841.     DCR    A    ;MAKE ZERO RELATIVE
  842.     JM    PARERR    ;OOPS
  843.     CALL    LOOKUP    ;LOOK IT UP IN PARM TABLE
  844.     JC    PARERR    ;IT'S NOT THERE
  845.     MOV    B,A    ;LENGTH IN B
  846. SUBLP1:
  847.     INR    B    ;TEST B FOR ZERO
  848.     DCR    B
  849.     JZ    PUTLP    ;DONE
  850.     MOV    A,M    ;GET CHAR OF REAL PARAMETER
  851.     INX    H    ;POINT PAST FOR NEXT TIME
  852.     PUSH    H    ;SAVE REAL PARM POINTER
  853.     CALL    PUTCHR    ;PUT IT IN THE FILE
  854.     POP    H    ;GET BACK REAL PARM POINTER
  855.     DCR    B    ;COUNTDOWN
  856.     JMP    SUBLP1
  857. ;
  858. ;    COME HERE WHEN A LINE IS FINISHED,
  859. ;    AND WE NEED TO WRITE THE BUFFER TO DISK
  860. ;
  861. FLUSH:
  862.     LXI    D,SUBFCB
  863.     MVI    C,WRITEF
  864.     CALL    BDOS
  865.     ORA    A
  866.     JNZ    WRERR    ;CPM RETURNED A WRITE ERROR
  867.     RET
  868. ;
  869. ;    GETCHR GETS ONE CHAR FROM
  870. ;    LINE STORED IN MEMORY
  871. ;
  872. GETCHR:
  873.     LXI    H,GETCNT
  874.     MOV    A,M    ;PICK UP COUNT
  875.     DCR    A    ;REMOVE THIS CHAR
  876.     STC        ;PRESET ERROR
  877.     RM        ;RETURN CY IF OUT OF CHARS
  878.     MOV    M,A    ;UPDATE COUNT
  879.     LHLD    GETPTR    ;CURRENT CHAR POINTER
  880.     MOV    A,M    ;PICK UP CHAR
  881.     INX    H    ;BUMP POINTER
  882.     SHLD    GETPTR    ;PUT IT BACK
  883.     CMC        ;TURN CARRY OFF
  884.     RET
  885. ;
  886. ;    PUTCHR PUTS ONE CHAR TO
  887. ;    THE OUTPUT BUFFER
  888. ;
  889. PUTCHR:
  890.     LXI    H,PUTCNT
  891.     INR    M    ;INCREMENT COUNT
  892.     JM    LENERR    ;LINE WENT TO > 128 CHARS
  893.     LHLD    PUTPTR    ;GET BUFFER POINTER
  894.     ANI    7FH    ;MASK OUT MSB
  895.     MOV    M,A    ;PUT CHAR THERE
  896.     INX    H    ;BUMP POINTER
  897.     SHLD    PUTPTR    ;PUT IT BACK
  898.     RET        ;ALL DONE
  899. ;
  900. ;    LOOK AHEAD ONE CHAR IN
  901. ;    THE INPUT STREAM.  SET
  902. ;    CARRY IF NONE LEFT.
  903. ;
  904. LKAHED:
  905.     LDA    GETCNT
  906.     ORA    A    ;SEE IF COUNT IS DOWN TO ZERO
  907.     STC        ;PRE SET INDICATOR
  908.     RZ
  909.     MOV    A,M    ;PICK UP CHAR
  910.     CMC        ;TURN OFF CARRY FLAG
  911.     RET
  912. ;
  913. ;    LOOK UP PARAMETER WITH NUMBER IN
  914. ;    A REG. RETURN A=LENGTH OF PARM,
  915. ;    AND HL => PARAMETER
  916. ;
  917. LOOKUP:
  918.     CPI    NPAR
  919.     JNC    PAROVF    ;PARM # TOO HIGH
  920.     MOV    L,A
  921.     MVI    H,0    ;NOW HAVE 16 BIT NUMBER
  922.     DAD    H    ;DOUBLE FOR WORD OFFSET
  923.     LXI    D,TABLE
  924.     DAD    D    ;DO THE OFFSET
  925.     MOV    E,M    ;GET ADDRESS OF PARM
  926.     INX    H
  927.     MOV    D,M
  928.     MOV    A,D    ;ANYTHING THERE?
  929.     ORA    E
  930.     JNZ    LKUPOK
  931.     XRA    A    ;NO, ZERO LENGTH
  932.     RET
  933. LKUPOK:
  934.     XCHG        ;NOW IN DE
  935.     MOV    A,M    ;PICK UP LENGTH
  936.     INX    H    ;POINT PAST LENGTH
  937.     RET
  938. ;
  939. ;    UTILITY COMPARE SUBROUTINE
  940. ;
  941. COMPAR:
  942.     LDAX    D
  943.     CMP    M
  944.     RNZ
  945.     INX    H
  946.     INX    D
  947.     DCR    B
  948.     JNZ    COMPAR
  949.     RET
  950. ;
  951. ;    NUMERIC TEST UTILITY SUBROUTINE
  952. ;
  953. NUMTST:
  954.     CPI    '0'
  955.     RC
  956.     CPI    '9'+1
  957.     CMC
  958.     RET
  959. ;
  960. ;DECIMAL OUTPUT ROUTINE
  961. ;
  962. DECOUT:
  963.     PUSH    B
  964.     PUSH    D
  965.     PUSH    H
  966.     LXI    B,-10
  967.     LXI    D,-1
  968. ;
  969. DECOU2:
  970.     DAD    B
  971.     INX    D
  972.     JC    DECOU2
  973.     LXI    B,10
  974.     DAD    B
  975.     XCHG
  976.     MOV    A,H
  977.     ORA    L
  978.     CNZ    DECOUT
  979.     MOV    A,E
  980.     ADI    '0'
  981.     CALL    TYPE
  982.     POP    H
  983.     POP    D
  984.     POP    B
  985.     RET
  986. ;
  987. ; PRINT CR, LF ON CONSOLE
  988. ;
  989. CRLF:
  990.     MVI    A,CR
  991.     CALL    TYPE
  992.     MVI    A,LF
  993. ;
  994. ; PRINT CHAR IN A ON CONSOLE
  995. ;
  996. TYPE:
  997.     PUSH    H    ;SAVE REGS
  998.     PUSH    D
  999.     PUSH    B
  1000.     MOV    E,A    ;PUT IN E FOR CP/M
  1001.     MVI    C,FPCHAR
  1002.     CALL    BDOS    ;PRINT IT
  1003.     POP    B    ;RESTORE ALL
  1004.     POP    D
  1005.     POP    H
  1006.     RET
  1007. ;
  1008. ; CONVERT CHAR IN A TO UPPER CASE
  1009. ;
  1010. UCASE:
  1011.     CPI    'a'    ;VALIDATE CASE
  1012.     RC
  1013.     CPI    'z'+1
  1014.     RNC
  1015.     ANI    5FH    ;GOT LC, CONV TO UC
  1016.     RET
  1017. ;
  1018. ;    ERROR HANDLERS
  1019. ;
  1020. WRERR:
  1021.     CALL    ERRXIT
  1022.     DB    'Disk Full$'
  1023. NOMAKE:
  1024.     CALL    ERRXIT
  1025.     DB    'Directory Full$'
  1026. MEMERR:
  1027.     CALL    ERRXIT
  1028.     DB    'Memory Full$'
  1029. NOTFND:
  1030.     CALL    ERRXIT
  1031.     DB    'SUBMIT File Not Found$'
  1032. PARERR:
  1033.     CALL    ERRXIT
  1034.     DB    'Parameter$'
  1035. PAROVF:
  1036.     CALL    ERRXIT
  1037.     DB    'Too Many Parameters: $'
  1038. LENERR:
  1039.     CALL    ERRXIT
  1040.     DB    'Line too Long: $'
  1041. NOTEXT:
  1042.     CALL    ERRXIT
  1043.     DB    'SUBMIT File Empty$'
  1044. CCERR:
  1045.     CALL    ERRXIT
  1046.     DB    'Control Character$'
  1047. ERRXIT:
  1048.     LXI    D,SUBERR    ;PRINT ERROR HERALD
  1049.     MVI    C,PRINTF
  1050.     CALL    BDOS
  1051.     POP    D
  1052.     MVI    C,PRINTF
  1053.     CALL    BDOS
  1054.     LXI    D,ERRMSG    ;PRINT 2ND HALF MSG
  1055.     MVI    C,PRINTF
  1056.     CALL    BDOS
  1057.     LHLD    LINNUM        ;TELL LINE NUMBER
  1058.     CALL    DECOUT
  1059.     CALL    CRLF
  1060.     LXI    D,SUBFCB    ;DELETE THE $$$.SUB FILE
  1061.     MVI    C,DELETF
  1062.     CALL    BDOS
  1063.     JMP    CPBASE
  1064. ;
  1065. SUBERR:
  1066.     DB    CR,LF,'SUB Error -- $'
  1067. ERRMSG:
  1068.     DB    ' error on line number: $'
  1069. ;
  1070. ; PROMPT FOR COMMAND LINE INPUT
  1071. ;
  1072. PROMPT:
  1073.     DB    CR,LF,'Command Line? $'
  1074. ;
  1075. ;    INITIALIZE ALL VARIABLES
  1076. ;
  1077. INITVAR:
  1078.     LXI    H,VAR
  1079.     LXI    B,ENDVAR-VAR
  1080. INITLP:
  1081.     MVI    M,0    ;ZERO ENTIRE VAR AREA
  1082.     INX    H
  1083.     DCX    B
  1084.     MOV    A,B
  1085.     ORA    C
  1086.     JNZ    INITLP
  1087.     LXI    H,TABLE    ;INIT PARM TABLE POINTER
  1088.     SHLD    TBLPTR
  1089.     LXI    H,0FFFFH    ;MARK END OF TABLE
  1090.     SHLD    ENDTBL
  1091.     LXI    H,FREMEM    ;FREE MEMORY STARTS TXT AREA
  1092.     SHLD    TXTPTR
  1093.     MVI    A,80H    ;FORCE READ
  1094.     STA    IBP
  1095.     STA    CLCNT    ;FORCE CONSOLE READ
  1096.     RET
  1097. ;
  1098. ; PRINT HELP WITH PROGRAM OPTIONS
  1099. ;
  1100. HELP:
  1101.     LXI    D,HLPMSG    ;PRINT THE HELP STUFF
  1102.     MVI    C,PRINTF
  1103.     CALL    BDOS
  1104.     LHLD    SPSAVE    ;THEN RETURN W/NO WARM-BOOT
  1105.     SPHL
  1106.     RET
  1107. ;
  1108. HLPMSG:
  1109.     DB    CR,LF,'How to use SUB --',CR,LF
  1110.     DB    CR,LF,'SUB<CR>            - print this HELP message'
  1111.     DB    CR,LF,'SUB /A <text>        - Abort of SUBMIT File'
  1112.     DB    CR,LF,'SUB /AB <text>        - /A and Ring Bell'
  1113.     DB    CR,LF,'SUB /D <cmd lines>    - use SUMMARY (DO) mode'
  1114.     DB    CR,LF,'SUB /I<CR>        - go into Interactive mode'
  1115.     DB    CR,LF,'SUB <FILE> <PARMS>    - as in standard SUBMIT.COM'
  1116.     DB    CR,LF
  1117.     DB    CR,LF,'In "/I" (interactive) mode, SUB will prompt you'
  1118.     DB    CR,LF,'a line at a time for the SUBMIT job input...logical'
  1119.     DB    CR,LF,'lines may be combined on the same input line by sep-'
  1120.     DB    CR,LF,'erating them with semicolons.  Example:'
  1121.     DB    CR,LF,'  A>SUB /D STAT;DIR'
  1122.     DB    CR,LF,'specifies two commands on the same input line.',CR,LF
  1123.     DB    CR,LF,'Submitted jobs may be nested...SUB does not erase'
  1124.     DB    CR,LF,'any existing submit job (appends to them instead).'
  1125.     DB    CR,LF
  1126.     DB    CR,LF,'To insert a control character into the output, pre-'
  1127.     DB    CR,LF,'fix it with a "^" (works in any mode).'
  1128.     DB    CR,LF,'$'
  1129. ;
  1130. ;    VARIABLE STORAGE
  1131. ;
  1132. VAR    EQU    $
  1133. ;
  1134. AFLAG:
  1135.     DB    0    ;ABORT FLAG (0=NO)
  1136. TXTPTR:
  1137.     DW    0    ;FREE MEMORY POINTER
  1138. TBLPTR:
  1139.     DW    0    ;POINTER TO PARM TABLE
  1140. DDISK:
  1141.     DB    0    ;DEFAULT DISK NUMBER
  1142. DUSER:
  1143.     DB    0    ;DEFAULT USER NUMBER
  1144. LINNUM:
  1145.     DW    0    ;CURRENT LINE NUMBER
  1146. PREV:
  1147.     DW    0    ;POINTER TO PREV LINE
  1148. GETCNT:
  1149.     DB    0    ;COUNTER FOR 'GET'
  1150. GETPTR:
  1151.     DW    0    ;POINTER FOR 'GET'
  1152. PUTPTR:
  1153.     DW    0    ;POINTER FOR 'PUT'
  1154. IBP:
  1155.     DB    0    ;INPUT BUFFER POINTER
  1156. CLPTR:
  1157.     DW    0    ;COMMAND LINE POINTER
  1158. CLFLAG:
  1159.     DB    0    ;USE CP/M CMD LINE FLAG
  1160. BELL$FLAG:
  1161.     DB    0    ;RING BELL ON ABORT FLAG
  1162. OPTION:
  1163.     DB    0    ;OPT OPTION FLAG STORE
  1164. TABLE:
  1165.     DS    NPAR*3    ;PARAMETER TABLE
  1166. ENDTBL:
  1167.     DW    0FFFFH    ;END OF PARAMETER TABLE
  1168. ;
  1169. ENDVAR    EQU    $
  1170. ;
  1171. ; COMMAND LINE BUFFER...NOT INITIALIZED
  1172. ;
  1173. CLBUF:
  1174.     DB    128    ;BUFFER LENGTH
  1175. CLCNT:
  1176.     DB    0    ;CHARACTER COUNTER
  1177. CLTEXT:
  1178.     DS    128    ;THE BUFFER ITSELF
  1179. ;
  1180. SPSAVE:
  1181.     DW    0    ;STACK POINTER SAVE
  1182. ;
  1183. ;
  1184. ;    FCB FOR $$$.SUB
  1185. ;
  1186. SUBFCB:
  1187.     DB    SUBDRV    ;DRIVE SPECIFIER
  1188.     DB    '$$$     '
  1189. SUBTYP:
  1190.     DB    'SUB'
  1191.     DW    0,0,0,0    ;INITIALIZE REST OF FCB
  1192.     DW    0,0,0,0
  1193.     DW    0,0,0,0
  1194. ;
  1195. ;    STACK AREA
  1196. ;
  1197.     DS    200    ;WHY NOT?
  1198. STACK    EQU    $
  1199. FREMEM    EQU    $
  1200. ;
  1201.     END    SUB
  1202.  
  1203.