home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / a / cpscmd.asm < prev    next >
Assembly Source File  |  2020-01-01  |  32KB  |  1,141 lines

  1. ; CPSCMD.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. ;
  25. ;edit 13, 17-Jan-1991 by MF. Modified "cmifil" routine to zero the entire
  26. ;    fcb (not just the extent) to fix a bug in the COPY command which
  27. ;    prevented successive COPY commands from working properly.
  28. ;edit 12, 16-Jan-1991 by MF. Modified routine "cmkeyw" to ignore leading
  29. ;    spaces/tabs before a keyword. This apparently was the intent in
  30. ;    "prompt" and "repars" (at least for command-lines) as the variable 
  31. ;    "cmsflg "is set upon command parse and reparse. The intent was ,
  32. ;    subverted, however, as "cmkeyw" did not reset the flag to ignore
  33. ;    leading white space for each search thru the key tables (even though
  34. ;    the buffer pointer to the keyword entered was reset). The fix was
  35. ;    to reset the "spaces seen" flag (cmsflg) after "cmkey2" so that
  36. ;    it is reset each time a new table entry is compared to the text
  37. ;    the user has entered from the keyboard/TAKE-file etc. The upshot
  38. ;    of all this is that the kluge code in "cminbf" at "cminb0" designed
  39. ;    to force Kermit to ignore leading white space on command-lines in
  40. ;    TAKE-files and on the CP/M command-line is no longer needed and,
  41. ;    therefore, has been eliminated. Also modify "comnd" to expect leading
  42. ;    spaces for functions other than "get keyword".
  43. ;edit 11, 26-Dec-1990 by MF. Modified routines to ignore leading white space
  44. ;    in lines from TAKE-files as well as during input from the CP/M
  45. ;    command-line  (form-feeds are now considered white space under these
  46. ;    circumstances).
  47. ;edit 10, 8-Sep-1990 by Mike Freeman.  Modified routines to ignore leading
  48. ;    spaces/tabs when processing Kermit commands from the CP/M
  49. ;    command-line.
  50. ;    Added flag CMBFLG to allow initial word on a command-line
  51. ;    to be blank (useful for Remote commands such as Remote CWD etc).
  52. ;    Added flag cmqflg to prevent character-echoing while entering
  53. ;    commands so Remote CWD etc can have nonechoing password entry.
  54. ; edit 9, 15 June, 1987 by OBSchou.  Bug fixing to allow a second filename
  55. ;    (quiet) be entered as d:<blank>.  Previous revision put the drive name 
  56. ;    in first character of FCB, I put that character back to a space.
  57. ;
  58. ; edit 8, 12 June, 1987 by OBSchou.  Addedin code in cmkeyw to print
  59. ;    20 lines of help, then pause for a key from the user befor
  60. ;    proceeding with help.
  61. ;
  62. ; edit 7, 11 March, 1987 by OBSchou for Richard Russell, BBC.  He writes:
  63. ;    Bug in cmtext which prevented use of octal characters (\nnn) fixed.
  64. ;
  65. ; edit 6, 18 June, 1986 by OBSchou, Loughborough University, Leics. UK
  66. ;       added code to parse a number from user input.  Added check to make 
  67. ;       sure the input command buffer does not overflow the limit.
  68. ;
  69. ; edit 5a: 7 March, 1986.  OBSchou. Added stuff rom MJ Carter.  He writes:
  70. ;       7th May 85, MJ Carter [majoc], Nottingham University
  71. ;       Code in cmifil() put one too many spaces in the FCB; this caused 
  72. ;       the BDOS of the British Micro Mimi to search for exteny 32,
  73. ;       rather than extent 0, so era() always said "can't find file"
  74. ;       Puttig a null at the point in question ought to fix 9 it.
  75. ;
  76. ; edit 5: 6-Feb-85 by Charles Carvalho
  77. ;       Make ffussy a runtime (rather than assembly-time) switch, to
  78. ;       eliminate conditional assembly in system-independent module.
  79. ;       Don't allow _%|()/\ in filenames if ffussy set; my CP/M manual
  80. ;       disallows those, too.
  81. ;
  82. ; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
  83. ;
  84. ;pcc006 2-jan-85        VJC     modules:cp4cmd,cp4utl
  85. ;       Problems with "?" in filespecs.  On reparse, may cause action
  86. ;       flag to be reset at wrong point, requiring multiple <CR>'s
  87. ;       to terminate the line or other weird stuff.  Also need to
  88. ;       check flag and complain if wild-cards illegal.
  89.  
  90. ;pcc007 2-Jan-85        vjc     modules:cp4def,cp4cmd
  91. ;       Cmifil is too fussy about what characters to accept in a
  92. ;       filespec.  My CP/M manual says any printable character is ok
  93. ;       except <>.,;:?*[], and lower case.  In practice, even those work
  94. ;       sometimes.  Kermit itself uses '&' if file warning is on,
  95. ;       and then won't let you reference the file.  Allow all
  96. ;       printable characters except those above.  Add conditional
  97. ;       ffussy, so that if not ffussy, all special characters will be
  98. ;       allowed, just convert lower to upper-case.
  99.  
  100. ; edit 3: July 8, 1984 (CJC)
  101. ;       integrate Toad Hall changes for LASM compatibility: CP4CPM is linked
  102. ;       by CP4WLD, and links CP4UTL.
  103. ;       
  104. ; edit 2: June 5, 1984 (CJC)
  105. ;       formatting and documentation; delete unnecessary code at cminb7; add
  106. ;       module version string.
  107. ;
  108. ; edit 1: May, 1984 (CJC)
  109. ;       extracted from CPMBASE.M80 version 3.9; modifications are described in
  110. ;       the accompanying .UPD file.
  111.  
  112. cmdver:    db    'CPSCMD.ASM (13)  17-Jan-1991$'    ; name, edit number, date
  113.  
  114. ;       This routine prints the prompt in DE and specifies the reparse
  115. ;       address.
  116. ;       called by:  kermit
  117.  
  118. prompt:    pop    h        ;Get the return address.
  119.     push    h        ;Put it on the stack again.
  120.     shld    cmrprs        ;Save it as the address to go to on reparse.
  121.     lxi    h,0        ;Clear out hl pair.
  122.     dad    sp        ;Get the present stack pointer.
  123.     shld    cmostp        ;Save for later restoral.
  124.     xchg            ;Save the pointer to the prompt.
  125.     shld    cmprmp
  126.     xchg
  127.     lxi    h,cmdbuf
  128.     shld    cmcptr        ;Initialize the command pointer.
  129.     shld    cmdptr
  130.     xra    a
  131.     sta    cmaflg        ;Zero the flags.
  132.     sta    cmccnt
  133. ;    mvi    a,0FFH        ;Try it this way (Daphne.)
  134. ;    sta    cmsflg
  135.     call    prcrlf        ;Print a CR/LF [Toad Hall]
  136.     jmp    prprmp        ;Print the prompt.  [Toad Hall]
  137. ;
  138. ;       This address is jumped to on reparse.
  139. ;       here from:  cmcfrm, cmkeyw, cmifil, cminbf
  140.  
  141. repars:    lhld    cmostp        ;Get the old stack pointer.
  142.     sphl            ;Make it the present one.
  143.     lxi    h,cmdbuf
  144.     shld    cmdptr
  145. ;    mvi    a,0FFH        ;Try it this way (Daphne.)
  146. ;    sta    cmsflg
  147.     lhld    cmrprs        ;Get the reparse address.
  148.     pchl            ;Go there.
  149.  
  150. ;       This address can be jumped to on a parsing error.
  151. ;       here from:  cmkeyw, cminbf
  152.  
  153. prserr:    lhld    cmostp        ;Get the old stack pointer.
  154.     sphl            ;Make it the present one.
  155.     lxi    h,cmdbuf
  156.     shld    cmcptr        ;Initialize the command pointer.
  157.     shld    cmdptr
  158.     xra    a
  159.     sta    cmaflg        ;Zero the flags.
  160.     sta    cmccnt
  161. ;    mvi    a,0FFH        ;Try it this way (Daphne.)
  162. ;    sta    cmsflg
  163.     call    prcrlf        ;Print a CR/LF  [Toad Hall]
  164.     call    prprmp        ;Print the prompt  [Toad Hall]
  165. ;* Instead return to before the prompt call.
  166.     lhld    cmrprs
  167.     pchl
  168. ;
  169. ;       This routine parses the specified function in A.  Any additional
  170. ;       information is in DE and HL.
  171. ;       Returns +1 on success
  172. ;               +4 on failure (assumes a JMP follows the call)
  173. ;       called by:  log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd
  174. ;    and CPSREM
  175.  
  176. comnd:    sta    cmstat        ;Save what we are presently parsing.
  177.     call    cminbf        ;Get chars until an action or a erase char.
  178.     push    psw        ;[MF]Save function
  179.     mvi    a,0ffh        ;[MF]Expect leading spaces
  180.     sta    cmsflg        ;[MF]...
  181.     pop    psw        ;[MF]Restore function
  182.     cpi    cmcfm        ;Parse a confirm?
  183.     jz    cmcfrm        ;Go get one.
  184.     cpi    cmkey        ;Parse a keyword?
  185.     jz    cmkeyw        ;Try and get one.
  186.     cpi    cmifi        ;Parse an input file spec?
  187.     jz    cmifil        ;Go get one.
  188.     cpi    cmifin        ;Input file-spec silent?
  189.     jz    cmifil        ;do as he wishes
  190.     cpi    cmofi        ;Output file spec?
  191.     jz    cmofil        ;Go get one.
  192.     cpi    cmtxt        ;Parse arbitrary text?
  193.     jz    cmtext        ;Go do it.
  194.     cpi    cmnum        ;[7] Parse a number?
  195.     jz    cmnumb        ;[7] go do it
  196.     lxi    d,cmer00    ;"?Unrecognized COMND call"
  197.     call    prtstr
  198.     ret
  199. ;
  200. ;       This routine parses arbitrary text up to a CR.
  201. ;       Accepts DE:     address to put text
  202. ;       Returns in A:   number of chars in text (may be 0)
  203. ;                DE:    updated pointer
  204. ;       called by: comnd
  205.  
  206. cmtext:    xra    a        ; clear counters erc for slashes etc
  207.     sta    slshsn        ; if we are in a slash sequence
  208.     sta    slashn        ; the octal number being entered
  209.     sta    slashc        ; number of characters entered
  210.  
  211.     xchg            ;Put the pointer to the dest in HL.
  212.     shld    cmptab        ;Save the pointer.
  213.     mvi    b,0        ;Init the char count
  214. cmtxt1:    call    cmgtch        ;Get a char.
  215.     ora    a        ;Terminator?
  216.     jp    cmtx3        ;No, put in user space. [rtr] was cmtx5
  217.     ani    7FH        ;Turn off minus bit.
  218.     cpi    esc        ;An escape?
  219.     jnz    cmtxt2        ;No.
  220.     mvi    c,conout
  221.     mvi    e,bell        ;Get a bell.
  222.     call    bdos
  223.     xra    a
  224.     sta    cmaflg        ;Turn off the action flag.
  225.     lhld    cmcptr        ;Move the pointer to before the escape.
  226.     dcx    h
  227.     shld    cmcptr
  228.     shld    cmdptr
  229.     lxi    h,cmccnt    ;Get the char count.
  230.     dcr    m        ;Decrement it by one.
  231.     jmp    cmtxt1        ;Try again.
  232.  
  233. cmtxt2:    cpi    '?'             ;Is it a question mark?
  234.     jz    cmtxt4        ;If so put it in the text. [rtr] was cmtx3
  235.     cpi    ff        ;Is it a formfeed?
  236.     cz    clrtop        ;If so blank the screen.
  237.     mov    a,b        ;Return the count.
  238.     lhld    cmptab        ;Return updated pointer in HL.
  239.     xchg
  240.     jmp    rskp        ;Return success.
  241.  
  242. cmtx3:    cpi    '\'             ; slash?
  243.     jnz    cmtx3a        ; nope, so try something else
  244.     lda    slshsn        ; a slash already entered?
  245.     ana    a
  246.     cma            ;[rtr]
  247.     jnz    cmtx3a        ; yes, so assume its a valid slash to enter
  248.     sta    slshsn        ; make sure the flag is set for next time routnd
  249.     jmp    cmtxt1        ; get another character
  250.  
  251. cmtx3a:
  252. ;    lxi    h,cmaflg    ;Point to the action flag.
  253. ;    mvi    m,0        ;Set it to zero.
  254.     mov    e,a        ; save it in case we are interpreting a slash
  255.     lda    slshsn        ; slash already entered?
  256.     ana    a        ; test flag
  257.     mov    a,e        ; restore it in case...
  258.     jz    cmtx5        ; not a slash seen, so enter as a normal character
  259.     cpi    '\'
  260.     jnz    cmtx3b        ; \\ not detected
  261.     lda    slashn        ; else get number
  262.     jmp    cmtx5b        ; and enter it ( in the case of \n or \nn)
  263.                 ; here if an octal number of 1 or 2 digits
  264.                 ; entered instead of 3, followed by \ again
  265.  
  266. cmtx3b:
  267.     sui    30h        ; else it should be an octal number
  268.     jm    cmtxt6        ; if not a digit complain
  269.     cpi    8        ; ditto
  270.     jp    cmtxt6        ;[rtr] was cmtxt
  271.     mov    e,a        ; else add it to the number already entered
  272.     lda    slashn
  273.     add    a
  274.     add    a
  275.     add    a        ; multiply by 8
  276.     add    e
  277.     sta    slashn
  278.     lda    slashc        ; get the count
  279.     inr    a
  280.     sta    slashc        ; plus one.  If three then a number entered
  281.     cpi    3
  282.     lda    slashn        ; get the number in case...
  283.     jz    cmtx5
  284.     jmp    cmtxt1        ; else loop
  285.  
  286. cmtxt4:    lhld    cmdptr        ;[rtr] Get a pointer into the buffer
  287.     inx    h        ;[rtr] Bump past '?'
  288.     shld    cmdptr        ;[rtr]
  289. cmtx5:    call    cmtx5c
  290.     jmp    cmtxt1        ; put this into a subroutine
  291.  
  292. cmtx5b:
  293.     call    cmtx5c        ; here if we see \n\ or \nn\ rather than \nnn\
  294.     mvi    a,'\'           ; so send slash number to buffer, 
  295.     sta    slshsn        ; re-store a slash seen
  296.     jmp    cmtxt1        ; try next one
  297.  
  298. cmtx5c:
  299.     inr    b        ;Increment the count.
  300.     lhld    cmptab        ;Get the pointer.
  301.     mov    m,a        ;Put the char in the array.
  302.     inx    h
  303.     shld    cmptab        ;Save the updated pointer.
  304.     xra    a        ; clear slash counters etc
  305.     sta    slashc
  306.     sta    slashn
  307.     sta    slshsn
  308.     ret            ; and exit
  309.  
  310. cmtxt6:    lxi    d,cmer05    ; complain - not a valid \ parameter
  311.     call    prtstr
  312.     jmp    kermit        ; and try another command
  313.     ds    20h        ; for debugging
  314. ;
  315. ;       This routine gets a number from user input.
  316. ;       Called by: comnd
  317. ;
  318. cmnumb:    lxi    h,0        ; make sure the number is zero to start with
  319.     shld    number
  320. cmnum0:    call    cmgtch        ; get another character
  321.     ora    a        ; if negative then its an action
  322.     jp    cmnum1        ; nope, so (possibly) valid input
  323.     ani    7fh        ; else lets see what it is...
  324.     cpi    esc        ; do not know what to do with this one...
  325.     cpi    ' '             ; if it is a space then either a return or more
  326.     jnz    cmnum2        ; else
  327.     jmp    rskp        ; space is a deliminter
  328.     dw    0        ; set three bytes aside for a jump/call
  329.     dw    0        ; and then another three just in case...
  330.     dw    0        ; making 6 bytes
  331. cmnum2:    cpi    '?'             ; user is curious
  332.     jz    gnum2
  333.     cpi    cr        ; end of input?
  334.     jz    cmnumx
  335. gnum1:    jmp    prserr        ; did not under stand this, so error
  336. cmnumx:    dw    0
  337.     dw    0
  338.     jmp    rskp        ; return ok
  339.  
  340. gnum2:    lhld    number        ; get the number.. if at all entered
  341.     mov    a,l
  342.     ora    h        ; if hl = 0 then possibly no number entered
  343.     lxi    d,cmin02    ; say confirm...or more on line
  344.     jnz    gnum21        ; else say enter a return
  345.     lxi    d,cmin01    ; say enter a number
  346. gnum21:    call    prtstr        ; say it
  347.     call    prcrlf        ; do a lf
  348.     call    prprmp        ; another reprompt
  349.     lhld    cmdptr        ; get pointer of string already entered
  350.     mvi    m,'$'           ; dollar it to  set end of line
  351.     lhld    cmcptr
  352.     dcx    h        ; decrement and save the buffer pointer
  353.     shld    cmcptr
  354.     lxi    d,cmdbuf
  355.     call    prtstr        ; print what has already been entered
  356.     xra    a
  357.     sta    cmaflg        ; turn the action flag off
  358.     jmp    repars        ; and try again
  359.  
  360.     mvi    a,cmcfm        ; parse a confirm
  361. dw    0
  362. dw    0
  363. dw    0
  364. dw    0
  365. dw    0    ; some space to patch...
  366. dw    0
  367.  
  368. cmnum1:    ani    7fh        ; here for a (potentially) valid number
  369.     sui    '0'             ; less ascii bias
  370.     jc    gnum3
  371.     cpi    10        ; if 10 or more its still bad
  372.     jnc    gnum3
  373.     cmc
  374.     lhld    number        ; now multiply number by ten and add the new value
  375.     push    h
  376.     pop    d
  377.     dad    h        ; hl = hl * 2
  378.     dad    h        ; * 4
  379.     dad    d        ; * 5
  380.     dad    h        ; * 10
  381.     mvi    d,0
  382.     mov    e,a        ; add de to hl...
  383.     dad    d
  384.     shld    number
  385.     jmp    cmnum0
  386. ;
  387. gnum3:    lxi    d,cmer04    ; invalid number...
  388.     call    prtstr
  389.     jmp    rskp
  390. ;
  391.  
  392. ;
  393. ;       This routine gets a confirm.
  394. ;       called by: comnd
  395.  
  396. cmcfrm:    call    cmgtch        ;Get a char.
  397.     ora    a        ;Is it negative (a terminator;a space or
  398.                 ;a tab will not be returned here as they
  399.                 ;will be seen as leading white space.)
  400.     rp            ;If not, return failure.
  401.     ani    7FH        ;Turn off the minus bit.
  402.     cpi    esc        ;Is it an escape?
  403.     jnz    cmcfr2
  404.     mvi    c,conout
  405.     mvi    e,bell        ;Get a bell.
  406.     call    bdos
  407.     xra    a
  408.     sta    cmaflg        ;Turn off the action flag.
  409.     lhld    cmcptr        ;Move the pointer to before the escape.
  410.     dcx    h
  411.     shld    cmcptr
  412.     shld    cmdptr
  413.     lxi    h,cmccnt    ;Get the char count.
  414.     dcr    m        ;Decrement it by one.
  415.     jmp    cmcfrm        ;Try again.
  416.  
  417. cmcfr2:    cpi    '?'             ;Curious?
  418.     jnz    cmcfr3
  419.     lxi    d,cmin00    ;Print something useful.
  420.     call    prtstr
  421.     call    prcrlf        ;Print a crlf.  [Toad Hall]
  422.     call    prprmp        ;Reprint the prompt  [Toad Hall]
  423.     lhld    cmdptr        ;Get the pointer into the buffer.
  424.     mvi    a,'$'           ;Put a $ there for printing.
  425.     mov    m,a
  426.     lhld    cmcptr
  427.     dcx    h        ;Decrement and save the buffer pointer.
  428.     shld    cmcptr
  429.     lxi    d,cmdbuf
  430.     call    prtstr
  431.     xra    a        ;Turn off the action flag.
  432.     sta    cmaflg
  433.     jmp    repars        ;Reparse everything.
  434.  
  435. cmcfr3:    cpi    ff        ;Is it a form feed?
  436.     cz    clrtop        ;If so blank the screen.
  437.     jmp    rskp
  438. ;
  439. ;       This routine parses a keyword from the table pointed
  440. ;       to in DE.  The format of the table is as follows:
  441. ;
  442. ;       addr:   db      n       ;Where n is the # of entries in the table.
  443. ;               db      m       ;M is the size of the keyword.
  444. ;               db      'string$' ;Where string is the keyword.
  445. ;               db      a,b     ;Where a & b are pieces of data
  446. ;                               ;to be returned.  (Must be two of them.)
  447. ;
  448. ;       The keywords must be in alphabetical order.
  449. ;**** Note:  The data value a is returned in registers A and E.  The
  450. ;****   data value b is returned in register D.  This allows the two data
  451. ;       bytes to be stored as:
  452. ;               dw      xxx
  453. ;       and result in a correctly formatted 16-bit value in register pair
  454. ;       DE.
  455. ;       called by: comnd
  456.  
  457. cmkeyw:    shld    cmhlp        ;Save the help.
  458.     xchg            ;Get the address of the table.
  459.     shld    cmptab        ;Save the beginning of keyword tab for '?'.
  460.     mov    b,m        ;Get the number of entries in the table.
  461.     inx    h
  462.     shld    cmkptr
  463.     lhld    cmdptr        ;Save the command pointer.
  464.     shld    cmsptr
  465. cmkey2:    mov    a,b        ;Get the number of entries left.
  466.     ora    a        ;Any left?
  467.     rz            ;If not we failed.
  468.     mvi    a,0ffh        ;[MF]Make sure we ignore leading spaces
  469.     sta    cmsflg        ;[MF]...
  470.     lhld    cmkptr
  471.     mov    e,m        ;Get the length of the keyword.
  472.     inx    h
  473. cmkey3:    dcr    e        ;Decrement the number of chars left.
  474.     mov    a,e
  475.     cpi    0FFH        ;Have we passed the end?
  476.     jm    cmkey5        ;If so go to the next.
  477.     call    cmgtch        ;Get a char.
  478.     ora    a        ;Is it a terminator?
  479.     jp    cmkey4        ;If positive, it is not.
  480.     ani    7FH        ;Turn off the minus bit.
  481.     cpi    '?'
  482.     jnz    cmky31
  483.     xra    a
  484.     sta    cmaflg        ;Turn off the action flag.
  485.     lxi    h,cmccnt    ;Decrement the char count.
  486.     dcr    m
  487. ;* Must go through the keyword table and print them.
  488.     lhld    cmhlp        ;For now print the help text.
  489.     xchg
  490.     call    p20ln        ;[8] print at most 20 lines then pause
  491. ;    call    prtstr
  492.     call    prcrlf        ;Print a crlf  [Toad Hall]
  493.     call    prprmp        ;Reprint the prompt  [Toad Hall]
  494.     lhld    cmdptr        ;Get the pointer into the buffer.
  495.     mvi    a,'$'           ;Put a $ there for printing.
  496.     mov    m,a
  497.     lhld    cmcptr
  498.     dcx    h        ;Decrement and save the buffer pointer.
  499.     shld    cmcptr
  500.     lxi    d,cmdbuf
  501.     call    prtstr
  502.     jmp    repars        ;Reparse everything.
  503.  
  504. cmky31:    cpi    esc        ;Is it an escape?
  505.     jnz    cmky35
  506.     xra    a
  507.     sta    cmaflg        ;Turn off the action flag.
  508.     push    d
  509.     push    b
  510.     push    h
  511.     call    cmambg
  512.     jmp    cmky32        ;Not ambiguous.
  513.     mvi    c,conout
  514.     mvi    e,bell
  515.     call    bdos        ;Ring the bell.
  516.     lhld    cmcptr        ;Move the pointer to before the escape.
  517.     dcx    h
  518.     shld    cmcptr
  519.     shld    cmdptr
  520.     lxi    h,cmccnt    ;Get the char count.
  521.     dcr    m        ;Decrement it by one.
  522.     pop    h
  523.     pop    b
  524.     pop    d
  525.     inr    e        ;Increment the left to parse char count.
  526.     jmp    cmkey3
  527.  
  528. cmky32:    lhld    cmcptr        ;Pointer into buffer.
  529.     dcx    h        ;Backup to the escape.
  530.     xchg
  531.     pop    h
  532.     push    h
  533. cmky33:    mov    a,m        ;Get the next char.
  534.     cpi    '$'             ;Finished?
  535.     jz    cmky34
  536.     inx    h
  537.     xchg
  538.     mov    m,a        ;Move it into the buffer.
  539.     inx    h
  540.     xchg
  541.     lda    cmccnt        ;Increment the char count.
  542.     inr    a
  543.     sta    cmccnt
  544.     jmp    cmky33
  545.  
  546. cmky34:    lda    cmccnt        ;Get the character count.
  547.     inr    a        ;Increment and save it.
  548.     sta    cmccnt
  549.     xchg            ;Put the command buffer pointer in HL.
  550.     mvi    a,' '           ;Get a blank.
  551.     mov    m,a        ;Put it in the command buffer.
  552.     inx    h        ;Increment the pointer
  553.     shld    cmcptr        ;Save the updated pointer.
  554.     shld    cmdptr
  555.     pop    h
  556.     push    h
  557.     xchg
  558.     call    prtstr        ;Print the rest of the keyword.
  559.     mvi    c,conout
  560.     mvi    e,' '
  561.     call    bdos        ;Print a blank.
  562.     pop    h
  563.     pop    b
  564.     pop    d
  565.     jmp    cmky37
  566.  
  567. cmky35:    push    h
  568.     push    d
  569.     call    cmambg
  570.     jmp    cmky36
  571.     lxi    d,cmer01
  572.     call    prtstr        ;Say its ambiguous.
  573.     jmp    prserr        ;Give up.
  574.  
  575. cmky36:    pop    d
  576.     pop    h
  577. cmky37:    inr    e        ;Add one incase it is negative.
  578.     mvi    d,0
  579.     dad    d        ;Increment past the keyword.
  580.     inx    h        ;Past the $.
  581.     mov    e,m        ;Get the data.
  582.     inx    h
  583.     mov    d,m
  584.     mov    a,e
  585.     jmp    rskp
  586.  
  587. cmkey4:    cpi    'a'             ;Is it less than a?
  588.     jm    cmky41        ;If so don't capitalize it.
  589.     cpi    'z'+1           ;Is it more than z?
  590.     jp    cmky41        ;If so don't capitalize it.
  591.     ani    137O        ;Capitalize it.
  592. cmky41:    mov    d,m        ;Get the next char of the keyword.
  593.     inx    h
  594.     cmp    d        ;Match?
  595.     jz    cmkey3        ;If so get the next letter.
  596.  
  597. cmkey5:    mvi    d,0
  598.     mov    a,e        ;Get the number of chars left.
  599.     ora    a        ;Is it negative?
  600.     jp    cmky51
  601.     mvi    d,0FFH        ;If so, sign extend.
  602. cmky51:    dad    d        ;Increment past the keyword.
  603.     lxi    d,0003H        ;Plus the $ and data.
  604.     dad    d
  605.     shld    cmkptr
  606.     dcr    b        ;Decrement the number of entries left.
  607.     lhld    cmsptr        ;Get the old cmdptr.
  608.     shld    cmdptr        ;Restore it.
  609. ;* check so we don't pass it.
  610.     jmp    cmkey2        ;Go check the next keyword.
  611. ;
  612. ;       Test keyword for ambiguity.
  613. ;       returns: nonskip if ambiguous, skip if OK.
  614. ;       called by: cmkeyw
  615.  
  616. cmambg:    dcr    b        ;Decrement the number of entries left.
  617.     rm            ;If none left then it is not ambiguous.
  618.     inr    e        ;This is off by one;adjust.
  619.     mov    c,e        ;Save the char count.
  620.     mov    a,e
  621.     ora    a        ;Any chars left?
  622.     rz            ;No, it can't be ambiguous.
  623.     mvi    d,0
  624.     dad    d        ;Increment past the keyword.
  625.     mvi    e,3        ;Plus the $ and data.
  626.     dad    d
  627.     mov    b,m        ;Get the length of the keyword.
  628.     inx    h
  629.     xchg
  630.     lhld    cmkptr        ;Get pointer to keyword entry.
  631.     mov    a,m        ;Get the length of the keyword.
  632.     sub    c        ;Subtract how many left.
  633.     mov    c,a        ;Save the count.
  634.     cmp    b
  635.     jz    cmamb0
  636.     rp            ;If larger than the new word then not amb.
  637. cmamb0:    lhld    cmsptr        ;Get the pointer to what parsed.
  638. cmamb1:    dcr    c        ;Decrement the count.
  639.     jm    rskp        ;If we are done then it is ambiguous.
  640.     xchg            ;Exchange the pointers.
  641.     mov    b,m        ;Get the next char of the keyword
  642.     inx    h
  643.     xchg            ;Exchange the pointers.
  644.     mov    a,m        ;Get the next parsed char.
  645.     inx    h
  646.     cpi    'a'             ;Is it less than a?
  647.     jm    cmamb2        ;If so don't capitalize it.
  648.     cpi    'z'+1           ;Is it more than z?
  649.     jp    cmamb2        ;If so don't capitalize it.
  650.     ani    137O
  651. cmamb2:    cmp    b        ;Are they equal?
  652.     rnz            ;If not then its not ambiguous.
  653.     jmp    cmamb1        ;Check the next char.
  654. ;
  655. ;       cmofil - parse output filespec
  656. ;       cmifil - parse input filespec
  657. ;       here from: comnd
  658.  
  659. cmofil:    mvi    a,0        ;Don't allow wildcards.
  660. ;       jmp     cmifil          ;For now, the same as CMIFI.
  661. cmifil:    sta    cmfwld        ;Set wildcard flag
  662.     xchg            ;Get the fcb address.
  663.     shld    cmfcb        ;Save it.
  664.     mvi    e,0        ;Initialize char count.
  665.     mvi    m,0        ;Set the drive to default to current.
  666.     inx    h
  667.     shld    cmfcb2
  668.     xra    a        ;Initialize counter.
  669. cmifi0:    mvi    m,' '           ;Blank the FCB.
  670.     inx    h
  671.     inr    a
  672. ;       cpi     0CH             ;Twelve? [5a dont use this]
  673.     cpi    0Bh        ; [majoc 850585] Eleven?
  674.     jm    cmifi0
  675. cmif0a:                ;[MF]Zero entire fcb, not just the extent
  676.     mvi    m,0        ; [majoc 850507] Specify extent 0
  677.     inx    h        ;[MF]Increment fcb byte pointer
  678.     inr    a        ;[MF]Increment fcb byte count
  679.     cpi    32        ;[MF]Done with fcb?
  680.     jm    cmif0a        ;[MF]No, zero until done
  681. cmifi1:    call    cmgtch        ;Get another char.
  682.     ora    a        ;Is it an action character?
  683.     jp    cmifi2
  684.     ani    7FH        ;Turn off the action bit.
  685.     cpi    '?'             ;A question mark?
  686.     jnz    cmif12
  687.     lda    cmfwld        ;[pcc006] Wildcards allowed?
  688.     ora    a        ;[pcc006]
  689.     jz    cmif11        ;[pcc006] complain if not
  690.     lhld    cmdptr        ;[jd] Increment buffer pointer
  691.     inx    h        ;[jd] that was decremented in cmgtch
  692.     shld    cmdptr        ;[jd] since we want this chr
  693.     lda    cmcptr        ;[pcc006] get lsb of real input pointer
  694.     cmp    l        ;[pcc006] is this the last chr input?
  695.     jnz    cmif1a        ;[pcc006] no, don't reset action flag
  696.     xra    a        ;[pcc006] yes, reset action flag
  697.     sta    cmaflg        ;[pcc006] 
  698. cmif1a:    mvi    a,'?'           ;[pcc006] get it back in A
  699.     jmp    cmifi8        ;Treat like any other character
  700.  
  701. cmif12:    cpi    esc        ;An escape?
  702.     jnz    cmif13
  703. ;Try to recognize file-spec a'la TOPS-20
  704.     xra    a
  705.     sta    cmaflg        ;Turn off the action flag.
  706.     lhld    cmcptr        ;Move the pointer to before the escape.
  707.     dcx    h
  708.     shld    cmcptr
  709.     shld    cmdptr
  710.     lxi    h,cmccnt    ;Get the char count.
  711.     dcr    m        ;Decrement it by one.
  712.     mov    a,e        ;Save character count up to now.
  713.     sta    temp1
  714.     cpi    9        ;Past '.'?
  715.     jm    cmfrec        ;No.
  716.     dcr    a        ;Yes, don't count point.
  717. cmfrec:    lhld    cmfcb2        ;Fill the rest with CP/M wildcards.
  718. cmfrc1:    cpi    11        ;Done?
  719.     jp    cmfrc2        ;Yes.
  720.     mvi    m,'?'
  721.     inx    h
  722.     inr    a
  723.     jmp    cmfrc1
  724.  
  725. cmfrc2:    mvi    c,sfirst    ;Find first matching file?
  726.     lhld    cmfcb
  727.     xchg
  728.     call    bdos
  729.     cpi    0FFH
  730.     jz    cmfrc9        ;No, lose.
  731.     lxi    h,fcbblk    ;Copy first file spec.
  732.     call    fspcop
  733.     lxi    h,fcbblk+10H    ;Get another copy (in case not ambiguous).
  734.     call    fspcop
  735.     mvi    c,snext        ;More matching specs?
  736.     lhld    cmfcb
  737.     xchg
  738.     call    bdos
  739.     cpi    0FFH
  740.     jz    cmfrc3        ;Only one.
  741.     lxi    h,fcbblk+10H    ;Copy second file spec.
  742.     call    fspcop
  743. cmfrc3:    lxi    d,fcbblk    ;Start comparing file names.
  744.     lxi    h,fcbblk+10H
  745.     lda    temp1        ;Bypass characters typed.
  746.     cpi    9        ;Past '.'?
  747.     jm    cmfrc4        ;No.
  748.     dcr    a        ;Yes, don't count point.
  749. cmfrc4:    mvi    c,0
  750. cmfrl1:    cmp    c        ;Bypassed?
  751.     jz    cmfrl2        ;Yes.
  752.     inx    d
  753.     inx    h
  754.     inr    c
  755.     jmp    cmfrl1        ;Repeat.
  756.  
  757. cmfrl2:    mov    a,c        ;Get file name characters processed.
  758.     cpi    11        ;All done?
  759.     jz    cmfrc5        ;Yes.
  760.     cpi    8        ;End of file name?
  761.     jnz    cmfrl3        ;No.
  762.     lda    temp1        ;Exactly at point?
  763.     cpi    9
  764.     jz    cmfrl3        ;Yes, don't output a second point.
  765.     mvi    a,'.'           ;Output separator.
  766.     call    cmfput
  767. cmfrl3:    ldax    d        ;Get a character from first file spec.
  768.     inx    d
  769.     mov    b,m        ;Get from second file spec.
  770.     inx    h
  771.     cmp    b        ;Compare.
  772.     jnz    cmfrc5        ;Ambiguous.
  773.     inr    c        ;Same, count.
  774.     cpi    ' '             ;Blank?
  775.     jz    cmfrl2        ;Yes, don't output.
  776.     call    cmfput        ;Put character into buffer.
  777.     jmp    cmfrl2        ;Repeat.
  778.  
  779. cmfrc5:    mov    a,c        ;Get count of characters processed.
  780.     sta    temp1        ;Save it.
  781.     mvi    a,'$'           ;Get terminator.
  782.     call    cmfput        ;Put it into buffer.
  783.     lhld    cmdptr        ;Output recognized characters.
  784.     xchg
  785.     mvi    c,prstr
  786.     call    bdos
  787.     lhld    cmcptr        ;Remove terminator from buffer.
  788.     dcx    h
  789.     shld    cmcptr
  790.     lxi    h,cmccnt
  791.     dcr    m
  792.     lda    temp1        ;Characters processed.
  793.     cpi    11        ;Complete file name.
  794.     jz    repars        ;Yes, don't beep.
  795.  
  796. cmfrc9:    mvi    c,conout
  797.     mvi    e,bell
  798.     call    bdos        ;Ring the bell.
  799.     jmp    repars
  800. ;
  801. ;       Continue file spec parsing.
  802.  
  803. cmif13:    mov    a,e        ;It must be a terminator.
  804.     ora    a        ;Test the length of the file name.
  805.     jz    cmifi9        ;If zero complain.
  806.     cpi    0DH
  807.     jp    cmifi9        ;If too long complain.
  808.     jmp    rskp        ;Otherwise we have succeeded.
  809.  
  810. cmifi2:    cpi    '.'
  811.     jnz    cmifi3
  812.     inr    e
  813.     mov    a,e
  814.     cpi    1H        ;Any chars yet?
  815.     jz    cmifi9        ;No, give error.
  816.     cpi    0AH        ;Tenth char?
  817.     jp    cmifi9        ;Past it, give an error.
  818.     mvi    c,9H
  819.     mvi    b,0
  820.     lhld    cmfcb
  821.     dad    b        ;Point to file type field.
  822.     shld    cmfcb2
  823.     mvi    e,9H        ;Say we've gotten nine.
  824.     jmp    cmifi1        ;Get the next char.
  825.  
  826. cmifi3:    cpi    ':'
  827.     jnz    cmifi4
  828.     inr    e
  829.     mov    a,e
  830.     cpi    2H        ;Is it in the right place for a drive?
  831.     jnz    cmifi9        ;If not, complain.
  832.     lhld    cmfcb2
  833.     dcx    h        ;Point to previous character.
  834.     mov    a,m        ;Get the drive name.
  835.     sui    '@'             ;Get the drive number.
  836.     shld    cmfcb2        ;Save pointer to beginning of name field.
  837.     mvi    m,space        ;[obs] restore a space in FCB
  838.     dcx    h        ;Point to drive number.
  839.     mov    m,a        ;Put it in the fcb.
  840.     mvi    e,0        ;Start character count over.
  841.     jmp    cmifi1
  842.  
  843. cmifi4:    cpi    '*'
  844.     jnz    cmifi7
  845.     lda    cmfwld        ;Wildcards allowed?
  846.     cpi    0
  847.     jz    cmif11        ;No,complain
  848.     mov    a,e
  849.     cpi    8H        ;Is this in the name or type field?
  850.     jz    cmifi9        ;If its where the dot should be give up.
  851.     jp    cmifi5        ;Type.
  852.     mvi    b,8H        ;Eight chars.
  853.     jmp    cmifi6
  854.  
  855. cmifi5:    mvi    b,0CH        ;Three chars.
  856. cmifi6:    lhld    cmfcb2        ;Get a pointer into the FCB.
  857.     mvi    a,'?'
  858.     mov    m,a        ;Put a question mark in.
  859.     inx    h
  860.     shld    cmfcb2
  861.     inr    e
  862.     mov    a,e
  863.     cmp    b
  864.     jm    cmifi6        ;Go fill in another.
  865.     jmp    cmifi1        ;Get the next char.
  866.  
  867. cmifi7:    cpi    '!'             ;[pcc007] control chr or space?
  868.     jm    cmifi9        ;[pcc007] yes, illegal
  869.     mov    h,a        ;[5] stash input char for a bit
  870.     lda    ffussy        ;[5]  while we check the fussy flag
  871.     ora    a        ;[5] set the flags accordingly
  872.     mov    a,h        ;[5] restore the input character
  873.     jz    cmif7a        ;[5] if ffussy=0, allow <>.,;:?*[]
  874. ;[5] So far, we've eliminated "action characters" (including question),
  875. ;[5] period, colon, asterisk, control characters, and space.
  876. ;[5] That leaves us %(),/;<=>[\]_| to check for.
  877.     cpi    '%'             ;[5]
  878.     jz    cmifi9        ;[5]
  879.     cpi    '('             ;[5]
  880.     jz    cmifi9        ;[5]
  881.     cpi    ')'             ;[5]
  882.     jz    cmifi9        ;[5]
  883.     cpi    ','             ;[pcc007] weed out comma
  884.     jz    cmifi9        ;[pcc007]
  885.     cpi    '/'             ;[5]
  886.     jz    cmifi9        ;[5]
  887.     cpi    '9'+1           ;[pcc007] anything else 21H-39H is ok
  888.     jm    cmifi8        ;[pcc007] except '*' never gets here
  889.     cpi    '@'             ;[pcc007] all of 3AH-3FH is illegal
  890.     jm    cmifi9        ;[pcc007]
  891.     cpi    '['             ;[pcc007] [\] also illegal
  892.     jm    cmifi8        ;[pcc007]
  893.     cpi    ']'+1           ;[pcc007]
  894.     jm    cmifi9        ;[pcc007]
  895.     cpi    '_'             ;[5]
  896.     jz    cmifi9        ;[5] (If I was doing CP/M, I would have
  897.     cpi    '|'             ;[5]  just eliminated all them funny chars
  898.     jz    cmifi9        ;[5]  instead of a random selection)
  899. cmif7a:                ;[5]
  900.     cpi    'a'             ;[pcc007] if not lower case its ok
  901.     jm    cmifi8        ;[pcc007] (DEL never gets here)
  902.     cpi    'z'+1           ;[pcc007] only convert letters
  903.     jp    cmifi8        ;[pcc007]
  904.     ani    137O        ;Capitalize.
  905. cmifi8:    lhld    cmfcb2        ;Get the pointer into the FCB.
  906.     mov    m,a        ;Put the char there.
  907.     inx    h
  908.     shld    cmfcb2
  909.     inr    e
  910.     jmp    cmifi1
  911.  
  912. cmifi9:    lda    cmstat
  913.     cpi    cmifin        ;"silent"?
  914.     jz    r        ;Yes,let him go w/o check
  915.     lxi    d,cmer02
  916. cmif10:    mvi    c,prstr
  917.     call    bdos
  918.     ret
  919.  
  920. cmif11:    lxi    d,cmer03    ;Complain about wildcards.
  921.     jmp    cmif10
  922.  
  923. ;
  924.  
  925. ;       copy filename from buffer
  926. ;       called with HL = destination, A = position (0-3) in buffer
  927. ;       called by: cmifil
  928.  
  929. fspcop:    push    psw        ;Save A.
  930.     lxi    d,buff        ;Get the right offset in the buffer.
  931.     rlc
  932.     rlc
  933.     rlc
  934.     rlc
  935.     rlc
  936.     add    e
  937.     inr    a        ;Bypass drive spec.
  938.     mov    e,a
  939.     mvi    b,11        ;Copy file name.
  940. fspcp1:    ldax    d
  941.     inx    d
  942.     mov    m,a
  943.     inx    h
  944.     dcr    b
  945.     jnz    fspcp1
  946.     pop    psw        ;Restore A.
  947.     ret
  948.  
  949. ;       append character in A to command buffer
  950. ;       called by: cmifil
  951.  
  952. cmfput:    push    h        ;Save H.
  953.     lhld    cmcptr        ;Get buffer pointer.
  954.     mov    m,a        ;Store in buffer.
  955.     inx    h
  956.     shld    cmcptr
  957.     lxi    h,cmccnt    ;Count it.
  958.     inr    m
  959.     pop    h        ;Restore H.
  960.     ret
  961. ;
  962. ;       Read characters from the command buffer.
  963. ;       called by:  cmtext, cmcfrm, cmkeyw, cmifil
  964.  
  965. cmgtch:    push    h
  966.     push    b
  967. cmgtc1:    lda    cmaflg
  968.     ora    a        ;Is it set.
  969.     cz    cminbf        ;If the action char flag is not set get more.
  970.     lhld    cmdptr        ;Get a pointer into the buffer.
  971.     mov    a,m        ;Get the next char.
  972.     inx    h
  973.     shld    cmdptr
  974.     cpi    ' '             ;Is it a space?
  975.     jz    cmgtc2
  976.     cpi    tab        ;Or a tab?
  977.     jnz    cmgtc3
  978. cmgtc2:    lda    cmsflg        ;Get the space flag.
  979.     ora    a        ;Was the last char a space?
  980.     jnz    cmgtc1        ;Yes, get another char.
  981.     mvi    a,0FFH        ;Set the space flag.
  982.     sta    cmsflg
  983.     mvi    a,' '
  984.     pop    b
  985.     pop    h
  986.     jmp    cmgtc5
  987.  
  988. cmgtc3:    push    psw
  989.     xra    a
  990.     sta    cmsflg        ;Zero the space flag.
  991.     pop    psw
  992.     pop    b
  993.     pop    h
  994.     cpi    esc
  995.     jz    cmgtc5
  996.     cpi    '?'             ;Is the user curious?
  997.     jz    cmgtc4
  998.     cpi    cr
  999.     jz    cmgtc4
  1000.     cpi    lf
  1001.     jz    cmgtc4
  1002.     cpi    ff
  1003.     rnz            ;Not an action char, just return.
  1004. cmgtc4:    push    h
  1005.     lhld    cmdptr
  1006.     dcx    h
  1007.     shld    cmdptr
  1008.     pop    h
  1009. cmgtc5:    ori    80H        ;Make the char negative to indicate it is
  1010.     ret            ;a terminator.
  1011. ;
  1012. ;       Read characters from console into command buffer, processing
  1013. ;       editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del).
  1014. ;       called by: comnd, cmgtch
  1015.  
  1016. cminbf:    push    psw
  1017.     push    d
  1018.     push    h
  1019.     lda    cmaflg        ;Is the action char flag set?
  1020.     ora    a
  1021.     jnz    cminb9        ;If so get no more chars.
  1022. cminb1:    lxi    h,cmccnt    ;Increment the char count.
  1023.     inr    m
  1024.     mvi    c,conin        ;Get a char.
  1025.     lda    cmqflg        ;[MF]but do we want it echoed?
  1026.     ora    a        ;[MF]...
  1027.     jz    cmin1b        ;[MF]Yup, proceed normally
  1028. cmin1c:    mvi    e,0ffH        ;[MF]Nope, do it with Direct
  1029.     mvi    c,dconio    ;[MF]Console I/O
  1030.     call    bdos        ;[MF]...
  1031.     ora    a        ;[MF]Did the user type anything?
  1032.     jz    cmin1c        ;[MF]No, don't go on until he/she does.
  1033.     jmp    cmin1a        ;[MF]We got a character
  1034. cmin1b:    call    bdos
  1035. cmin1a:    lhld    cmcptr        ;Get the pointer into the buffer.
  1036.     mov    m,a        ;Put it in the buffer.
  1037.     inx    h
  1038.     shld    cmcptr
  1039.     cpi    25O        ;Is it a ^U?
  1040.     jz    cmnb12        ;Yes.
  1041.     cpi    30O        ;Is it a ^X?
  1042.     jnz    cminb2
  1043. cmnb12:    call    clrlin        ;Clear the line.
  1044.     call    prprmp        ;Print the prompt  [Toad Hall]
  1045.     lxi    h,cmdbuf
  1046.     shld    cmcptr        ;Reset the point to the start.
  1047.     lxi    h,cmccnt    ;Zero the count.
  1048.     mvi    m,0
  1049.     jmp    repars        ;Go start over.
  1050.  
  1051. cminb2:    cpi    10O        ;Backspace?
  1052.     jz    cminb3
  1053.     cpi    del        ;or Delete?
  1054.     jnz    cminb4
  1055.     lda    cmqflg        ;[MF]If we are echoing characters,
  1056.     ora    a        ;[MF]...
  1057.     cz    delchr        ;Print the delete string. [MF]
  1058. cminb3:    lda    cmccnt        ;Decrement the char count by two.
  1059.     dcr    a
  1060.     dcr    a
  1061.     ora    a        ;Have we gone too far?
  1062.     jp    cmnb32        ;If not proceed.
  1063.     mvi    c,conout    ;Ring the bell.
  1064.     mvi    e,bell
  1065.     call    bdos
  1066.     jmp    cmnb12        ;Go reprint prompt and reparse.
  1067.  
  1068. cmnb32:    sta    cmccnt        ;Save the new char count.
  1069.     lda    cmqflg        ;[MF]Echoing characters?
  1070.     ora    a        ;[MF]If we are, then
  1071.     cz    clrspc        ;Erase the character. [MF]
  1072.     lhld    cmcptr        ;Get the pointer into the buffer.
  1073.     dcx    h        ;Back up in the buffer.
  1074.     dcx    h
  1075.     shld    cmcptr
  1076.     jmp    repars        ;Go reparse everything.
  1077.  
  1078. cminb4:    cpi    '?'             ;Is it a question mark.
  1079.     jz    cminb6
  1080.     cpi    esc        ;Is it an escape?
  1081.     jz    cminb6
  1082.     cpi    cr        ;Is it a carriage return?
  1083.     jz    cminb5
  1084.     cpi    lf        ;Is it a line feed?
  1085.     jz    cminb5
  1086.     cpi    ff        ;Is it a formfeed?
  1087.     jnz    cminb8        ;no - just store it and 
  1088.                 ;test if buffer overflowing, else get another character.
  1089.     call    clrtop
  1090. cminb5:    lda    cmbflg        ;[MF]Allowing initial blank word (<cr>)?
  1091.     ora    a        ;[MF]...
  1092.     jnz    cminb6        ;[MF]Yes
  1093.     lda    cmccnt        ;Have we parsed any chars yet?
  1094.     cpi    1
  1095.     jz    prserr        ;If not, just start over.
  1096. cminb6:    mvi    a,0FFH        ;Set the action flag.
  1097.     sta    cmaflg
  1098.     jmp    cminb9
  1099.  
  1100. cminb8:
  1101.     lda    cmccnt        ; get the command character count
  1102.     cpi    cmbufl        ; check for comand buffer length
  1103.     jm    cminb1        ; if less, then all ok
  1104.     mvi    e,bell        ; else beep at user
  1105.     call    outcon        ; send it to the console
  1106.     lda    cmccnt        ; back up one character
  1107.     dcr    a
  1108.     sta    cmccnt
  1109.     lhld    cmcptr        ; ditto pointer
  1110.     dcx    h
  1111.     shld    cmcptr        ; save it again
  1112.     jmp    cminb1        ; and try again
  1113.  
  1114. cminb9:    pop    h
  1115.     pop    d
  1116.     pop    psw
  1117.     ret
  1118. ;
  1119. ;Little utility to print the prompt.  (We do a LOT of these.)  [Toad Hall]
  1120. ;Enters with nothing.
  1121. ;Destroys HL (and I suppose B and DE and A).
  1122.  
  1123. prprmp:    mvi    e,cr        ; do a cr first
  1124.     mvi    c,dconio
  1125.     call    bdos
  1126.     lhld    cmprmp        ;Get the prompt.
  1127.     xchg
  1128.     call    prtstr
  1129.     ret
  1130.  
  1131. ; Little code to allow some expansion of code without changing
  1132. ;  every futher address, only up to the end of this file.
  1133. ;   TO BE REMOVED FOR RELEASE!
  1134.  
  1135. ;    org ($+100h) AND 0FF00H
  1136.  
  1137.  
  1138. IF    lasm
  1139. LINK    CPSUTL
  1140. ENDIF    ;lasm  [Toad Hall]
  1141.