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 / ZCPR2 / SUB2.ASM < prev    next >
Assembly Source File  |  2000-06-30  |  32KB  |  1,434 lines

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