home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol085 / supersub.asm < prev    next >
Encoding:
Assembly Source File  |  1983-08-29  |  19.5 KB  |  838 lines

  1. ;
  2. ;********************************************************
  3. ;*        Extended Submit for            *
  4. ;*            CP/M                *
  5. ;********************************************************
  6. ;
  7. ; Revised 09/13/81 (RGF): added control character translation
  8. ;              fixed bug in line number reporting
  9. ;
  10. ;        Version 1.1        by Ron Fowler
  11. ;        2/18/81 (first written)     Westland, MI
  12. ;
  13. ; Published in Lifelines, Volume II, Number 8- Jan 82
  14. ;
  15. ;
  16. ;    This program is intended as a replacement for the
  17. ; SUBMIT program provided with CP/M.  It provides several
  18. ; new facilities:
  19. ;    1) Nestable SUBMIT runs
  20. ;    2) Interactive entry of SUBMIT job (no need
  21. ;       to use an editor for simple SUBMIT runs)
  22. ;    3) Command line entry of small SUBMIT jobs
  23. ;    4) Ability to enter blank lines in an edited
  24. ;       SUBMIT file
  25. ;    5) User customization of number of parameters
  26. ;       and drive to send $$$.SUB to
  27. ;
  28. ;
  29. ;  Define Booleans
  30. ;
  31. false    equ    0
  32. true    equ    not false
  33. ;
  34. ;*************************************************************
  35. ;    --- User Customizable options ---
  36. ;
  37. npar    equ    10    ; Number of Allowable Parameters
  38. subdrv    equ    0    ; Make 0 for dflt - 1,2,3 for A,B,C
  39. quiet    equ    false    ; Set to true to eliminate sign-on msg
  40. cpbase    equ    0    ; Set to 4200h for Heath CP/M
  41. ;
  42. ;
  43. ;
  44. ;***************************************************************
  45. ;
  46. ;  CP/M Definitions
  47. ;
  48. fpchar    equ    2    ; Print char function
  49. printf    equ    9    ; Print string function
  50. rdbuf    equ    10    ; Read console buffer
  51. openf    equ    15    ; Open file function
  52. closef    equ    16    ; Close file function
  53. deletf    equ    19    ; Delete file function
  54. readf    equ    20    ; Read record function
  55. writef    equ    21    ; Write record function
  56. makef    equ    22    ; Make (create) file function
  57. ;
  58. bdos    equ    cpbase+5
  59. ;
  60. fcb    equ    5ch    ; Default file control block
  61. fcbrc    equ    15    ; FCB Offset to record  count
  62. fcbnr    equ    32    ; FCB Offset to next record
  63. fn    equ    1    ; FCB Offset to file name
  64. ft    equ    9    ; FCB Offset to file type
  65. tbuf    equ    cpbase+80h    ; Default buffer
  66. tpa    equ    cpbase+100h    ; Transient program area
  67. ;
  68. putcnt    equ    tbuf    ; Counter for output chars
  69. ;
  70. ;  Define Some Text Characters
  71. ;
  72. cr    equ    13    ; Carriage return
  73. lf    equ    10    ; Line feed
  74. tab    equ    9    ; Tab Char
  75. ;
  76. ;  Start of Program Code
  77. ;
  78.     org    tpa
  79. ;
  80. ;    Get the ball rolling
  81. ;
  82. submit:    lxi    h,0    ; Save stack in case
  83.     dad    sp    ;  only help requested
  84.     shld    spsave    ; (Not otherwise used)
  85.     lxi    sp,stack
  86.     call    start
  87. ;
  88. ;  Sign on Message
  89. ;
  90.     if    not quiet
  91.     db    'SuperSUB V1.1'
  92.     endif
  93. ;
  94.     db    cr,lf,'$'    ; Newline even if quiet
  95. ;
  96. start:    pop    d    ; Retrieve string pointer
  97.     mvi    c,printf
  98.     lda    fcb+1    ; Anything on CMd line?
  99.     cpi    ' '
  100.     jz    help    ; No, Go print help
  101.     call    bdos    ; Print the sign-on
  102.     call    initvar    ; Initialize the variable area
  103.     call    getpar    ; Get command line parameters
  104.     call    setup    ; Set up read of submit file
  105.     call    rdfile    ; Read the submit file
  106.     call    wrset    ; Set up write of "$$$.SUB"
  107.     call    wrsub    ; Write "$$$.SUB"
  108.     jmp    cpbase    ; Go start the SUBMIT
  109. ;
  110. ;
  111. ;  Setup sets up the file control block
  112. ;  for reading the the .SUB text file
  113. ;
  114. setup:    lxi    h,fcb+ft  ; Look at 1st char of
  115.     mov    a,m    ;    file type.  If it is
  116.     cpi    ' '    ;    blank, then go move
  117.     jz    putsub    ;    "SUB" into FT field
  118.     lxi    d,subtyp; It's not blank to make
  119.     mvi    b,3    ;   sure it's already
  120.     call    compar    ;    "SUB"
  121.     jnz    notfnd    ; If not, it's an error
  122.     ret
  123. ;
  124. ;  Move "SUB" into the file type
  125. ;
  126. putsub:    xchg
  127.     lxi    h,subtyp    ; By convention, move
  128.     mvi    b,3        ;  @HL to @DE
  129.     call    move
  130.     ret
  131. ;
  132. ;  Move # bytes in B Register from @HL to @DE
  133. ;
  134. move:    mov    a,m    ; Pick up
  135.     stax    d    ; Put down
  136.     inx    h    ; I'm sure
  137.     inx    d    ;  you've seen this
  138.     dcr    b    ;  before..
  139.     jnz    move    ;
  140.     ret
  141. ;
  142. ;  Getpar moves the substitution parameters specified
  143. ; in the command line into memory, and stores their
  144. ; addresses in the parameter table.  This allows
  145. ; substitution of $1, $2, etc., in the SUBMIT commands
  146. ; with their actual values specified in the command
  147. ; line.
  148. ;
  149. getpar:    lxi    h,tbuf+1    ; Where we find the command tail
  150.     call    scanto    ; Skip submit file name
  151.     sta    option    ; First char of cmd line is option
  152.     rc        ; Line ended?
  153.     cpi    '/'    ; No, check option
  154.     jnz    glpo    ; Not keyboard input, read file
  155.     inx    h    ; point past '/'
  156. slscan:    shld    clptr    ; Save cmd line ptr
  157.     mov    a,m    ; Kbd is source, get EOL flag
  158.     sta    clflag    ; Save as EOL flag
  159.     cpi    ' '    ; Allow spaces after '/'
  160.     rnz        ; Not non-blank - done
  161.     inx    h    ; Else continue scan
  162.     jmp    slscan
  163. glpo:    mov    a,m    ; Input is from a .SUB file. This
  164.     inx    h    ;   code skips over the name of
  165.     ora    a    ;   the SUB file to get to the
  166.     rz        ;   command line parameters
  167.     cpi    ' '
  168.     jz    glp
  169.     cpi    tab
  170.     jnz    glpo
  171. glp:    call    scanto    ; Pass up the blanks
  172.     rc        ; CY returned if end of cmd line
  173.     call    putpar    ; Not put the parameter into Mem
  174.     rc        ; CY returned if end of cmd line
  175.     jmp    glp    ; Get them all.
  176. ;
  177. ;  SCANTO scans past blanks to the first non-blank.  If
  178. ; end of command line is found, returns carry set.
  179. ;
  180. scanto:    mov    a,m
  181.     inx    h
  182.     ora    a    ; Set flags on zero
  183.     stc        ; In case zero found
  184.     rz
  185.     cpi    ' '
  186.     jz    scanto    ; Scan past blanks
  187.     cpi    tab    ; Do tabs to, just for
  188.     jz    scanto    ;  good measure.
  189.     dcx    h    ; Found char, point back to it
  190.     ora    a    ; insure carry clear
  191.     ret
  192. ;
  193. ;  PUTPAR puts the parameter pointed to by HL into
  194. ; memory pointed to by "TXTPTR".  Also stores the
  195. ; address of the parameter into the parameter table
  196. ; for easy access later, when we write $$$.SUB
  197. ;
  198. putpar:    push    h    ; Save pointer to parm
  199.     lhld    txtptr    ; Next free memory
  200.     xchg        ;   into DE
  201.     lhld    tblptr    ; Next pree area of table
  202.     mov    a,m    ; Non-zero in table
  203.     ora    a    ;  indicates table
  204.     jnz    parovf    ;  overflow
  205.     mov    m,e    ; Store the parm adrs
  206.     inx    h
  207.     mov    m,d
  208.     inx    h
  209.     shld    tblptr    ; Save table pntr for next time
  210.     pop    h    ; Get back parm pointer
  211.     push    d    ; Save free mem pointer because
  212.             ;   we will have to have it back
  213.             ;   later to store the length
  214.     inx    d    ; Point past length storage
  215.     mvi    b,0    ; Initialize length of parm
  216. pplp:    mov    a,m    ; Get next byte of parm
  217.     inx    h
  218.     ora    a    ; Test for end of cmd line
  219.     jz    pp2    ; Jump if End
  220.     cpi    ' '    ; Test for end of Command
  221.     jz    pp2
  222.     cpi    tab    ; Tab also ends command
  223.     jz    pp2
  224.     stax    d    ; Put parameter byte-by-byte
  225.     inx    d    ;  into free memory
  226.     inr    b    ; Bump length
  227.     jmp    pplp
  228. pp2:    xchg
  229.     shld    txtptr    ; New free memory pointer
  230.     pop    h    ; Remember our length pointer?
  231.     mov    m,b    ; Store the length
  232.     xchg        ; Have to retn HL > cmd line
  233.     ora    a    ; Now return end of line flag
  234.     stc
  235.     rz        ; Return CY is zero (EOL Mark)
  236.     cmc
  237.     ret
  238. ;
  239. ;  RDFILE reads the .SUB file specified
  240. ; in the SUBMIT command into memory
  241. ;
  242. rdfile:    lxi    h,0    ; Init line number
  243.     shld    linnum
  244.     lda    option    ; Using a file?
  245.     cpi    '/'    ; Option tells
  246.     jz    line    ; Jump if not
  247.     lxi    d,fcb    ; We are, open it.
  248.     mvi    c,openf
  249.     call    bdos
  250.     inr    a    ; if 0FFh returned,
  251.     jz    notfnd    ;   then file not found.
  252. line:    lhld    linnum    ; Bump line number
  253.     inx    h
  254.     shld    linnum
  255.     lhld    prev    ; Get prev line pointer
  256.     xchg
  257.     lhld    txtptr    ; Get current free mem pointer
  258.     shld    prev    ; Make it the prev line (for next pass)
  259.     mov    m,e    ; Store at begin of current line.
  260.     inx    h    ;  a pointer to the previous
  261.     mov    m,d
  262.     inx    h
  263.     push    h    ; Later we will put length here
  264.     inx    h    ; Skip past length
  265.     mvi    c,0    ; Initialize length to zero
  266. llp:    call    gnb    ; Get next byte from input source
  267.     jc    eof    ; CY set if end of file found
  268.     call    ucase    ; Convert to upper case
  269.     cpi    1ah    ;  See if CP/M End of File
  270.     jz    eof
  271.     cpi    lf    ; Ignore linefeeds
  272.     jz    llp
  273.     cpi    cr    ; If it's a carriage return,
  274.     jz    eol    ;   then do end of line
  275.     mov    m,a    ; Store all others into memory
  276.     inx    h
  277.     call    size    ; Make sure no memory overflow
  278.     inr    c    ; Bump char count
  279.     jm    lenerr    ; Max of 128 chars per line
  280.     jmp    llp    ; Go to next char
  281. ;
  282. ;  Do End of Line Sequence 
  283. ;
  284. eol:    shld    txtptr    ; Save free memory pointer
  285.     pop    h    ; Current line's length pointer
  286.     mov    m,c    ; Store length away
  287.     jmp    line    ; Go do next line
  288. ;
  289. ;  End of Text File
  290. ;
  291. eof:    shld    txtptr    ; Save free memory pointer
  292.     pop    h    ; Current line's length pointer
  293.     mov    m,c    ; Store length away
  294.     ret        ; All done reading SUB file
  295. ;
  296. ;  Get next byte from Input File
  297. ;
  298. gnb:    push    h    ; Don't alter anybody
  299.     push    d
  300.     push    b
  301.     lda    option    ; Input from .SUB file?
  302.     cpi    '/'    ; Told by orig cmd line option
  303.     jnz    nslash    ; Jump if we are
  304.     call    gnbkbd    ; No, get a byte from kbd input
  305.     jmp    gnbxit    ; Then leave
  306. nslash:    lda    ibp    ; Get buffer pointer
  307.     ora    a    ; Past end?
  308.     cm    fill    ; Wrapped around
  309.     jnc    gnb1    ; No end of file
  310.     mvi    1,1ah    ; Fake EOF
  311. gnb1:    mov    e,a    ; put in DE
  312.     mvi    d,0
  313.     inr    a    ; Point to next
  314.     sta    ibp    ; Put away
  315.     lxi    h,tbuf    ; Now offset into buff
  316.     dad    d
  317.     mov    a,m    ; Get char there
  318. gnbxit:    pop    b    ; Restore everybody
  319.     pop    d
  320.     pop    h
  321.     ora    a    ; Turn on carry
  322.     ret
  323. ;
  324. ;  Fill input buffer
  325. ;
  326. fill:    mvi    c,readf
  327.     lxi    d,fcb
  328.     call    bdos
  329.     ora    a
  330.     mvi    a,0
  331.     stc
  332.     rnz        ; Rtn CY=EOF
  333.     cmc        ; No EOF, No CY
  334.     ret
  335. ;
  336. ;  Come here to get a .SUB character when
  337. ;  we're not using a .SUB file ('/' option)
  338. ;
  339. gnbkbd:    lda    clflag    ; Use CP/M Cmd line?
  340.     ora    a
  341.     jnz    gnbcl    ; Then go do it
  342.     lda    clcnt    ; Not, check local
  343.     ora    a    ;   cmd line char count
  344.     cm    clfill    ; Refill when it wraps back
  345.     jc    gkend    ; Got carry (from CLFILL), return EOF
  346.     dcr    a    ; Count down
  347.     sta    clcnt
  348.     jp    gnbcl    ; If plus, buffer not empty
  349.     mvi    a,cr    ; Out of chars, return a CR
  350.     ret
  351. ;
  352. gkend:    mvi    a,1ah    ; Return EOF
  353.     ret
  354. ;
  355. ;  Get next byte of input from cmd line @clptr
  356. ;
  357. gnbcl:    lhld    clptr    ; Load the pointer
  358.     mov    a,m    ; Get the char
  359.     inx    h    ; Bump pointer for next time
  360.     shld    clptr
  361.     cpi    ';'    ; Logical end-of-line?
  362.     jnz    nsemi    ; Jump if not
  363.     mvi    a,cr    ; Yes, translate it
  364.     ret
  365. nsemi:    ora    a    ; Physical End-of-Line
  366.     rnz        ;  This only needed when input
  367.             ;  Source is orig cpm cmd line
  368.     mvi    a,1ah    ; Translate that to End of File
  369.     ret
  370. ;
  371. ;  Subroutine to re-fill the local command line
  372. ;
  373. clfill:    lxi    d,prompt    ; Print a prompt
  374.     mvi    c,printf    ; Use CP/M function 9
  375.     call    bdos
  376.     lxi    d,clbuf    ; Now fill the buffer
  377.     mvi    c,rdbuf
  378.     call    bdos
  379.     lda    clcnt    ; Return with count in A
  380.     lxi    h,cltext    ; Reset the cmd line pointer
  381.     shld    clptr
  382.     ora    a    ; Set CY on len NZ
  383.     stc
  384.     rz
  385.     cmc
  386.     ret
  387. ;
  388. ;  Make sure no memory overflow
  389. ;
  390. size:    lda    bdos+2    ; Highest page pointer
  391.     dcr    a    ; Make it be under BDOS
  392.     cmp    h    ; Check it against current page
  393.     rnc        ; NC= all okay
  394.     jmp    memerr    ; Otherwise Abort
  395. ;
  396. ;  Set up the $$$.SUB file
  397. ;   For Writing
  398. ;
  399. wrset:    lxi    d,subfcb
  400.     mvi    c,openf
  401.     call    bdos    ; Open the file
  402.     inr    a    ; Check CPM return
  403.     jz    none1    ; None exists already
  404. ;
  405. ;  $$$.SUB exists, so set
  406. ;  FCB to append to it
  407. ;
  408.     lda    subfcb+fcbrc    ; Get record count
  409.     sta    subfcb+fcbnr    ; Make that next rec
  410.     ret
  411. ;
  412. ;  Come here when no $$$.SUB exists
  413. ;
  414. none1:    lxi    d,subfcb
  415.     mvi    c,makef
  416.     call    bdos
  417.     inr    a
  418.     jz    nomake    ; 0FFh=Can't create file
  419.     ret
  420. ;
  421. ;  Write the "$$$.SUB" file
  422. ;
  423. wrsub:    lhld    prev    ; This code scans backward
  424.     mov    a,h    ;  Thru the file stored in
  425.     ora    l    ;  memory to the first non-
  426.     jz    notext    ;  nul line.  If none is
  427.     mov    e,m    ;  found, Aborts
  428.     inx    h
  429.     mov    d,m    ; Here, we pick up pntr to prev line
  430.     inx    h    ; Now we point to length
  431.     xchg        ; We need to store away
  432.     shld    prev    ;  pointer to prev line
  433.     xchg
  434.     mov    a,m    ; Now pick up the length
  435.     ora    a    ; Set Z flag on length
  436.     jnz    wrntry    ; Got line w/length: go do it
  437.     lhld    linnum    ; Nothing here, fix line number
  438.     dcx    h    ; (working backward now)
  439.     shld    linnum
  440.     jmp    wrsub
  441. wrlop:    lhld    prev    ; Get prev line pointer
  442.     mov    a,h
  443.     ora    l    ; If there is no prev line
  444.     jz    close    ;  then we are done
  445.     mov    e,m    ; Else set up prev for next
  446.     inx    h    ;   pass thru here
  447.     mov    d,m
  448.     inx    h
  449.     xchg        ; Now store it away
  450.     shld    prev
  451.     xchg
  452. wrntry:    call    putlin    ; Write the line to the file
  453.     lhld    linnum    ; Bump the line number
  454.     dcx    h    ; Down (working back now)
  455.     shld    linnum
  456.     jmp    wrlop
  457. ;
  458. ;  $$$.SUB is written, Close the file
  459. ;
  460. close:    lxi    d,subfcb
  461.     mvi    c,closef
  462.     jmp    bdos
  463. ;
  464. ;  This subroutine writes a line
  465. ; to the $$$.SUB file buffer,
  466. ; and flushes the buffer after
  467. ; the line is written.
  468. ;
  469. putlin:    mov    a,m    ; Pick up length byte
  470.     inx    h    ; Point past it
  471.     sta    getcnt    ; Make a count for "GET"
  472.     shld    getptr    ; Make a pointer for "get"
  473.     lxi    h,tbuf+1    ; Text goes after length
  474.     shld    putptr    ; Make pointer for "Put"
  475.     xra    a    ; Initialize PUT count
  476.     sta    putcnt
  477.     mov    b,l    ; Count for clear loop
  478. clr:    mov    m,a    ; Zero out buffer loc
  479.     inx    h
  480.     inr    b    ; Count
  481.     jnz    clr
  482. ;
  483. ;  This loop collects characters
  484. ; from the line stored in memory
  485. ; and writes them to the file.
  486. ; If the "$" parameter specifier
  487. ; is encountered, parameter sub-
  488. ; stitution is done.
  489. ;
  490. putlp:    call    getchr    ; Pick up a character
  491.     jc    flush    ; CY = no more char in line
  492.     cpi    '^'    ; Control char translate prefix?
  493.     jnz    notcx
  494.     call    getchr    ; Yes, get the next
  495.     jc    ccerr    ; Error: Early end of input
  496.     sui    '@'    ; Make it a control-char
  497.     jc    ccerr    ; Error: Too small
  498.     cpi    ' '
  499.     jnc    ccerr    ; Error: Too large
  500. notcx:    cpi    '$'    ; Parameter specifier?
  501.     jnz    stobyt    ; If not, just write char
  502.     lda    option    ; Check option: '$' doesn't
  503.     cpi    '/'    ;  count in '/' mode
  504.     mvi    a,'$'    ; (Restore the '$')
  505.     jz    stobyt
  506.     call    lkahed    ; Peek at next char
  507.     jc    parerr    ; Line ending means param err
  508.     cpi    '$'    ; Another "$"?
  509.     jnz    subs    ; If not then go do substitution
  510.     call    getchr    ; Get the 2nd "$" (We only looked
  511.             ;  ahead before)
  512. stobyt:    call    putchr    ; Write char to file
  513.     jmp    putlp
  514. ;
  515. ;  Parameter substitution...Looks up the
  516. ; parameter # after the "$" and plugs it
  517. ; in if it exists.
  518. ;
  519. subs:    call    numtst    ; It better be a number
  520.     jc    parerr    ;  otherwise param error
  521.     mvi    b,0    ; Initialize parm #
  522.     jmp    lpntry    ; We join loop in progress...
  523. sublp:    call    lkahed    ; Look at next char
  524.     jc    dosubs    ; If line empty, then plug in parm
  525.     call    numtst    ; Check for numric
  526.     jc    dosubs    ; Done in not
  527. lpntry:    call    getchr    ; Now remove the char from input stream
  528.     sui    '0'    ; Remove ASCII bias
  529.     mov    c,a    ; Save it
  530.     mov    a,b    ; Our accumulated count
  531.     add    a    ; Multiply by ten
  532.     add    a
  533.     add    b
  534.     add    a
  535.     add    c    ; then add in new digit
  536.     mov    b,a    ; restore count
  537.     jmp    sublp
  538. ;
  539. ;  Perform the substitution
  540. ;
  541. dosubs:    mov    a,b    ; Get parm #
  542.     dcr    a    ; Make zero relative
  543.     jm    parerr    ; oops
  544.     call    lookup    ; Look it up in parm table
  545.     jc    parerr    ; It's not there
  546.     mov    b,a    ; Length in B
  547. sublp1:    inr    b    ; Test B for zero
  548.     dcr    b
  549.     jz    putlp    ; Done
  550.     mov    a,m    ; Get char of real parameter
  551.     inx    h    ; Point past for next time
  552.     push    h    ; Save real parm pointer
  553.     call    putchr    ; Put it in the file
  554.     pop    h    ; Get back real parm pointer
  555.     dcr    b    ; Countdown
  556.     jmp    sublp1
  557. ;
  558. ;  Come here when a line is finished,
  559. ; and we need to write the buffer to disk.
  560. ;
  561. flush:    lxi    d,subfcb
  562.     mvi    c,writef
  563.     call    bdos
  564.     ora    a
  565.     jnz    wrerr    ; CPM returned a write error
  566.     ret
  567. ;
  568. ;  GETCHR gets one char from
  569. ; line stored in memory
  570. ;
  571. getchr:    lxi    h,getcnt
  572.     mov    a,m    ; Pick up count
  573.     dcr    a    ; Remove this char
  574.     stc        ; Preset error
  575.     rm        ; Return CY if out of chars
  576.     mov    m,a    ; Update count
  577.     lhld    getptr    ; Current char pointer
  578.     mov    a,m    ; Pick up char
  579.     inx    h    ; Bump pointer
  580.     shld    getptr    ; Put it back
  581.     cmc        ; Turn carry off
  582.     ret
  583. ;
  584. ;  PUTCHR puts one char to
  585. ; the output buffer
  586. ;
  587. putchr:    lxi    h,putcnt
  588.     inr    m    ; Increment count
  589.     jm    lenerr    ; Line went to > 128 chars
  590.     lhld    putptr    ; Get buffer pointer
  591.     mov    m,a    ; Put char there
  592.     inx    h    ; Bump pointer
  593.     shld    putptr    ; Put it back
  594.     ret        ; All done
  595. ;
  596. ;  Look ahead one char in
  597. ; the input stream.  Set
  598. ; carry if none left.
  599. ;
  600. lkahed:    lda    getcnt
  601.     ora    a    ; See if count is down to zero
  602.     stc        ; Preset indicator
  603.     rz
  604.     mov    a,m    ; Pick up char
  605.     cmc        ; Turn off carry flag
  606.     ret
  607. ;
  608. ;  Look up parameter with number in
  609. ; a reg.  Return A=length of parm,
  610. ; and HL => parameter
  611. ;
  612. lookup:    cpi    npar
  613.     jnc    parovf    ; Parm # too high
  614.     mov    l,a
  615.     mvi    h,0    ; Now have 16 bit number
  616.     dad    h    ; Double for word offset
  617.     lxi    d,table
  618.     dad    d    ; Do the offset
  619.     mov    e,m    ; Get the address of parm
  620.     inx    h
  621.     mov    d,m
  622.     mov    a,d    ; Anything there?
  623.     ora    e
  624.     jnz    lkupok
  625.     xra    a    ; No, zero length
  626.     ret
  627. lkupok:    xchg        ; Now in DE
  628.     mov    a,m    ; Pick up length
  629.     inx    h    ; Point past length
  630.     ret
  631. ;
  632. ;  Utility compare subroutine
  633. ;
  634. compar:    ldax    d
  635.     cmp    m
  636.     rnz
  637.     inx    h
  638.     inx    d
  639.     dcr    b
  640.     jnz    compar
  641.     ret
  642. ;
  643. ;  Numeric Test Utility Subroutine
  644. ;
  645. numtst:    cpi    '0'
  646.     rc
  647.     cpi    '9'+1
  648.     cmc
  649.     ret
  650. ;
  651. ;  Decimal output routine
  652. ;
  653. decout:    push    b
  654.     push    d
  655.     push    h
  656.     lxi    b,-10
  657.     lxi    d,-1
  658. ;
  659. decou2:    dad    b
  660.     inx    d
  661.     jc    decou2
  662.     lxi    b,10
  663.     dad    b
  664.     xchg
  665.     mov    a,h
  666.     ora    l
  667.     cnz    decout
  668.     mov    a,e
  669.     adi    '0'
  670.     call    type
  671.     pop    h
  672.     pop    d
  673.     pop    b
  674.     ret
  675. ;
  676. ;  Print CR, LF on console
  677. ;
  678. crlf:    mvi    a,cr
  679.     call    type
  680.     mvi    a,lf
  681. ;
  682. ;  Print char in A on console
  683. ;
  684. type:    push    h
  685.     push    d
  686.     push    b
  687.     mov    e,a    ; Put in E for CP/M
  688.     mvi    c,fpchar
  689.     call    bdos    ; Print it
  690.     pop    b
  691.     pop    d
  692.     pop    h
  693.     ret
  694. ;
  695. ;  Convert char in A to Upper Case
  696. ;
  697. ucase:    cpi    'a'    ; Validate case
  698.     rc
  699.     cpi    'z'+1
  700.     rnc
  701.     ani    5fh    ; Got LC, conv to UC
  702.     ret
  703. ;
  704. ;  Error Handlers
  705. ;
  706. wrerr:    call    errxit
  707.     db    'Disk full$'
  708. nomake:    call    errxit
  709.     db    'Directory full$'
  710. memerr:    call    errxit
  711.     db    'Memory full$'
  712. notfnd:    call    errxit
  713.     db    'Submit file not found$'
  714. parerr:    call    errxit
  715.     db    'Parameter$' 
  716. parovf:    call    errxit
  717.     db    'Too many parameters:$'
  718. lenerr:    call    errxit
  719.     db    'Line too long:$'
  720. notext:    call    errxit
  721.     db    'Submit file empty$'
  722. ccerr:    call    errxit
  723.     db    'Control character$'
  724. errxit:    pop    d
  725.     mvi    c,printf
  726.     call    bdos
  727.     lxi    d,errmsg    ; Print the 2nd half msg
  728.     mvi    c,printf
  729.     call    bdos
  730.     lhld    linnum        ; Tell line number
  731.     call    decout
  732.     call    crlf
  733.     lxi    d,subfcb    ; Delete the $$$.SUB file
  734.     mvi    c,deletf
  735.     call    bdos
  736.     jmp    cpbase
  737. ;
  738. errmsg:    db    ' error on line number: $'
  739. ;
  740. ; Prompt for command line input
  741. prompt:    db    cr,lf,'*$'
  742. ;
  743. ;  Initialize all variables
  744. ;
  745. initvar:
  746.     lxi    h,var
  747.     lxi    b,endvar-var
  748. initlp:    mvi    m,0        ; Zero entire var area
  749.     inx    h
  750.     dcx    b
  751.     mov    a,b
  752.     ora    c
  753.     jnz    initlp
  754.     lxi    h,table    ; Init parm table pointer
  755.     shld    tblptr
  756.     lxi    h,0ffffh; Mark end of table
  757.     shld    endtbl
  758.     lxi    h,fremem; Free memory starts txt area
  759.     shld    txtptr
  760.     mvi    a,80h    ; Force read
  761.     sta    ibp
  762.     sta    clcnt    ; Force console read
  763.     ret
  764. ;
  765. ;  Print help with program options
  766. ;
  767. help:    lxi    d,hlpmsg  ; Print the help stuff
  768.     mvi    c,printf
  769.     call    bdos
  770.     lhld    spsave    ; Then return w/no warm boot
  771.     sphl
  772.     ret
  773. ;
  774. hlpmsg:    db    cr,lf,'How to use SUPERSUB:',cr,lf
  775.     db    cr,lf,'SUPERSUB<CR>        :print this HELP message'
  776.     db    cr,lf,'SUPERSUB /<CR>        :go into interactive mode'
  777.     db    cr,lf,'SUPERSUB /<cmd lines>    :use SUMMARY mode'
  778.     db    cr,lf,'SUPERSUB <FILE> <PARMS>    :as in standard SUBMIT.COM'
  779.     db    cr,lf
  780.     db    cr,lf,'IN "/" (interactive) mode, SUPERSUB will prompt you'
  781.     db    cr,lf,'a line at a time for the SUBMIT job input...logical'
  782.     db    cr,lf,'lines may be combined on the same input line by sep-'
  783.     db    cr,lf,'erating them with semicolons.  Example:'
  784.     db    cr,lf,'   A>SUPERSUB /STAT;DIR'
  785.     db    cr,lf,'specifies two commands on the same input line.',cr,lf
  786.     db    cr,lf,'Submitted jobs may be nested...SUPERSUB does not erase'
  787.     db    cr,lf,'any existing submit job (appends to them instead).'
  788.     db    cr,lf
  789.     db    cr,lf,'To insert a control character into the output, pre-'
  790.     db    cr,lf,'fix it with a "^" (works in any mode).'
  791.     db    cr,lf,'$'
  792. ;
  793. ;  Variable Storage
  794. ;
  795. var    equ    $
  796. ;
  797. txtptr:    dw    0    ; Free memory pointer
  798. tblptr:    dw    0    ; Pointer to Parm Table
  799. linnum:    dw    0    ; Current line number
  800. prev:    dw    0    ; Pointer to previous line
  801. getcnt:    db    0    ; Counter for 'Get'
  802. getptr:    dw    0    ; Pointer for 'Get'
  803. putptr:    dw    0    ; Pointer for 'Put'
  804. ibp:    db    0    ; Input Buffer Pointer
  805. clptr:    dw    0    ; Command Line Pointer
  806. clflag:    db    0    ; Use CP/M cmd line flag
  807. option:    db    0    ; '/' option flag store
  808. table:    ds    npar*3    ; Parameter table
  809. endtbl:    dw    0    ; End of Parameter table
  810. ;
  811. endvar    equ    $
  812. ;
  813. ;  Command Line Buffer... Not Initialized
  814. ;
  815. clbuf:    db    128    ; Buffer length
  816. clcnt:    db    0    ; Character Counter
  817. cltext:    ds    128    ; The buffer itself
  818. ;
  819. spsave:    dw    0    ; Stack Pointer Save
  820. ;
  821. ;
  822. ;  FCB for $$$.SUB
  823. ;
  824. subfcb:    db    subdrv    ; Driver Specifier
  825.     db    '$$$     '
  826. subtyp:    db    'SUB'
  827.     dw    0,0,0,0    ; Initialize rest of FCB
  828.     dw    0,0,0,0
  829.     dw    0,0
  830. ;
  831. ;  Stack Area
  832. ;
  833.     ds    200
  834. stack    equ    $
  835. fremem    equ    $
  836. ;
  837.     end    submit
  838.