home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / modem / cp405src.ark / CP4CMD.ASM < prev    next >
Assembly Source File  |  1986-12-25  |  23KB  |  884 lines

  1. ; CP4CMD.ASM
  2. ;    KERMIT - (Celtic for "FREE")
  3. ;
  4. ;    This is the CP/M-80 implementation of the Columbia University
  5. ;    KERMIT file transfer protocol.
  6. ;
  7. ;    Version 4.0
  8. ;
  9. ;    Copyright June 1981,1982,1983,1984,1985
  10. ;    Columbia University
  11. ;
  12. ; Originally written by Bill Catchings of the Columbia University Center for
  13. ; Computing Activities, 612 W. 115th St., New York, NY 10025.
  14. ;
  15. ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
  16. ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
  17. ; others. 
  18.  
  19. ;
  20. ;    This file provides a user oriented way of parsing commands.
  21. ;    It is similar to that of the COMND JSYS in TOPS-20.
  22. ;
  23. ; revision history (latest first):
  24. ; edit 5: 6-Feb-85 by Charles Carvalho
  25. ;    Make ffussy a runtime (rather than assembly-time) switch, to
  26. ;    eliminate conditional assembly in system-independent module.
  27. ;    Don't allow _%|()/\ in filenames if ffussy set; my CP/M manual
  28. ;    disallows those, too.
  29. ;
  30. ; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
  31. ;
  32. ;pcc006    2-jan-85    VJC    modules:cp4cmd,cp4utl
  33. ;    Problems with "?" in filespecs.  On reparse, may cause action
  34. ;    flag to be reset at wrong point, requiring multiple <CR>'s
  35. ;    to terminate the line or other weird stuff.  Also need to
  36. ;    check flag and complain if wild-cards illegal.
  37.  
  38. ;pcc007    2-Jan-85    vjc    modules:cp4def,cp4cmd
  39. ;    Cmifil is too fussy about what characters to accept in a
  40. ;    filespec.  My CP/M manual says any printable character is ok
  41. ;    except <>.,;:?*[], and lower case.  In practice, even those work
  42. ;    sometimes.  Kermit itself uses '&' if file warning is on,
  43. ;    and then won't let you reference the file.  Allow all
  44. ;    printable characters except those above.  Add conditional
  45. ;    ffussy, so that if not ffussy, all special characters will be
  46. ;    allowed, just convert lower to upper-case.
  47.  
  48. ; edit 3: July 8, 1984 (CJC)
  49. ;    integrate Toad Hall changes for LASM compatibility: CP4CPM is linked
  50. ;    by CP4WLD, and links CP4UTL.
  51. ;    
  52. ; edit 2: June 5, 1984 (CJC)
  53. ;    formatting and documentation; delete unnecessary code at cminb7; add
  54. ;    module version string.
  55. ;
  56. ; edit 1: May, 1984 (CJC)
  57. ;    extracted from CPMBASE.M80 version 3.9; modifications are described in
  58. ;    the accompanying .UPD file.
  59.  
  60. cmdver:    db    'CP4CMD.ASM (5)  6-Feb-85$'    ; name, edit number, date
  61.  
  62. ;    This routine prints the prompt in DE and specifies the reparse
  63. ;    address.
  64. ;    called by:  kermit
  65.  
  66. prompt:    pop    h        ;Get the return address.
  67.     push    h        ;Put it on the stack again.
  68.     shld    cmrprs        ;Save it as the address to go to on reparse.
  69.     lxi    h,0        ;Clear out hl pair.
  70.     dad    sp        ;Get the present stack pointer.
  71.     shld    cmostp        ;Save for later restoral.
  72.     xchg            ;Save the pointer to the prompt.
  73.     shld    cmprmp
  74.     xchg
  75.     lxi    h,cmdbuf
  76.     shld    cmcptr        ;Initialize the command pointer.
  77.     shld    cmdptr
  78.     xra    a
  79.     sta    cmaflg        ;Zero the flags.
  80.     sta    cmccnt
  81.     mvi    a,0FFH        ;Try it this way (Daphne.)
  82.     sta    cmsflg
  83.     call    prcrlf        ;Print a CR/LF [Toad Hall]
  84.     jmp    prprmp        ;Print the prompt.  [Toad Hall]
  85. ;
  86. ;    This address is jumped to on reparse.
  87. ;    here from:  cmcfrm, cmkeyw, cmifil, cminbf
  88.  
  89. repars:    lhld    cmostp        ;Get the old stack pointer.
  90.     sphl            ;Make it the present one.
  91.     lxi    h,cmdbuf
  92.     shld    cmdptr
  93.     mvi    a,0FFH        ;Try it this way (Daphne.)
  94.     sta    cmsflg
  95.     lhld    cmrprs        ;Get the reparse address.
  96.     pchl            ;Go there.
  97.  
  98. ;    This address can be jumped to on a parsing error.
  99. ;    here from:  cmkeyw, cminbf
  100.  
  101. prserr:    lhld    cmostp        ;Get the old stack pointer.
  102.     sphl            ;Make it the present one.
  103.     lxi    h,cmdbuf
  104.     shld    cmcptr        ;Initialize the command pointer.
  105.     shld    cmdptr
  106.     xra    a
  107.     sta    cmaflg        ;Zero the flags.
  108.     sta    cmccnt
  109.     mvi    a,0FFH        ;Try it this way (Daphne.)
  110.     sta    cmsflg
  111.     call    prcrlf        ;Print a CR/LF  [Toad Hall]
  112.     call    prprmp        ;Print the prompt  [Toad Hall]
  113. ;* Instead return to before the prompt call.
  114.     lhld    cmrprs
  115.     pchl
  116. ;
  117. ;    This routine parses the specified function in A.  Any additional
  118. ;    information is in DE and HL.
  119. ;    Returns +1 on success
  120. ;        +4 on failure (assumes a JMP follows the call)
  121. ;    called by:  log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd
  122.  
  123. comnd:    sta    cmstat        ;Save what we are presently parsing.
  124.     call    cminbf        ;Get chars until an action or a erase char.
  125.     cpi    cmcfm        ;Parse a confirm?
  126.     jz    cmcfrm        ;Go get one.
  127.     cpi    cmkey        ;Parse a keyword?
  128.     jz    cmkeyw        ;Try and get one.
  129.     cpi    cmifi        ;Parse an input file spec?
  130.     jz    cmifil        ;Go get one.
  131.     cpi    cmifin        ;Input file-spec silent?
  132.     jz    cmifil        ;do as he wishes
  133.     cpi    cmofi        ;Output file spec?
  134.     jz    cmofil        ;Go get one.
  135.     cpi    cmtxt        ;Parse arbitrary text?
  136.     jz    cmtext        ;Go do it.
  137.     lxi    d,cmer00    ;"?Unrecognized COMND call"
  138.     call    prtstr
  139.     ret
  140. ;
  141. ;    This routine parses arbitrary text up to a CR.
  142. ;    Accepts DE:    address to put text
  143. ;    Returns in A:    number of chars in text (may be 0)
  144. ;          DE:    updated pointer
  145. ;    called by: comnd
  146.  
  147. cmtext:    xchg            ;Put the pointer to the dest in HL.
  148.     shld    cmptab        ;Save the pointer.
  149.     mvi    b,0        ;Init the char count
  150. cmtxt1:    call    cmgtch        ;Get a char.
  151.     ora    a        ;Terminator?
  152.     jp    cmtxt5        ;No, put in user space.
  153.     ani    7FH        ;Turn off minus bit.
  154.     cpi    esc        ;An escape?
  155.     jnz    cmtxt2        ;No.
  156.     mvi    c,conout
  157.     mvi    e,bell        ;Get a bell.
  158.     call    bdos
  159.     xra    a
  160.     sta    cmaflg        ;Turn off the action flag.
  161.     lhld    cmcptr        ;Move the pointer to before the escape.
  162.     dcx    h
  163.     shld    cmcptr
  164.     shld    cmdptr
  165.     lxi    h,cmccnt    ;Get the char count.
  166.     dcr    m        ;Decrement it by one.
  167.     jmp    cmtxt1        ;Try again.
  168.  
  169. cmtxt2:    cpi    '?'        ;Is it a question mark?
  170.     jz    cmtxt3        ;If so put it in the text.
  171.     cpi    ff        ;Is it a formfeed?
  172.     cz    clrtop        ;If so blank the screen.
  173.     mov    a,b        ;Return the count.
  174.     lhld    cmptab        ;Return updated pointer in HL.
  175.     xchg
  176.     jmp    rskp        ;Return success.
  177.  
  178. cmtxt3:    lxi    h,cmaflg    ;Point to the action flag.
  179.     mvi    m,0        ;Set it to zero.
  180. cmtxt5:    inr    b        ;Increment the count.
  181.     lhld    cmptab        ;Get the pointer.
  182.     mov    m,a        ;Put the char in the array.
  183.     inx    h
  184.     shld    cmptab        ;Save the updated pointer.
  185.     jmp    cmtxt1        ;Get another char.
  186.  
  187. ;
  188. ;    This routine gets a confirm.
  189. ;    called by: comnd
  190.  
  191. cmcfrm:    call    cmgtch        ;Get a char.
  192.     ora    a        ;Is it negative (a terminator;a space or
  193.                 ;a tab will not be returned here as they
  194.                 ;will be seen as leading white space.)
  195.     rp            ;If not, return failure.
  196.     ani    7FH        ;Turn off the minus bit.
  197.     cpi    esc        ;Is it an escape?
  198.     jnz    cmcfr2
  199.     mvi    c,conout
  200.     mvi    e,bell        ;Get a bell.
  201.     call    bdos
  202.     xra    a
  203.     sta    cmaflg        ;Turn off the action flag.
  204.     lhld    cmcptr        ;Move the pointer to before the escape.
  205.     dcx    h
  206.     shld    cmcptr
  207.     shld    cmdptr
  208.     lxi    h,cmccnt    ;Get the char count.
  209.     dcr    m        ;Decrement it by one.
  210.     jmp    cmcfrm        ;Try again.
  211.  
  212. cmcfr2:    cpi    '?'        ;Curious?
  213.     jnz    cmcfr3
  214.     lxi    d,cmin00    ;Print something useful.
  215.     call    prtstr
  216.     call    prcrlf        ;Print a crlf.  [Toad Hall]
  217.      call    prprmp        ;Reprint the prompt  [Toad Hall]
  218.     lhld    cmdptr        ;Get the pointer into the buffer.
  219.     mvi    a,'$'        ;Put a $ there for printing.
  220.     mov    m,a
  221.     lhld    cmcptr
  222.     dcx    h        ;Decrement and save the buffer pointer.
  223.     shld    cmcptr
  224.     lxi    d,cmdbuf
  225.     call    prtstr
  226.     xra    a        ;Turn off the action flag.
  227.     sta    cmaflg
  228.     jmp    repars        ;Reparse everything.
  229.  
  230. cmcfr3:    cpi    ff        ;Is it a form feed?
  231.     cz    clrtop        ;If so blank the screen.
  232.     jmp    rskp
  233. ;
  234. ;    This routine parses a keyword from the table pointed
  235. ;    to in DE.  The format of the table is as follows:
  236. ;
  237. ;    addr:    db    n    ;Where n is the # of entries in the table.
  238. ;        db    m    ;M is the size of the keyword.
  239. ;        db    'string$' ;Where string is the keyword.
  240. ;        db    a,b    ;Where a & b are pieces of data
  241. ;                ;to be returned.  (Must be two of them.)
  242. ;
  243. ;    The keywords must be in alphabetical order.
  244. ;**** Note:  The data value a is returned in registers A and E.  The
  245. ;****    data value b is returned in register D.  This allows the two data
  246. ;    bytes to be stored as:
  247. ;        dw    xxx
  248. ;    and result in a correctly formatted 16-bit value in register pair
  249. ;    DE.
  250. ;    called by: comnd
  251.  
  252. cmkeyw:    shld    cmhlp        ;Save the help.
  253.     xchg            ;Get the address of the table.
  254.     shld    cmptab        ;Save the beginning of keyword tab for '?'.
  255.     mov    b,m        ;Get the number of entries in the table.
  256.     inx    h
  257.     shld    cmkptr
  258.     lhld    cmdptr        ;Save the command pointer.
  259.     shld    cmsptr
  260. cmkey2: mov    a,b        ;Get the number of entries left.
  261.     ora    a        ;Any left?
  262.     rz            ;If not we failed.
  263.     lhld    cmkptr
  264.     mov    e,m        ;Get the length of the keyword.
  265.     inx    h
  266. cmkey3:    dcr    e        ;Decrement the number of chars left.
  267.     mov    a,e
  268.     cpi    0FFH        ;Have we passed the end?
  269.     jm    cmkey5        ;If so go to the next.
  270.     call    cmgtch        ;Get a char.
  271.     ora    a        ;Is it a terminator?
  272.     jp    cmkey4        ;If positive, it is not.
  273.     ani    7FH        ;Turn off the minus bit.
  274.     cpi    '?'
  275.     jnz    cmky31
  276.     xra    a
  277.     sta    cmaflg        ;Turn off the action flag.
  278.     lxi    h,cmccnt    ;Decrement the char count.
  279.     dcr    m
  280. ;* Must go through the keyword table and print them.
  281.     lhld    cmhlp        ;For now print the help text.
  282.     xchg
  283.     call    prtstr
  284.     call    prcrlf        ;Print a crlf  [Toad Hall]
  285.     call    prprmp        ;Reprint the prompt  [Toad Hall]
  286.     lhld    cmdptr        ;Get the pointer into the buffer.
  287.     mvi    a,'$'        ;Put a $ there for printing.
  288.     mov    m,a
  289.     lhld    cmcptr
  290.     dcx    h        ;Decrement and save the buffer pointer.
  291.     shld    cmcptr
  292.     lxi    d,cmdbuf
  293.     call    prtstr
  294.     jmp    repars        ;Reparse everything.
  295.  
  296. cmky31:    cpi    esc        ;Is it an escape?
  297.     jnz    cmky35
  298.     xra    a
  299.     sta    cmaflg        ;Turn off the action flag.
  300.     push    d
  301.     push    b
  302.     push    h
  303.     call    cmambg
  304.      jmp    cmky32        ;Not ambiguous.
  305.     mvi    c,conout
  306.     mvi    e,bell
  307.     call    bdos        ;Ring the bell.
  308.     lhld    cmcptr        ;Move the pointer to before the escape.
  309.     dcx    h
  310.     shld    cmcptr
  311.     shld    cmdptr
  312.     lxi    h,cmccnt    ;Get the char count.
  313.     dcr    m        ;Decrement it by one.
  314.     pop    h
  315.     pop    b
  316.     pop    d
  317.     inr    e        ;Increment the left to parse char count.
  318.     jmp    cmkey3
  319.  
  320. cmky32:    lhld    cmcptr        ;Pointer into buffer.
  321.     dcx    h        ;Backup to the escape.
  322.     xchg
  323.     pop    h
  324.     push    h
  325. cmky33:    mov    a,m        ;Get the next char.
  326.     cpi    '$'        ;Finished?
  327.     jz    cmky34
  328.     inx    h
  329.     xchg
  330.     mov    m,a        ;Move it into the buffer.
  331.     inx    h
  332.     xchg
  333.     lda    cmccnt        ;Increment the char count.
  334.     inr    a
  335.     sta    cmccnt
  336.     jmp    cmky33
  337.  
  338. cmky34:    lda    cmccnt        ;Get the character count.
  339.     inr    a        ;Increment and save it.
  340.     sta    cmccnt
  341.     xchg            ;Put the command buffer pointer in HL.
  342.     mvi    a,' '        ;Get a blank.
  343.     mov    m,a        ;Put it in the command buffer.
  344.     inx    h        ;Increment the pointer
  345.     shld    cmcptr        ;Save the updated pointer.
  346.     shld    cmdptr
  347.     pop    h
  348.     push    h
  349.     xchg
  350.     call    prtstr        ;Print the rest of the keyword.
  351.     mvi    c,conout
  352.     mvi    e,' '
  353.     call    bdos        ;Print a blank.
  354.     pop    h
  355.     pop    b
  356.     pop    d
  357.     jmp    cmky37
  358.  
  359. cmky35:    push    h
  360.     push    d
  361.     call    cmambg
  362.      jmp    cmky36
  363.     lxi    d,cmer01
  364.     call    prtstr        ;Say its ambiguous.
  365.     jmp    prserr        ;Give up.
  366.  
  367. cmky36:    pop    d
  368.     pop    h
  369. cmky37:    inr    e        ;Add one incase it is negative.
  370.     mvi    d,0
  371.     dad    d        ;Increment past the keyword.
  372.     inx    h        ;Past the $.
  373.     mov    e,m        ;Get the data.
  374.     inx    h
  375.     mov    d,m
  376.     mov    a,e
  377.     jmp    rskp
  378.  
  379. cmkey4:    cpi    'a'        ;Is it less than a?
  380.     jm    cmky41        ;If so don't capitalize it.
  381.     cpi    'z'+1        ;Is it more than z?
  382.     jp    cmky41        ;If so don't capitalize it.
  383.     ani    137O        ;Capitalize it.
  384. cmky41:    mov    d,m        ;Get the next char of the keyword.
  385.     inx    h
  386.     cmp    d        ;Match?
  387.     jz    cmkey3        ;If so get the next letter.
  388.  
  389. cmkey5:    mvi    d,0
  390.     mov    a,e        ;Get the number of chars left.
  391.     ora    a        ;Is it negative?
  392.     jp    cmky51
  393.     mvi    d,0FFH        ;If so, sign extend.
  394. cmky51:    dad    d        ;Increment past the keyword.
  395.     lxi    d,0003H        ;Plus the $ and data.
  396.     dad    d
  397.     shld    cmkptr
  398.     dcr    b        ;Decrement the number of entries left.
  399.     lhld    cmsptr        ;Get the old cmdptr.
  400.     shld    cmdptr        ;Restore it.
  401. ;* check so we don't pass it.
  402.     jmp    cmkey2        ;Go check the next keyword.
  403. ;
  404. ;    Test keyword for ambiguity.
  405. ;    returns: nonskip if ambiguous, skip if OK.
  406. ;    called by: cmkeyw
  407.  
  408. cmambg:    dcr    b        ;Decrement the number of entries left.
  409.     rm            ;If none left then it is not ambiguous.
  410.     inr    e        ;This is off by one;adjust.
  411.     mov    c,e        ;Save the char count.
  412.     mov    a,e
  413.     ora    a        ;Any chars left?
  414.     rz            ;No, it can't be ambiguous.
  415.     mvi    d,0
  416.     dad    d        ;Increment past the keyword.
  417.     mvi    e,3        ;Plus the $ and data.
  418.     dad    d
  419.     mov    b,m        ;Get the length of the keyword.
  420.     inx    h
  421.     xchg
  422.     lhld    cmkptr        ;Get pointer to keyword entry.
  423.     mov    a,m        ;Get the length of the keyword.
  424.     sub    c        ;Subtract how many left.
  425.     mov    c,a        ;Save the count.
  426.     cmp    b
  427.     jz    cmamb0
  428.     rp            ;If larger than the new word then not amb.
  429. cmamb0:    lhld    cmsptr        ;Get the pointer to what parsed.
  430. cmamb1:    dcr    c        ;Decrement the count.
  431.     jm    rskp        ;If we are done then it is ambiguous.
  432.     xchg            ;Exchange the pointers.
  433.     mov    b,m        ;Get the next char of the keyword
  434.     inx    h
  435.     xchg            ;Exchange the pointers.
  436.     mov    a,m        ;Get the next parsed char.
  437.     inx    h
  438.     cpi    'a'        ;Is it less than a?
  439.     jm    cmamb2        ;If so don't capitalize it.
  440.     cpi    'z'+1        ;Is it more than z?
  441.     jp    cmamb2        ;If so don't capitalize it.
  442.     ani    137O
  443. cmamb2:    cmp    b        ;Are they equal?
  444.     rnz            ;If not then its not ambiguous.
  445.     jmp    cmamb1        ;Check the next char.
  446. ;
  447. ;    cmofil - parse output filespec
  448. ;    cmifil - parse input filespec
  449. ;    here from: comnd
  450.  
  451. cmofil:    mvi    a,0        ;Don't allow wildcards.
  452. ;    jmp    cmifil        ;For now, the same as CMIFI.
  453. cmifil:    sta    cmfwld        ;Set wildcard flag
  454.     xchg            ;Get the fcb address.
  455.     shld    cmfcb        ;Save it.
  456.     mvi    e,0        ;Initialize char count.
  457.     mvi    m,0        ;Set the drive to default to current.
  458.     inx    h
  459.     shld    cmfcb2
  460.     xra    a        ;Initialize counter.
  461. cmifi0:    mvi    m,' '        ;Blank the FCB.
  462.     inx    h
  463.     inr    a
  464.     cpi    0CH        ;Twelve?
  465.     jm    cmifi0
  466. cmifi1:    call    cmgtch        ;Get another char.
  467.     ora    a        ;Is it an action character?
  468.     jp    cmifi2
  469.     ani    7FH        ;Turn off the action bit.
  470.     cpi    '?'        ;A question mark?
  471.     jnz    cmif12
  472.     lda    cmfwld        ;[pcc006] Wildcards allowed?
  473.     ora    a        ;[pcc006]
  474.     jz    cmif11        ;[pcc006] complain if not
  475.     lhld    cmdptr        ;[jd] Increment buffer pointer
  476.     inx    h        ;[jd] that was decremented in cmgtch
  477.     shld    cmdptr        ;[jd] since we want this chr
  478.     lda    cmcptr        ;[pcc006] get lsb of real input pointer
  479.     cmp    l        ;[pcc006] is this the last chr input?
  480.     jnz    cmif1a        ;[pcc006] no, don't reset action flag
  481.     xra    a        ;[pcc006] yes, reset action flag
  482.     sta    cmaflg        ;[pcc006] 
  483. cmif1a:    mvi    a,'?'        ;[pcc006] get it back in A
  484.     jmp    cmifi8        ;Treat like any other character
  485.  
  486. cmif12:    cpi    esc        ;An escape?
  487.     jnz    cmif13
  488. ;Try to recognize file-spec a'la TOPS-20
  489.     xra    a
  490.     sta    cmaflg        ;Turn off the action flag.
  491.     lhld    cmcptr        ;Move the pointer to before the escape.
  492.     dcx    h
  493.     shld    cmcptr
  494.     shld    cmdptr
  495.     lxi    h,cmccnt    ;Get the char count.
  496.     dcr    m        ;Decrement it by one.
  497.     mov    a,e        ;Save character count up to now.
  498.     sta    temp1
  499.     cpi    9        ;Past '.'?
  500.     jm    cmfrec        ;No.
  501.     dcr    a        ;Yes, don't count point.
  502. cmfrec:    lhld    cmfcb2        ;Fill the rest with CP/M wildcards.
  503. cmfrc1:    cpi    11        ;Done?
  504.     jp    cmfrc2        ;Yes.
  505.     mvi    m,'?'
  506.     inx    h
  507.     inr    a
  508.     jmp    cmfrc1
  509.  
  510. cmfrc2:    mvi    c,sfirst    ;Find first matching file?
  511.     lhld    cmfcb
  512.     xchg
  513.     call    bdos
  514.     cpi    0FFH
  515.     jz    cmfrc9        ;No, lose.
  516.     lxi    h,fcbblk    ;Copy first file spec.
  517.     call    fspcop
  518.     lxi    h,fcbblk+10H    ;Get another copy (in case not ambiguous).
  519.     call    fspcop
  520.     mvi    c,snext        ;More matching specs?
  521.     lhld    cmfcb
  522.     xchg
  523.     call    bdos
  524.     cpi    0FFH
  525.     jz    cmfrc3        ;Only one.
  526.     lxi    h,fcbblk+10H    ;Copy second file spec.
  527.     call    fspcop
  528. cmfrc3:    lxi    d,fcbblk    ;Start comparing file names.
  529.     lxi    h,fcbblk+10H
  530.     lda    temp1        ;Bypass characters typed.
  531.     cpi    9        ;Past '.'?
  532.     jm    cmfrc4        ;No.
  533.     dcr    a        ;Yes, don't count point.
  534. cmfrc4:    mvi    c,0
  535. cmfrl1:    cmp    c        ;Bypassed?
  536.     jz    cmfrl2        ;Yes.
  537.     inx    d
  538.     inx    h
  539.     inr    c
  540.     jmp    cmfrl1        ;Repeat.
  541.  
  542. cmfrl2:    mov    a,c        ;Get file name characters processed.
  543.     cpi    11        ;All done?
  544.     jz    cmfrc5        ;Yes.
  545.     cpi    8        ;End of file name?
  546.     jnz    cmfrl3        ;No.
  547.     lda    temp1        ;Exactly at point?
  548.     cpi    9
  549.     jz    cmfrl3        ;Yes, don't output a second point.
  550.     mvi    a,'.'        ;Output separator.
  551.     call    cmfput
  552. cmfrl3:    ldax    d        ;Get a character from first file spec.
  553.     inx    d
  554.     mov    b,m        ;Get from second file spec.
  555.     inx    h
  556.     cmp    b        ;Compare.
  557.     jnz    cmfrc5        ;Ambiguous.
  558.     inr    c        ;Same, count.
  559.     cpi    ' '        ;Blank?
  560.     jz    cmfrl2        ;Yes, don't output.
  561.     call    cmfput        ;Put character into buffer.
  562.     jmp    cmfrl2        ;Repeat.
  563.  
  564. cmfrc5:    mov    a,c        ;Get count of characters processed.
  565.     sta    temp1        ;Save it.
  566.     mvi    a,'$'        ;Get terminator.
  567.     call    cmfput        ;Put it into buffer.
  568.     lhld    cmdptr        ;Output recognized characters.
  569.     xchg
  570.     mvi    c,prstr
  571.     call    bdos
  572.     lhld    cmcptr        ;Remove terminator from buffer.
  573.     dcx    h
  574.     shld    cmcptr
  575.     lxi    h,cmccnt
  576.     dcr    m
  577.     lda    temp1        ;Characters processed.
  578.     cpi    11        ;Complete file name.
  579.     jz    repars        ;Yes, don't beep.
  580.  
  581. cmfrc9:    mvi    c,conout
  582.     mvi    e,bell
  583.     call    bdos        ;Ring the bell.
  584.     jmp    repars
  585. ;
  586. ;    Continue file spec parsing.
  587.  
  588. cmif13:    mov    a,e        ;It must be a terminator.
  589.     ora    a        ;Test the length of the file name.
  590.     jz    cmifi9        ;If zero complain.
  591.     cpi    0DH
  592.     jp    cmifi9        ;If too long complain.
  593.     jmp    rskp        ;Otherwise we have succeeded.
  594.  
  595. cmifi2:    cpi    '.'
  596.     jnz    cmifi3
  597.     inr    e
  598.     mov    a,e
  599.     cpi    1H        ;Any chars yet?
  600.     jz    cmifi9        ;No, give error.
  601.     cpi    0AH        ;Tenth char?
  602.     jp    cmifi9        ;Past it, give an error.
  603.     mvi    c,9H
  604.     mvi    b,0
  605.     lhld    cmfcb
  606.     dad    b        ;Point to file type field.
  607.     shld    cmfcb2
  608.     mvi    e,9H        ;Say we've gotten nine.
  609.     jmp    cmifi1        ;Get the next char.
  610.  
  611. cmifi3:    cpi    ':'
  612.     jnz    cmifi4
  613.     inr    e
  614.     mov    a,e
  615.     cpi    2H        ;Is it in the right place for a drive?
  616.     jnz    cmifi9        ;If not, complain.
  617.     lhld    cmfcb2
  618.     dcx    h        ;Point to previous character.
  619.     mov    a,m        ;Get the drive name.
  620.     sui    '@'        ;Get the drive number.
  621.     shld    cmfcb2        ;Save pointer to beginning of name field.
  622.     dcx    h        ;Point to drive number.
  623.     mov    m,a        ;Put it in the fcb.
  624.     mvi    e,0        ;Start character count over.
  625.     jmp    cmifi1
  626.  
  627. cmifi4:    cpi    '*'
  628.     jnz    cmifi7
  629.     lda    cmfwld        ;Wildcards allowed?
  630.     cpi    0
  631.     jz    cmif11        ;No,complain
  632.     mov    a,e
  633.     cpi    8H        ;Is this in the name or type field?
  634.     jz    cmifi9        ;If its where the dot should be give up.
  635.     jp    cmifi5        ;Type.
  636.     mvi    b,8H        ;Eight chars.
  637.     jmp    cmifi6
  638.  
  639. cmifi5:    mvi    b,0CH        ;Three chars.
  640. cmifi6:    lhld    cmfcb2        ;Get a pointer into the FCB.
  641.     mvi    a,'?'
  642.     mov    m,a        ;Put a question mark in.
  643.     inx    h
  644.     shld    cmfcb2
  645.     inr    e
  646.     mov    a,e
  647.     cmp    b
  648.     jm    cmifi6        ;Go fill in another.
  649.     jmp    cmifi1        ;Get the next char.
  650.  
  651. cmifi7:    cpi    '!'        ;[pcc007] control chr or space?
  652.     jm    cmifi9        ;[pcc007] yes, illegal
  653.     mov    h,a        ;[5] stash input char for a bit
  654.     lda    ffussy        ;[5]  while we check the fussy flag
  655.     ora    a        ;[5] set the flags accordingly
  656.     mov    a,h        ;[5] restore the input character
  657.     jz    cmif7a        ;[5] if ffussy=0, allow <>.,;:?*[]
  658. ;[5] So far, we've eliminated "action characters" (including question),
  659. ;[5] period, colon, asterisk, control characters, and space.
  660. ;[5] That leaves us %(),/;<=>[\]_| to check for.
  661.     cpi    '%'        ;[5]
  662.     jz    cmifi9        ;[5]
  663.     cpi    '('        ;[5]
  664.     jz    cmifi9        ;[5]
  665.     cpi    ')'        ;[5]
  666.     jz    cmifi9        ;[5]
  667.     cpi    ','        ;[pcc007] weed out comma
  668.     jz    cmifi9        ;[pcc007]
  669.     cpi    '/'        ;[5]
  670.     jz    cmifi9        ;[5]
  671.     cpi    '9'+1        ;[pcc007] anything else 21H-39H is ok
  672.     jm    cmifi8        ;[pcc007] except '*' never gets here
  673.     cpi    '@'        ;[pcc007] all of 3AH-3FH is illegal
  674.     jm    cmifi9        ;[pcc007]
  675.     cpi    '['        ;[pcc007] [\] also illegal
  676.     jm    cmifi8        ;[pcc007]
  677.     cpi    ']'+1        ;[pcc007]
  678.     jm    cmifi9        ;[pcc007]
  679.     cpi    '_'        ;[5]
  680.     jz    cmifi9        ;[5] (If I was doing CP/M, I would have
  681.     cpi    '|'        ;[5]  just eliminated all them funny chars
  682.     jz    cmifi9        ;[5]  instead of a random selection)
  683. cmif7a:                ;[5]
  684.     cpi    'a'        ;[pcc007] if not lower case its ok
  685.     jm    cmifi8        ;[pcc007] (DEL never gets here)
  686.     cpi    'z'+1        ;[pcc007] only convert letters
  687.     jp    cmifi8        ;[pcc007]
  688.     ani    137O        ;Capitalize.
  689. cmifi8:    lhld    cmfcb2        ;Get the pointer into the FCB.
  690.     mov    m,a        ;Put the char there.
  691.     inx    h
  692.     shld    cmfcb2
  693.     inr    e
  694.     jmp    cmifi1
  695.  
  696. cmifi9:    lda    cmstat
  697.     cpi    cmifin        ;"silent"?
  698.     jz    r        ;Yes,let him go w/o check
  699.     lxi    d,cmer02
  700. cmif10:    mvi    c,prstr
  701.     call    bdos
  702.     ret
  703.  
  704. cmif11:    lxi    d,cmer03    ;Complain about wildcards.
  705.     jmp    cmif10
  706.  
  707. ;
  708.  
  709. ;    copy filename from buffer
  710. ;    called with HL = destination, A = position (0-3) in buffer
  711. ;    called by: cmifil
  712.  
  713. fspcop:    push    psw        ;Save A.
  714.     lxi    d,buff        ;Get the right offset in the buffer.
  715.     rlc
  716.     rlc
  717.     rlc
  718.     rlc
  719.     rlc
  720.     add     e
  721.     inr    a        ;Bypass drive spec.
  722.     mov    e,a
  723.     mvi    b,11        ;Copy file name.
  724. fspcp1:    ldax    d
  725.     inx    d
  726.     mov    m,a
  727.     inx    h
  728.     dcr    b
  729.     jnz    fspcp1
  730.     pop    psw        ;Restore A.
  731.     ret
  732.  
  733. ;    append character in A to command buffer
  734. ;    called by: cmifil
  735.  
  736. cmfput:    push    h        ;Save H.
  737.     lhld    cmcptr        ;Get buffer pointer.
  738.     mov    m,a        ;Store in buffer.
  739.     inx    h
  740.     shld    cmcptr
  741.     lxi    h,cmccnt    ;Count it.
  742.     inr    m
  743.     pop    h        ;Restore H.
  744.     ret
  745. ;
  746. ;    Read characters from the command buffer.
  747. ;    called by:  cmtext, cmcfrm, cmkeyw, cmifil
  748.  
  749. cmgtch:    push    h
  750.     push    b
  751. cmgtc1:    lda    cmaflg
  752.     ora    a        ;Is it set.
  753.     cz    cminbf        ;If the action char flag is not set get more.
  754.     lhld    cmdptr        ;Get a pointer into the buffer.
  755.     mov    a,m        ;Get the next char.
  756.     inx    h
  757.     shld    cmdptr
  758.     cpi    ' '        ;Is it a space?
  759.     jz    cmgtc2
  760.     cpi    tab        ;Or a tab?
  761.     jnz    cmgtc3
  762. cmgtc2:    lda    cmsflg        ;Get the space flag.
  763.     ora    a        ;Was the last char a space?
  764.     jnz    cmgtc1        ;Yes, get another char.
  765.     mvi    a,0FFH        ;Set the space flag.
  766.     sta    cmsflg
  767.     mvi    a,' '
  768.     pop    b
  769.     pop    h
  770.     jmp    cmgtc5
  771.  
  772. cmgtc3:    push    psw
  773.     xra    a
  774.     sta    cmsflg        ;Zero the space flag.
  775.     pop    psw
  776.     pop    b
  777.     pop    h
  778.     cpi    esc
  779.     jz    cmgtc5
  780.     cpi    '?'        ;Is the user curious?
  781.     jz    cmgtc4
  782.     cpi    cr
  783.     jz    cmgtc4
  784.     cpi    lf
  785.     jz    cmgtc4
  786.     cpi    ff
  787.     rnz            ;Not an action char, just return.
  788. cmgtc4:    push    h
  789.     lhld    cmdptr
  790.     dcx    h
  791.     shld    cmdptr
  792.     pop    h
  793. cmgtc5:    ori    80H        ;Make the char negative to indicate it is
  794.     ret            ;a terminator.
  795. ;
  796. ;    Read characters from console into command buffer, processing
  797. ;    editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del).
  798. ;    called by: comnd, cmgtch
  799.  
  800. cminbf:    push    psw
  801.     push    d
  802.     push    h
  803.     lda    cmaflg        ;Is the action char flag set?
  804.     ora    a
  805.     jnz    cminb9        ;If so get no more chars.
  806. cminb1:    lxi    h,cmccnt    ;Increment the char count.
  807.     inr    m
  808.     mvi    c,conin        ;Get a char.
  809.     call    bdos
  810.     lhld    cmcptr        ;Get the pointer into the buffer.
  811.     mov    m,a        ;Put it in the buffer.
  812.     inx    h
  813.     shld    cmcptr
  814.     cpi    25O        ;Is it a ^U?
  815.     jz    cmnb12        ;Yes.
  816.     cpi    30O        ;Is it a ^X?
  817.     jnz    cminb2
  818. cmnb12:    call    clrlin        ;Clear the line.
  819.     call    prprmp        ;Print the prompt  [Toad Hall]
  820.     lxi    h,cmdbuf
  821.     shld    cmcptr        ;Reset the point to the start.
  822.     lxi    h,cmccnt    ;Zero the count.
  823.     mvi    m,0
  824.     jmp    repars        ;Go start over.
  825.  
  826. cminb2:    cpi    10O        ;Backspace?
  827.     jz    cminb3
  828.     cpi    del        ;or Delete?
  829.     jnz    cminb4
  830.     call    delchr        ;Print the delete string.
  831. cminb3:    lda    cmccnt        ;Decrement the char count by two.
  832.     dcr    a
  833.     dcr    a
  834.     ora    a        ;Have we gone too far?
  835.     jp    cmnb32        ;If not proceed.
  836.     mvi    c,conout    ;Ring the bell.
  837.     mvi    e,bell
  838.     call    bdos
  839.     jmp    cmnb12        ;Go reprint prompt and reparse.
  840.  
  841. cmnb32:    sta    cmccnt        ;Save the new char count.
  842.     call    clrspc        ;Erase the character.
  843.     lhld    cmcptr        ;Get the pointer into the buffer.
  844.     dcx    h        ;Back up in the buffer.
  845.     dcx    h
  846.     shld    cmcptr
  847.     jmp    repars        ;Go reparse everything.
  848.  
  849. cminb4:    cpi    '?'        ;Is it a question mark.
  850.     jz    cminb6
  851.     cpi    esc        ;Is it an escape?
  852.     jz    cminb6
  853.     cpi    cr        ;Is it a carriage return?
  854.     jz    cminb5
  855.     cpi    lf        ;Is it a line feed?
  856.     jz    cminb5
  857.     cpi    ff        ;Is it a formfeed?
  858.     jnz    cminb1        ;no - just store it and get another character.
  859.     call    clrtop
  860. cminb5:    lda    cmccnt        ;Have we parsed any chars yet?
  861.     cpi    1
  862.     jz    prserr        ;If not, just start over.
  863. cminb6:    mvi    a,0FFH        ;Set the action flag.
  864.     sta    cmaflg
  865.     jmp    cminb9
  866.  
  867. cminb9:    pop    h
  868.     pop    d
  869.     pop    psw
  870.     ret
  871. ;
  872. ;Little utility to print the prompt.  (We do a LOT of these.)  [Toad Hall]
  873. ;Enters with nothing.
  874. ;Destroys HL (and I suppose B and DE and A).
  875.  
  876. prprmp:    lhld    cmprmp        ;Get the prompt.
  877.     xchg
  878.     call    prtstr
  879.     ret
  880.  
  881. IF    lasm
  882. LINK    CP4UTL
  883. ENDIF    ;lasm  [Toad Hall]
  884.