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 / JOB15.LBR / JOB15.MQC / JOB15.MAC
Text File  |  2000-06-30  |  22KB  |  1,177 lines

  1.     title    'JOB 1.5 (86/10/15)'
  2. ; An improved submit facility for CP/m systems.
  3. ;    evolved from public domain supersub by Ron Fowler
  4. ; copyright (c) 1983,1984,1986
  5. ; By C.B. Falconer,
  6. ;    680 Hartford Tpk, Hamden, CT 06517. (203) 281-1438
  7. ; released to the public domain 
  8. ;
  9. ; JOB allows parameters to be terminated by commas, thus a pair
  10. ; (i.e. ",,") can specify a null parameter.  In addition, parameters
  11. ; can be "quoted strings", to allow any input whatsoever.  In a quoted
  12. ; string a quote must be represented by two quotes.  JOB also accepts
  13. ; empty input lines (e.g. PIP exit command).
  14. ;
  15. ; JOB creates the $$$.SUB file on drive A, (user 0 as of JOB15) and
  16. ; thus can be executed with any setting of the default drive.  In
  17. ; addition JOB searches both the default and A drives for the .JOB
  18. ; file when no drive is specified in the command line, and (ver 1.4)
  19. ; if no .JOB file has yet been found searches default and system disks
  20. ; for a component of JOBS.LBR file.
  21. ;
  22. ; Thus a set of small .JOB files can be packed into JOBS.LBR and
  23. ; executed directly.  When many .JOB files are used this can
  24. ; significantly reduce disk storage
  25. ;
  26. ; An initial line in the .JOB file beginning with ";;" (double
  27. ; semi-colon) signifies that the line specifies a default set of
  28. ; parameters ($0 thru $9). These are only used when the execution
  29. ; command line does not supply parameters.
  30. ;
  31. ; JOB does not arbitrarily upshift anything, however an unmodified CCP
  32. ; will probably upshift all input lines.  CCPLUS can be set to avoid
  33. ; this upshifting.
  34. ;
  35. ; JOB will accept most files created for SUBMIT, unless supplied
  36. ; parameters include commas and quotes.  Since the reverse is not true
  37. ; JOB expects its' input files to be of type .JOB.
  38. ;
  39. ; JOB15 up is organized to co-operate with CCP+ and execute jobs thru
  40. ; changes in user number.  To perform correctly, a minor patch to BDOS
  41. ; is required, listed below.
  42. ;
  43. ; A test file to demonstrate JOB appears below (note null line):
  44.  
  45. ;;testingjob parm1, "parm2",, parm4 parm5, ," parm ""7"", "
  46. ; null defaults for parm3, parm6, parm8, parm9
  47. ;$1;
  48.  
  49. ;$2;
  50. ;$3,$4,$5,$6;
  51. ;$7;
  52. ;$8;
  53. ;$9;
  54. ;$0; <<end of test file>>
  55.  
  56. ; try A>JOB TESTJOB
  57. ;        where testjob is the above file from the ";;"
  58. ; This simply shows a set of comment commands on the console.
  59. ;
  60. ; Revision history
  61. ; ================
  62. ;
  63. ; 1.5    86/10/15 (cbf) Forced $$$.SUB file on user 0. After all, CPM
  64. ;    is a single user system.  Cooperates with CCP+ v21 up.
  65. ;    A patch for cpm2.2 for submit jobs to execute while changing
  66. ;    user numbers.  This co-operates with CCP+ v2.1 and JOB v1.5.
  67. ;
  68. ;    All values are shown for an unrelocated BDOS.  marked bytes
  69. ;    may be different by a constant
  70. ;
  71. ;    Location
  72. ;    (from start
  73. ;    of BDOS)    Was    Becomes    Comment
  74. ;    06DE        3e    7e    mvi a,0e5 --> mov a,m
  75. ;    06DF        e5    fe
  76. ;    06E0        be    e5    cmp m       --> cpi 0e5
  77. ;    06E1        ca
  78. ;    06E2        d2          jz ...   unchanged
  79. ;    06E3        06 *
  80. ;    06E4        3a    18    lda usrno --> jr $+3
  81. ;    06E5        41    01
  82. ;    06E6        03 *        (code byte skipped)
  83. ;    06E7        be    b7    cmp m     --> ora a
  84. ;        
  85. ;    The WAS items marked by '*' will vary with the location of
  86. ;    the CPM system, and should not be altered.  The patch uses
  87. ;    the Z80 JR instruction, so for Z80 systems only.  This has
  88. ;    been carefully designed to be position independant.
  89. ;
  90. ;    When completed, the original CCP will no longer execute
  91. ;    SUBMIT jobs when the user number is non-zero. It would never
  92. ;    allow a submit job to change users, which can now be done
  93. ;    when using CCP+ and JOB15.  (earlier versions of JOB will
  94. ;    work if the job is started on user 0 only.)
  95. ;
  96. ;    This causes BDOS to return 0ffh for call 13 (reset disks)
  97. ;    whenever a '$*.*' file exists on user 0.  This flag is
  98. ;    used by CCP+, ZCPR, and the original CCP to decide whether
  99. ;    to bother searching for the $$$.SUB file.  The original
  100. ;    code only returned 0ffh when the file existed on the current
  101. ;    user.
  102. ;
  103. ; 1.4    84/06/23 (cbf) Added library file search 
  104. ;
  105. ver        equ    15;    update with each revision
  106. ;
  107. cr        equ    0dh
  108. lf        equ    0ah
  109. tab        equ    9
  110. eol        equ    '$'
  111. parmchar    equ    '$'
  112. slash        equ    '/'
  113. comma        equ    ','
  114. quote        equ    '"'
  115. semi        equ    ';'
  116. blank        equ    ' '
  117. linesep        equ    '|'
  118. escape        equ    '^';    to control chars
  119. eofmark        equ    01ah;    sub=cntrl-z
  120. maxparms    equ    9
  121. ;
  122. putchar        equ    2;    cp/m functions
  123. putstring    equ    9
  124. getstring    equ    10
  125. fopen        equ    15
  126. fclose        equ    16
  127. fpurge        equ    19
  128. rdseq        equ    20
  129. wrtseq        equ    21
  130. newfile        equ    22
  131. gsuser        equ    32;    get/set user
  132. rdran        equ    33
  133. ;
  134. reboot        equ    0;    cp/m connector locations
  135. bdos        equ    00005h
  136. tfcb        equ    05ch
  137. tfcb.nam    equ    tfcb+1
  138. tfcb.ext    equ    tfcb+9
  139. cmdline        equ    080h
  140. defdma        equ    cmdline
  141. cmd.lgh        equ    cmdline
  142. cmd.chars    equ    cmdline+1
  143. ;
  144. ;
  145.     aseg
  146.     org    0100h
  147. ;
  148. begin:    lxi    h,0
  149.     dad    sp
  150.     shld    stksave    
  151.     lxi    sp,stack
  152.     mvi    a,gsuser
  153.     mvi    e,0ffh
  154.     call    dos
  155.     sta    defusr;        save input user
  156.     call    job
  157.     db    'JOB V'
  158.     db    ver / 10 + '0', '.', ver MOD 10 + '0',cr,lf,eol
  159. ;
  160. job:    pop    d
  161.     lda    tfcb.nam
  162.     cpi    blank
  163.     jz    help
  164.     mvi    a,putstring
  165.     call    dos;        sign-on
  166.     call    init
  167.     call    getcmnd
  168.     call    chkinf;        for blank or .job extension
  169.     lxi    h,0
  170.     shld    linenum    
  171.     call    openinf;    zero flag for interactive mode
  172.     cnz    freadjob;    put 1st line in buffer
  173.     jnz    jobempty;    read failed
  174.     call    default;    set default params
  175.     call    inputlns
  176.  
  177.     xra    a;        REMOVE this for use with original
  178.     mov    e,a;        CCP or ZCPR.
  179.     mvi    a,gsuser
  180.     call    dos;        jam to user 0 for subf operations
  181.  
  182.     call    opnsubf
  183.     call    wrtsubf
  184.     lda    defusr
  185.     mov    e,a
  186.     mvi    a,gsuser
  187.     call    dos;        restore entry user
  188.     jmp    reboot
  189. ;
  190. ; Check that any extension is ".JOB", or insert such
  191. ; if the supplied extension is blank.
  192. ; a,f,b,d,e,h,l
  193. chkinf:    lxi    h,tfcb.ext
  194.     mov    a,m
  195.     cpi    blank
  196.     jz    chkinf2
  197.     lxi    d,job.xt
  198.     mvi    b,3
  199.     call    qmatch
  200.     rz    
  201. ;    "    "
  202. nofile:    call    errexit;    leaves forever
  203.     db    '.'
  204. job.xt:    db    'JOB file not found',eol
  205. ;
  206. chkinf2:
  207.     xchg    
  208.     lxi    h,job.xt
  209.     mvi    b,3
  210. chkinf3:
  211.     mov    a,m;        move "JOB" into place
  212.     stax    d
  213.     inx    h
  214.     inx    d
  215.     dcr    b
  216.     jnz    chkinf3
  217.     ret
  218. ;
  219. getcmnd:
  220.     lxi    h,cmd.chars
  221.     call    skipblks
  222.     sta    mode    
  223.     rc    
  224.     cpi    slash
  225.     jnz    getcmnd3;    normal operation
  226.     inx    h
  227. getcmnd1:
  228.     shld    cursor    
  229.     mov    a,m
  230.     sta    onelnflg    
  231.     cpi    blank
  232.     rnz    
  233.     inx    h
  234.     jmp    getcmnd1
  235. getcmnd3:
  236.     call    skipblks
  237. getcmnd4:
  238.     cnc    setparm
  239.     jnc    getcmnd3
  240.     dcx    h;        back to eol mark for null param
  241.     push    h
  242.     lhld    parmindx
  243.     mov    a,m
  244.     ora    a
  245.     pop    h
  246.     jz    getcmnd4;    setup a null parameter
  247.     ret
  248. ;
  249. ; skipblanks in hl^, return 1st non blank. cy for eol, eof
  250. ; a,f,h,l
  251. skipblks:
  252.     mov    a,m
  253.     inx    h
  254.     ora    a
  255.     stc
  256.     rz    
  257.     cpi    cr
  258.     stc
  259.     rz    
  260.     cpi    eofmark
  261.     stc
  262.     rz    
  263.     cpi    blank
  264.     jz    skipblks
  265.     cpi    tab
  266.     jz    skipblks
  267.     dcx    h
  268.     ora    a
  269.     ret
  270. ;
  271. ; return carry if eol encountered
  272. setparm:
  273.     call    setdelim
  274.     push    h;        save input index
  275.     lhld    freeptr
  276.     xchg    
  277.     lhld    parmindx
  278.     mov    a,m
  279.     ora    a
  280.     jnz    manyparm
  281.     mov    m,e
  282.     inx    h
  283.     mov    m,d
  284.     inx    h
  285.     shld    parmindx    
  286.     pop    h
  287. ;    "    "
  288. ; save parameter
  289. ; (hl)^ is start of parameter string,
  290. ; (de)^ to location to save parameter
  291. savparm:
  292.     push    d
  293.     inx    d
  294.     mvi    b,0
  295. savparm1:
  296.     lda    delim
  297.     cpi    quote
  298.     jnz    savparm2;    not a quoted string
  299.     mov    a,m
  300.     inx    h
  301.     ora    a
  302.     jz    parmerr;    no terminal quote
  303.     cpi    quote
  304.     jnz    savparm4;    not terminal quote, go save char
  305.     cmp    m;        is it a double quote?
  306.     jnz    savparm5;    no, string is terminated
  307.     inx    h
  308.     jmp    savparm4;    yes, store a quote
  309. savparm2:
  310.     mov    a,m
  311.     inx    h
  312.     call    chkdelim
  313.     jz    savparm5
  314. savparm4:
  315.     stax    d
  316.     inx    d
  317.     inr    b
  318.     jmp    savparm1
  319. savparm5:
  320.     xchg    
  321.     shld    freeptr    
  322.     pop    h
  323.     mov    m,b
  324.     xchg;            pointer to terminal char
  325.     cpi    quote
  326.     jnz    savparm6;    not a quoted string
  327.     mov    a,m
  328.     cpi    comma
  329.     jnz    savparm6
  330.     inx    h;        skip terminating comma on
  331.     mov    a,m;          a quoted string
  332. savparm6:
  333.     ora    a
  334.     stc
  335.     rz    
  336.     cmc
  337.     ret
  338. ;
  339. ; setup delimiter for parameters. Advance past any initial '"'
  340. ; a,f,h,l
  341. setdelim:
  342.     mvi    a,' '
  343.     sta    delim    
  344.     mov    a,m
  345.     cpi    quote
  346.     rnz;            not a quoted string
  347.     sta    delim    
  348.     inx    h;        advance past the initial quote
  349.     ret
  350. ;
  351. ; Set up default parameters
  352. ; The first line is in defdma.  If the mode is not interactive, and
  353. ; the line begins with ";;", then replace each null parameter with
  354. ; the value in this first line, starting with 0.  Note that the 0th
  355. ; parameter is the jobfile name, and cannot be null.  The replacement
  356. ; parameters may be null. Such an initial line will be treated as a
  357. ; comment when executed by CCP, displaying the defaults.
  358. default:
  359.     lda    mode
  360.     cpi    slash
  361.     rz;            interactive mode
  362.     lda    defdma
  363.     cpi    semi
  364.     rnz;            not initial ";;"
  365.     lda    defdma+1
  366.     cpi    semi
  367.     rnz;            not initial ";;"
  368.     lxi    h,defdma+1;    before first possible character
  369.     mvi    b,0;        parameter number
  370. ; WHILE NOT eoln DO BEGIN
  371. ;   delimit_parameter;
  372. ;   IF non-null THEN
  373. ;     IF parameter (b) is null THEN BEGIN
  374. ;       expand_parm_storage
  375. ;       insert_default; END;
  376. ;     delimit next parameter; END;
  377. default1:
  378.     inx    h;        bypass previous delimiter
  379.     call    skipblks
  380.     rc;            no more
  381.     call    setdelim
  382.     call    scan;        to parm end
  383. ; now (c) is parameter lgh, (de) is start, (b) is id
  384. ; watch out for doubled quotes, counted as singles
  385. ; (hl)^ is terminating char, not part of parm
  386.     push    h
  387.     push    d
  388.     mov    a,c
  389.     ora    a
  390.     jz    default8;    default param is null
  391.     mov    a,b;        parameter id
  392.     call    findparm
  393.     ora    a
  394.     jnz    default8;    cmdline input is non-null
  395. ; now store the default parameter and
  396. ; update the index to it.  The previous
  397. ; storage for a null parameter is discarded.
  398.     lhld    freeptr
  399.     xchg    
  400.     mov    m,e
  401.     inx    h
  402.     mov    m,d
  403.     pop    h;        ^ param start
  404.     push    h
  405.     push    b
  406.     call    savparm
  407.     pop    b
  408. default8:
  409.     pop    d
  410.     pop    h
  411.     mov    a,m
  412.     call    chklnend
  413.     rz;            done
  414.     inr    b;        next parameter id
  415.     jmp    default1;    go try for next
  416. ;
  417. ; scan to parameter end. (hl)^ is start
  418. ; return (de)^ to start, (c) = length
  419. ; (hl)^ to delimiting character
  420. ; a,f,c,d,e,h,l
  421. scan:    mov    d,h
  422.     mov    e,l;        save starting point
  423.     mvi    c,0;        length, default 0
  424.     lda    delim
  425.     cpi    quote
  426.     jz    scan2;        looking for terminal quote
  427. scan1:    mov    a,l
  428.     ora    a
  429.     jz    parmerr;    no end found
  430.     mov    a,m
  431.     call    chkdelim
  432.     jz    scan9
  433.     inx    h
  434.     inr    c;        count length
  435.     jmp    scan1
  436. scan2:    mov    a,l
  437.     ora    a
  438.     jz    parmerr
  439.     mov    a,m
  440.     cpi    cr
  441.     jz    parmerr
  442.     cpi    quote
  443.     jz    scan4;        go check for double
  444. scan3:    inr    c;        count chars
  445.     inx    h
  446.     jmp    scan2
  447. scan4:    inx    h
  448.     cmp    m
  449.     jz    scan3;        double quote, keep 1 only
  450.     mov    a,m
  451.     call    chkdelim
  452.     jnz    parmerr
  453. scan9:    ret;            m points to terminating char.
  454. ;
  455. ; check (a) for possible delimiter, zero flag if so
  456. ; a,f
  457. chkdelim:
  458.     cpi    blank
  459.     rz    
  460.     cpi    tab
  461.     rz    
  462.     cpi    comma
  463.     rz    
  464. ;    "    "
  465. ; check (a) for line ending char, zero flag if so
  466. ; a,f
  467. chklnend:
  468.     cpi    cr
  469.     rz    
  470.     cpi    eofmark
  471.     rz    
  472.     ora    a
  473.     ret
  474. ;
  475. ; open input file. z flag for interactive mode
  476. openinf:
  477.     lda    mode
  478.     cpi    slash
  479.     rz;            interactive mode
  480.     lxi    d,tfcb
  481.     call    openf
  482.     rnz;            success
  483.     lxi    h,lbrfcb
  484.     call    trylb;        look in JOBS.LBR if not found
  485.     jz    nofile;        failed
  486.     ret
  487. ;
  488. ; Try to find component (de)^ in library file (hl)^
  489. ; z flag for failure
  490. ; If successful set up (de)^ [TFCB] for component access
  491. ; Note that the component size is needed in case the item
  492. ; ends on a record boundary without any eof mark.
  493. ; ** This routine needs cleanup to return component size
  494. ;    in (bc), and use only the input pointers (and defdma)
  495. ;    for access.  This will decouple it from this program. 
  496. ; a,f,b,c
  497. trylb:    xchg    
  498.     mvi    m,0;        mark default again
  499.     call    openf;        automatically tries system disk
  500.     xchg    
  501.     rz;            failed
  502.     xchg    
  503.     mvi    a,rdseq
  504.     call    dos
  505.     jnz    trylb9;        else first directory rcd read
  506.     call    chksz;        set (a) = entry count
  507.     jz    trylb9;        not a valid library
  508.     mov    b,a;        entry count
  509.     push    h;        save component id pointer
  510. trylb1:    dcr    b
  511.     jz    trylb8;        no more entries, not found
  512.     mov    a,b;        Now check (max - b)th entry
  513.     ani    3;        for the one we want
  514.     mvi    a,rdseq
  515.     cz    dos;        get next directory chunk
  516.     mov    a,b
  517.     cma
  518.     inr    a
  519.     ani    3
  520.     add    a
  521.     add    a
  522.     add    a
  523.     add    a
  524.     add    a;        * 32 bytes per entry
  525.     adi    defdma;        point to this entry
  526.     pop    h
  527.     push    h;        get component pointer
  528.     push    d
  529.     push    b;        THIS needs cleanup to use only the
  530.     xchg    
  531.     mov    l,a;        entry parameters for TFCB etc.
  532.     mvi    h,0;        and return a record count in (bc)
  533.     mvi    b,12;        Does this entry match
  534.     call    qmatch;        the one we want?
  535.     pop    b
  536.     pop    d
  537.     jnz    trylb1;        no, try next entry
  538.     mov    a,m;        yes, set up file access etc.
  539.     sta    lb.rrn;        m points to loc'n entry
  540.     inx    h
  541.     mov    a,m
  542.     sta    lb.rrn+1;        record pointer
  543.     inx    h
  544.     mov    a,m
  545.     inx    h
  546.     mov    h,m
  547.     mov    l,a;        record count
  548.     shld    maxrecs;    to force an eof when reading
  549.     xra    a
  550.     sta    lb.rrn+2;     now do a random read to set ptrs
  551.     push    d
  552.     mvi    a,rdran
  553.     lxi    d,lbrfcb
  554.     call    dos
  555.     lxi    h,tfcb
  556.     mvi    b,36
  557. trylb7:    ldax    d;        Move the complete opened fcb
  558.     mov    m,a;            to tfcb
  559.     inx    h
  560.     inx    d
  561.     dcr    b
  562.     jnz    trylb7;        More
  563.     pop    d
  564.     pop    h
  565.     ori    1
  566.     ret;            signal success
  567. trylb8:    pop    h
  568. trylb9:    xchg;            Not found, restore
  569.     mov    a,m
  570.     inr    m
  571.     ora    a;        If was default disk then
  572.     jz    trylb;        go try system disk
  573.     xra    a;        else signal failure
  574.     ret
  575. ;
  576. ; check size of library directory (de)^. 1st record in defdma
  577. ; Return (a) = count of entries (0 if not a library)
  578. ; a,f
  579. chksz:    push    b
  580.     push    d
  581.     push    h
  582.     lxi    h,defdma
  583.     mov    a,m
  584.     ora    a
  585.     jnz    chksz2
  586.     mvi    b,11
  587. chksz1:    inx    h
  588.     mov    a,m
  589.     cpi    ' '
  590.     jnz    chksz2;        invalid director
  591.     dcr    b
  592.     jnz    chksz1
  593.     inx    h
  594.     mov    a,m
  595.     inx    h
  596.     ora    m
  597.     inx    h
  598.     inx    h
  599.     ora    m
  600.     jnz    chksz2
  601.     dcx    h
  602.     mov    a,m;        get directory size
  603.     add    a
  604.     add    a;        in directory entries
  605.     jmp    chksz3;        0 causes error signal
  606. chksz2:    xra    a;        signal none
  607. chksz3:    pop    h
  608.     pop    d
  609.     pop    b
  610.     ret
  611. ;
  612. ; Open file (de)^.  Check default and system disks
  613. ; z flag for failure
  614. ; a,f
  615. openf:    push    h
  616.     lxi    h,32
  617.     dad    d
  618.     mvi    m,0;        set record pointer to zero
  619.     pop    h
  620.     mvi    a,fopen
  621.     call    dos
  622.     inr    a
  623.     rnz;            success
  624.     ldax    d
  625.     ora    a
  626.     jz    openf1;        was default, try system
  627.     xra    a
  628.     ret;            with z flag for failure
  629. openf1:    mvi    a,1;        try system disk
  630.     stax    d
  631.     jmp    openf
  632. ;
  633. inputlns:
  634.     lhld    linenum;    set up for line
  635.     inx    h
  636.     shld    linenum    
  637.     lhld    lineptr
  638.     xchg    
  639.     lhld    freeptr
  640.     shld    lineptr    
  641.     mov    m,e
  642.     inx    h
  643.     mov    m,d
  644.     inx    h
  645.     push    h
  646.     inx    h
  647.     mvi    c,0
  648. inputl3:
  649.     call    nextch;        store a line
  650.     jc    inputl5
  651.     db    0,0,0;        was call upshift
  652.     cpi    eofmark
  653.     jz    inputl5
  654.     cpi    lf
  655.     jz    inputl3
  656.     cpi    cr
  657.     jz    inputl4
  658.     mov    m,a
  659.     inx    h
  660.     call    memcheck
  661.     inr    c
  662.     jm    toolong
  663.     jmp    inputl3
  664. inputl4:
  665.     shld    freeptr    
  666.     pop    h
  667.     mov    m,c
  668.     jmp    inputlns;    next line
  669. inputl5:
  670.     shld    freeptr    
  671.     pop    h
  672.     mov    m,c
  673.     ret
  674. ;
  675. nextch:    push    h
  676.     push    d
  677.     push    b
  678.     lda    mode
  679.     cpi    slash
  680.     jnz    nextch1;    get from file
  681.     call    getch;        get from terminal
  682.     jmp    nextch3
  683. nextch1:
  684.     lda    inptr
  685.     ora    a
  686.     cm    freadjob
  687.     jnc    nextch2;    success, (a) is zero
  688.     mvi    a,eofmark
  689.     jmp    nextch3
  690. nextch2:
  691.     mov    e,a
  692.     mvi    d,0
  693.     inr    a
  694.     sta    inptr    
  695.     lxi    h,cmd.lgh
  696.     dad    d
  697.     mov    a,m
  698. nextch3:
  699.     pop    b
  700.     pop    d
  701.     pop    h
  702.     ora    a
  703.     ret
  704. ;
  705. freadjob:
  706.     mvi    a,0
  707.     sta    inptr    
  708.     lhld    maxrecs
  709.     mov    a,h
  710.     ora    l
  711.     dcx    h
  712.     shld    maxrecs    
  713.     mvi    a,1;        to signal eof if no read
  714.     mvi    a,rdseq
  715.     lxi    d,tfcb
  716.     cnz    dos;        records left
  717.     ora    a
  718.     stc
  719.     rnz;            eof
  720.     cmc
  721.     ret
  722. ;
  723. getch:    lda    onelnflg
  724.     ora    a
  725.     jnz    getch2;        one line only
  726.     lda    buf.size
  727.     ora    a
  728.     cm    userline
  729.     jc    getch3
  730.     dcr    a
  731.     sta    buf.size    
  732.     jp    getch2
  733. getch1:    mvi    a,cr
  734.     ret
  735. getch2:    lhld    cursor
  736.     mov    a,m
  737.     inx    h
  738.     shld    cursor    
  739.     cpi    linesep
  740.     jz    getch1
  741.     ora    a
  742.     rnz    
  743. getch3:    mvi    a,eofmark
  744.     ret
  745. ;
  746. userline:
  747.     lxi    d,prompter
  748.     mvi    a,putstring
  749.     call    dos
  750.     lxi    d,buf.max
  751.     mvi    a,getstring
  752.     call    dos
  753.     lda    buf.size
  754.     lxi    h,buf.data
  755.     shld    cursor    
  756.     ora    a
  757.     stc
  758.     rz    
  759.     cmc
  760.     ret
  761. ;
  762. memcheck:
  763.     lda    bdos+2
  764.     dcr    a
  765.     cmp    h
  766.     rnc    
  767.     call    errexit
  768.     db    'Memory full',eol
  769. ;
  770. opnsubf:
  771.     mvi    a,fopen
  772.     call    xsubf
  773.     inr    a
  774.     jz    opnsubf1
  775.     lda    sub.size
  776.     sta    sub.rnum;        prepare to append
  777.     ret
  778. opnsubf1:
  779.     sta    sub.rnum;        assumes (a)=0
  780.     mvi    a,newfile
  781.     call    xsubf
  782.     inr    a
  783.     rnz    
  784.     call    errexit
  785.     db    'Directory full',eol
  786. ;
  787. wrtsubf:
  788.     lhld    lineptr
  789.     mov    a,h
  790.     ora    l
  791.     jz    jobempty
  792.     mov    e,m
  793.     inx    h
  794.     mov    d,m
  795.     inx    h
  796.     xchg    
  797.     shld    lineptr    
  798.     xchg    
  799.     mov    a,m
  800.     ora    a
  801.     jz    wrtsubf3;    empty line
  802. wrtsubf1:
  803.     call    wrtln
  804.     lhld    linenum
  805.     dcx    h
  806.     shld    linenum    
  807.     lhld    lineptr
  808.     mov    a,h
  809.     ora    l
  810.     jz    wrtsubf4;    no more
  811.     mov    e,m
  812.     inx    h
  813.     mov    d,m
  814.     inx    h
  815.     xchg    
  816.     shld    lineptr    
  817.     xchg    
  818.     jmp    wrtsubf1
  819. wrtsubf3:
  820.     lhld    linenum
  821.     dcx    h
  822.     shld    linenum    
  823.     jmp    wrtsubf
  824. wrtsubf4:
  825.     mvi    a,fclose
  826. ;    "    "
  827. ; subfile operation (a)
  828. ; a,f,d,e
  829. xsubf:    lxi    d,subfcb
  830. ;    "    "
  831. ; Bdos call, function (a), return in (a), preserve registers
  832. ; Set flags on (a)
  833. ; a,f
  834. dos:    push    h
  835.     push    d
  836.     push    b
  837.     mov    c,a
  838.     call    bdos
  839.     ora    a
  840.     pop    b
  841.     pop    d
  842.     pop    h
  843.     ret
  844. ;
  845. ; Copy the line, making any parameter substitutions
  846. wrtln:    mov    a,m
  847.     inx    h
  848.     sta    chrsleft    
  849.     shld    @nextch    
  850.     lxi    h,cmd.chars
  851.     shld    putptr    
  852.     xra    a
  853.     sta    cmd.lgh    
  854.     mov    b,l
  855. wrtln1:    mov    m,a
  856.     inx    h
  857.     inr    b
  858.     jnz    wrtln1
  859. wrtln2:    call    getchar
  860.     jc    putsubf
  861.     cpi    escape
  862.     jnz    wrtln3
  863.     call    getchar
  864.     jc    cntrlch
  865.     cpi    escape
  866.     jz    wrtln3;        doubled to use escape char.
  867.     call    upshift
  868.     sui    '@'
  869.     jc    cntrlch
  870.     cpi    blank
  871.     jnc    cntrlch
  872. wrtln3:    cpi    parmchar
  873.     jnz    wrtln4
  874.     lda    mode
  875.     cpi    slash
  876.     mvi    a,parmchar;    In case interactive, use it
  877.     jz    wrtln4;        '$' not special in interactive mode
  878.     call    chknxtch
  879.     jc    parmerr
  880.     cpi    parmchar
  881.     jnz    wrtln5;        Go expand a parameter
  882.     call    getchar
  883. wrtln4:    call    putoutch
  884.     jmp    wrtln2
  885. wrtln5:    call    getchar;    a parameter identifier
  886.     call    qnum
  887.     jc    parmerr;    not numeric, no good
  888.     sui    '0';        one digit only allowed
  889.     call    findparm
  890.     jc    parmerr
  891.     mov    b,a;        length
  892.     inr    b;        may be zero
  893. wrtln6:    dcr    b
  894.     jz    wrtln2;        end of substitution
  895.     mov    a,m
  896.     inx    h
  897.     push    h
  898.     call    putoutch
  899.     pop    h
  900.     jmp    wrtln6
  901. ;
  902. putsubf:
  903.     mvi    a,wrtseq
  904.     call    xsubf
  905.     ora    a
  906.     rz    
  907.     call    errexit
  908.     db    'Disk full',eol
  909. ;
  910. getchar:
  911.     lxi    h,chrsleft
  912.     mov    a,m
  913.     dcr    a
  914.     stc
  915.     rm    
  916.     mov    m,a
  917.     lhld    @nextch
  918.     mov    a,m
  919.     inx    h
  920.     shld    @nextch    
  921.     cmc
  922.     ret
  923. ;
  924. putoutch:
  925.     lxi    h,cmd.lgh
  926.     inr    m
  927.     jm    toolong
  928.     lhld    putptr
  929.     mov    m,a
  930.     inx    h
  931.     shld    putptr    
  932.     ret
  933. ;
  934. chknxtch:
  935.     lda    chrsleft
  936.     ora    a
  937.     stc
  938.     rz    
  939.     mov    a,m
  940.     cmc
  941.     ret
  942. ;
  943. ; find parameter (a). Returns (a)=length,
  944. ; (hl)^ to start of parameter,
  945. ; (de)^ to pointer to lgh field (index table)
  946. ; a,f,d,e,h,l
  947. findparm:
  948.     cpi    maxparms+1
  949.     jnc    manyparm
  950.     mov    l,a
  951.     mvi    h,000h
  952.     dad    h
  953.     lxi    d,parmxpnd
  954.     dad    d
  955.     mov    e,m
  956.     inx    h
  957.     mov    d,m
  958.     dcx    h
  959.     xchg    
  960.     mov    a,m
  961.     inx    h
  962.     ret
  963. ;
  964. qmatch:    ldax    d
  965.     cmp    m
  966.     rnz    
  967.     inx    h
  968.     inx    d
  969.     dcr    b
  970.     jnz    qmatch
  971.     ret
  972. ;
  973. ; carry if (a) is not a numeric character
  974. ; f
  975. qnum:    cpi    '0'
  976.     rc    
  977.     cpi    '9'+1
  978.     cmc
  979.     ret
  980. ;
  981. ; write (hl) as decimal number, suppress leading zeroes
  982. tdzs:    push    psw
  983.     push    h
  984.     push    b
  985.     lxi    b,0f00ah;    c=divisor=10; b=iter.cnt=-16
  986.     xra    a;        clear
  987. tdzs1:    dad    h
  988.     ral;            shift off into (a)
  989.     cmp    c
  990.     jc    tdzs2;        no bit
  991.     sub    c
  992.     inx    h;        bit=1
  993. tdzs2:    inr    b
  994.     jm    tdzs1;        not done
  995.     pop    b
  996.     push    psw;        save output digit
  997.     mov    a,h
  998.     ora    l
  999.     cnz    tdzs;        recursive
  1000.     pop    psw
  1001.     pop    h
  1002.     adi    '0'
  1003.     call    cout
  1004.     pop    psw
  1005.     ret
  1006. ;
  1007. ; crlf to console
  1008. ; a,f
  1009. crlf:    mvi    a,cr
  1010.     call    cout
  1011.     mvi    a,lf
  1012. ;    "    "
  1013. ; (a) to console
  1014. ; a,f
  1015. cout:    push    d
  1016.     mov    e,a
  1017.     mvi    a,putchar
  1018.     call    dos
  1019.     pop    d
  1020.     ret
  1021. ;
  1022. ; Upshift (a)
  1023. ; a,f
  1024. upshift:
  1025.     cpi    'a'
  1026.     rc    
  1027.     cpi    'z'+1
  1028.     rnc    
  1029.     ani    05fh
  1030.     ret
  1031. ;
  1032. parmerr:
  1033.     call    errexit
  1034.     db    'Parameter',eol
  1035. ;
  1036. manyparm:
  1037.     call    errexit
  1038.     db    'Too many parameters:',eol
  1039. ;
  1040. toolong:
  1041.     call    errexit
  1042.     db    'Line too long:',eol
  1043. ;
  1044. jobempty:
  1045.     call    errexit
  1046.     db    'Job file empty',eol
  1047. ;
  1048. cntrlch:
  1049.     call    errexit
  1050.     db    'Control character',eol
  1051. ;
  1052. ; Message (tos)^ and exit
  1053. errexit:
  1054.     pop    d
  1055.     mvi    a,putstring
  1056.     call    dos
  1057.     lxi    d,errmsg
  1058.     mvi    a,putstring
  1059.     call    dos
  1060.     lhld    linenum
  1061.     call    tdzs
  1062.     call    crlf
  1063.     mvi    a,fpurge
  1064.     call    xsubf
  1065.     jmp    reboot
  1066. ;
  1067. errmsg:    db    ' error on line number: ',eol
  1068. prompter:
  1069.     db    cr,lf,'*',eol
  1070. ;
  1071. init:    lxi    h,clrbegin
  1072.     lxi    b,buf.max-clrbegin
  1073. init1:    mvi    m,000h;    clear
  1074.     inx    h
  1075.     dcx    b
  1076.     mov    a,b
  1077.     ora    c
  1078.     jnz    init1
  1079.     lxi    h,parmxpnd
  1080.     shld    parmindx    
  1081.     lxi    h,-1;        mark end of parameter pointers
  1082.     shld    lastparm    
  1083.     shld    maxrecs;    allow 65535 recs on non lbr file
  1084.     lxi    h,storage
  1085.     shld    freeptr    
  1086.     mvi    a,080h
  1087.     sta    inptr    
  1088.     sta    buf.size    
  1089.     sta    buf.max    
  1090.     ret
  1091. ;
  1092. help:    lxi    d,helpmsg
  1093.     mvi    a,putstring
  1094.     call    dos
  1095.     lhld    stksave
  1096.     sphl    
  1097.     ret
  1098. ;
  1099. helpmsg:
  1100.     db    cr,lf,'How to use JOB:',cr,lf,lf
  1101.     db    'JOB<CR>            : '
  1102.     db    'print this message',cr,lf
  1103.     db    'JOB /<CR>          : '
  1104.     db    'interactive mode',cr,lf
  1105.     db    'JOB /<cmd lines>   : '
  1106.     db    'use SUMMARY mode',cr,lf
  1107.     db    'JOB <FILE> <PARMS> : as standard '
  1108.     db    'SUBMIT.COM, but JOB will search',cr,lf
  1109.     db    'for A:file.JOB after the default '
  1110.     db    'disk if no drive was specified,',cr,lf
  1111.     db    'and then as a component of "JOBS.LBR" '
  1112.     db    'if not already found.',cr,lf
  1113.     db    'The SUB file is created on "A:", '
  1114.     db    ' thus JOB may be used while any',cr,lf
  1115.     db    'drive is the default.  Parameters '
  1116.     db    'may be delimited by commas and',cr,lf
  1117.     db    'may be "quoted strings". An initial '
  1118.     db    'line beginning with ";;" can',cr,lf
  1119.     db    'be used to specify default params '
  1120.     db    '(0..9) at execution time.',cr,lf,lf
  1121.     db    'In "/" (interactive) mode,  JOB '
  1122.     db    'will prompt you a line at a time',cr,lf
  1123.     db    'for the "SUBMIT" job input. '
  1124.     db    'Logical lines may be combined on the',cr,lf
  1125.     db    'same input line by separating them '
  1126.     db    'with "|".  Example:',cr,lf
  1127.     db    '  A>JOB /STAT|DIR',cr,lf
  1128.     db    'specifies two commands on the'
  1129.     db    ' same input line.',cr,lf,lf
  1130.     db    'Submitted jobs may nest...JOB '
  1131.     db    'inserts ahead of an existing job.',cr,lf,lf
  1132.     db    'To insert a control character '
  1133.     db    'into the output, prefix it with',cr,lf
  1134.     db    'a "^" ("^^" for real "^").',cr,lf,eol
  1135. ;
  1136. lbrfcb:    db    0,'JOBS    LBR',0,0,0,0
  1137.     ds    16
  1138. lb.rno:    ds    1
  1139. lb.rrn:    ds    3;
  1140. ;
  1141. subfcb:    db    1,'$$$     SUB';    LAST initialized storage
  1142. ;
  1143. clrbegin:    ds    3;    This area cleared at initialization
  1144. sub.size:    ds    17
  1145. sub.rnum:    ds    1
  1146.         ds    3;    for  random records
  1147. ;
  1148. delim:        ds    1;    delimiter for parameter input
  1149. freeptr:    ds    2
  1150. parmindx:    ds    2
  1151. linenum:    ds    2
  1152. lineptr:    ds    2
  1153. chrsleft:    ds    1
  1154. @nextch:    ds    2
  1155. putptr:        ds    2
  1156. inptr:        ds    1
  1157. cursor:        ds    2
  1158. onelnflg:    ds    1
  1159. mode:        ds    1
  1160. maxrecs:    ds    2;    to simulate eof on .lbr file
  1161. parmxpnd:    ds    2*(maxparms+1);    a list of pointers to
  1162. ;                      lgh, char string
  1163. lastparm:    ds    2;    -1 marks end of parmxpnd array
  1164. ; End of area cleared at initialization time
  1165. ;
  1166. defusr:        ds    1;    user at initialization time
  1167. buf.max:    ds    1
  1168. buf.size:    ds    1
  1169. buf.data:    ds    128
  1170. stksave:    ds    2
  1171.         ds    200;    stack space
  1172. stack:
  1173. storage:    ds    0;    actually the rest
  1174. ;
  1175.     end
  1176. V