home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccpm86 / cn8cmd.a86 next >
Text File  |  2020-01-01  |  24KB  |  863 lines

  1. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  2. ; [32c] remove check for 0-length filename
  3. ; [32b] fix minor bugs
  4. ; [32a]    fix prompt to show default drive and user
  5. ;    RonB, 09/13/84
  6. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  7. ; [fdc]    Fix small glitch w/CMLEVL that issued msg spuriously sometimes.
  8. ; []    Introduced CMLEVL flag to intercept "empty" command-options
  9. ;    Reset by PRSERR, SET in 86KERMIT KERMIT:
  10. ;        B.E.; EIBEN at DEC-MARLBORO 2-May-84
  11. ; [30c] Isolate ANSI escape sequences for machine independence.
  12. ; [30b] Make DEL work like BS and ^X like ^U in command input.
  13. ;    RonB, 04/18/84
  14. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  15. ; [28d] Improve filename special character processing
  16. ;    RonB, 03/27/84
  17. ; [25]    Move logic for "seteol" and "escape" (from KERSYS) into here so those 
  18. ;    routines need not use internal CMD routines and variables.  For this 
  19. ;    purpose add 2 parse routines and codes: "cmcha" and "cmnum".  The point
  20. ;    of this is to keep calls to CMD modular since I want to eventually
  21. ;    replace the whole thing.
  22. ;    R. Garland    9-Mar-1984
  23. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  24. ;  [9]    Fix filename parsing, and add wildcard ability.
  25. ;    RonB,12/26/83
  26. ;  [8]    Show choices for ambiguous keywords, finish keyword on '?'
  27. ;    RonB,12/26/83
  28. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  29. ; This module contains all the routines and storage necessary for the
  30. ; command parser.  The command parser approximates that of the Tops-20
  31. ; COMND% JSYS.  This code is adapted from the IBM PC Kermit code which
  32. ; was adapted from the CP/M-80 Kermit code.
  33. ; COMND definitions.
  34.  
  35. cmcfm    equ    01H
  36. cmkey    equ    02H
  37. cmifi    equ    03H
  38. cmofi    equ    04H
  39. cmtxt    equ    05H
  40. cmcha    equ    06H
  41. cmnum    equ    07H
  42.  
  43.     DSEG $            ; Resume the data segment.
  44.  
  45. ; COMND storage.
  46.  
  47. cmer00    db    bell,'?Program error -- Invalid COMND call$'
  48. cmer01    db    bell,'?Ambiguous command$'
  49. cmer02    db    bell,'?Illegal input file spec$'
  50. cmer03    db    bell,'?Unrecognized instruction$'
  51. cmer04    db    bell,'?Invalid command or operand$'
  52. cmer05    db    bell,'?Missing command-option$'
  53. cmin00    db    ' Confirm with carriage return$'
  54. cmin01  db      ' Input file spec (possibly wild) $'
  55. cmin02    db    ' One of the following:$'            ;[8]
  56.  
  57. cmlevl    db    0        ;0 at main-level, 1 otherwise
  58. cmstat    db    0        ;What is presently being parsed.
  59. cmaflg    db    0        ;Non-zero when an action char has been found.
  60. cmccnt    db    0        ;Non-zero if a significant char is found.
  61. cmsflg    db    0        ;Non-zero when the last char was a space.
  62. cmostp    dw    0        ;Old stack pointer for reparse.
  63. cmrprs    dw    0        ;Address to go to on reparse.
  64. cmprmp    dw    0        ;Address of prompt.
  65. cmptab    dw    0        ;Address of present keyword table.
  66. cmhlp    dw    0        ;Address of present help.
  67. cmdbuf    rb    80H        ;Buffer for command parsing.
  68. cmfcb    dw    0        ;Pointer to FCB.
  69. cmfcb2    dw    0        ;Pointer to position in FCB.
  70. cmcptr    dw    0        ;Pointer for next char input.
  71. cmdptr    dw    0        ;Pointer into the command buffer.
  72. cmsiz    dw    0        ;Size info of user input.
  73. cmkptr    dw    0        ;Pointer to keyword.
  74. cmsptr    dw    0        ;Place to save a pointer.
  75. cmchr    db    0        ;Save char when checking ambiguity.
  76. cmten    dw    10        ;the number "10"
  77.  
  78. spchar    db    '!#$%&()+-/@\^`|~0000' ;Valid special characters ;[8][28d]
  79.  
  80. ;    This set of routines provides a user oriented way of parsing
  81. ;    commands.  It is similar to that of the COMND JSYS in TOPS-20.
  82.  
  83.     CSEG $            ;Resume coding.
  84.  
  85. ;    This routine prints the prompt in DX and specifies the reparse
  86. ;    address.
  87.  
  88. prompt:    pop    bx        ;Get the return address.
  89.     push    bx        ;Put it on the stack again.
  90.     mov    cmrprs, bx    ;Save as addr to go to on reparse.
  91.     mov    bx, 0        ;Clear out register.
  92.     add    bx, sp        ;Get the present stack pointer.
  93.     mov    cmostp, bx    ;Save for later restoral.
  94.     mov    cmprmp, dx    ;Save pointer to the prompt.
  95.     mov    bx, offset cmdbuf
  96.     mov    cmcptr, bx    ;Initialize the command pointer.
  97.     mov    cmdptr, bx
  98.     mov    cmaflg, 0    ;Zero the flags.
  99.     mov    cmlevl, 0    ;[fdc]Including the level-flag
  100.     mov    cmccnt, 0
  101.     mov    cmsflg, 0FFH
  102. reprompt:                            ;[32a] begin
  103.     call    tcrlf
  104. repmt2:    mov    dx, cmprmp    ;Print the prompt.
  105.     call    tmsg
  106.     mov    dl,defdrv    ;Print the default drive and user
  107.     add    dl,'A'
  108.     call    bout
  109.     mov    al,defusr
  110.     cbw
  111.     or    ax,ax        ;Only print the user number if nonzero
  112.     jz    repmt3
  113.     call    nout
  114. repmt3:    mov    dl,'>'
  115.     call    bout                        ;[32a] end
  116.     ret
  117.  
  118.  
  119. ;    This address is jumped to on reparse.
  120.  
  121. repars:    mov    sp, cmostp    ;new sp <-- old sp
  122.     mov    bx, offset cmdbuf
  123.     mov    cmdptr, bx
  124.     mov    cmsflg, 0FFH
  125.     mov    bx, cmrprs    ;Get the reparse address.
  126.     jmp    bx        ;Go there.
  127.  
  128. ;    This address can be jumped to on a parsing error.
  129.  
  130. prserr:    mov    ah, cmlevl    ;What level are we in?
  131.     cmp    ah, 0        ;
  132.     jz    prser1        ;skip error-message
  133.     mov    dx, offset cmer05 ;we're out of main-commands
  134.     call    tcrmsg        ;and got an empty option
  135.     mov    cmlevl, 0    ;reset level-flag
  136. prser1:    mov    sp, cmostp    ;Set new sp to old one.
  137.     mov    bx, offset cmdbuf
  138.     mov    cmcptr, bx    ;Initialize the command pointer.
  139.     mov    cmdptr, bx
  140.     mov    cmaflg, 0    ;Zero the flags.
  141.     mov    cmccnt, 0
  142.     mov    cmsflg, 0FFH
  143.     call    reprompt                    ;[32a]
  144.     mov    bx, cmrprs
  145.     jmp    bx
  146.  
  147.  
  148. ;    This routine parses the specified function in AH. Any additional
  149. ;    information is in DX and BX.
  150. ;    Returns +1 on success
  151. ;        +4 on failure (assumes a JMP follows the call)
  152.  
  153. comnd:    mov    cmstat, ah    ;Save what we are presently parsing.
  154.     call    cminbf        ;Get chars until an action or a erase char.
  155.     mov    ah, cmstat    ;Restore 'ah' for upcoming checks.
  156.     cmp    ah, cmcfm    ;Parse a confirm?
  157.     jz    cmcfrm        ;Go get one.
  158.     cmp    ah, cmkey    ;Parse a keyword?
  159.     jnz    cm1
  160.     jmp    cmkeyw        ;Try and get one.
  161. cm1:    cmp    ah, cmifi    ;Parse an input file spec?
  162.     jnz    cm2
  163.     jmp    cmifil        ;Go get one.
  164. cm2:    cmp    ah, cmofi    ;Output file spec?
  165.     jnz    cm3
  166.     jmp    cmofil        ;Go get one.
  167. cm3:    cmp    ah, cmtxt    ;Parse arbitrary text.
  168.     jnz    cm4
  169.     jmp    cmtext
  170. cm4:    cmp    ah, cmcha    ;[25] parse a single character?
  171.     jnz    cm5        ;[25]
  172.     jmp    cmchar        ;[25] go do it.
  173. cm5:    cmp    ah, cmnum    ;[25] parse a (decimal) number?
  174.     jnz    cm99        ;[25]
  175.     jmp    cmnumr        ;[25] go do it.
  176. cm99:    mov    dx, offset cmer00 ;"?Unrecognized COMND call" [25]
  177.     call    tcrmsg
  178.     ret
  179.  
  180. ; This routine gets a confirm.
  181.  
  182. cmcfrm:    call    cmgtch        ;Get a char.
  183.     cmp    ah, 0        ;Is it negative (a terminator;a space or
  184.                 ;a tab will not be returned here as they
  185.                 ;will be seen as leading white space)?
  186.     js    cmcfr0
  187.     ret            ;If not, return failure.
  188. cmcfr0:    and    ah, 7FH        ;Turn off the minus bit.
  189.     cmp    ah, esc        ;Is it an escape?
  190.     jne    cmcfr2
  191.     mov    dl, bell    ;Get a bell.
  192.     call    bout        ;Output the char.
  193.     mov    cmaflg, 0    ;Turn off the action flag.
  194.     mov    bx, cmcptr    ;Move the pointer to before the escape.
  195.     dec    bx
  196.     mov    cmcptr, bx
  197.     mov    cmdptr, bx
  198.     dec    cmccnt        ;Decrement the char count.
  199.     jmp    cmcfrm        ;Try again.
  200. cmcfr2:    cmp    ah, '?'        ;Curious?
  201.     jne    cmcfr3
  202.     mov    dx, offset cmin00 ;Print something useful.
  203.     call    tmsg
  204.     call    reprompt    ;Reprint the prompt        ;[32a]
  205.     mov    bx, cmdptr    ;Get the pointer into the    buffer.
  206.     mov    ah, '$'        ;Put a $ there for printing.
  207.     mov    [bx], ah
  208.     mov    bx, cmcptr
  209.     dec    bx        ;Decrement & save the buffer pointer.
  210.     mov    cmcptr, bx
  211.     mov    dx, offset cmdbuf
  212.     call    tmsg
  213.     mov    cmaflg, 0    ;Turn off the action flag.
  214.     jmp    repars        ;Reparse everything.
  215.  
  216. cmcfr3:                                ;[8] begin
  217. cmcfr4:    jmp    rskp
  218.  
  219.  
  220. ;    This routine parses a keyword from the table pointed
  221. ;    to in DX.  The format of the table is as follows:
  222. ;
  223. ;    addr:    db    n    ;Where n is the # of entries in the table.
  224. ;        db    m    ;M is the size of the keyword.
  225. ;        db    'string$' ;Where string is the keyword.
  226. ;        dw    ab    ;Where ab is data to be returned.
  227. ;
  228. ;    The keywords must be in alphabetical order.
  229.  
  230. cmkeyw:    mov    cmhlp, bx    ;Save the help string.
  231.     mov    cmptab, dx    ;Save the beginning of keyword table.
  232.     mov    bx, dx
  233.     mov    ch, [bx]    ;Get number of entries in table.
  234.     inc    bx
  235.     mov    dx, cmdptr    ;Save command pointer.
  236.     mov    cmsptr, dx    ;Save pointer's here.
  237. cmky1:    cmp    ch, 0        ;Any commands left to check?
  238.     jne    cmky2
  239.     ret
  240. cmky2:    dec    ch
  241.     mov    cl, 0        ;Keep track of how many chars read in so far.
  242.     call    cmgtch        ;Get a char.
  243.     cmp    ah, 0        ;Do we have a terminator?
  244.     jns    cmky2x 
  245.     jmp    cmky4        ;Negative number means we do.
  246. cmky2x:    inc    bx        ;Point to first letter of keyword.
  247.     inc    cl        ;Read in another char.
  248.     mov    al, [bx]              
  249.     cmp    ah, 'a'        ;Less than a?
  250.     jl    cmky21        ;If so, don't capitalize.
  251.     cmp    ah, 'z'+1    ;More than z?
  252.     jns    cmky21
  253.     and    ah, 137O    ;Capitalize the letter.
  254. cmky21:    cmp    ah, al
  255.     je    cmky3
  256.     jg    cmky2y
  257.     jmp    cmky41        ;Fail if ah preceeds al alphabetically.
  258. cmky2y:    jmp    cmky6        ;Not this keyword - try the next.
  259. cmky3:    inc    bx        ;We match here, how 'bout next char?
  260.     mov    al, [bx]
  261.     cmp    al, '$'        ;End of keyword?
  262.     jne    cmky3x
  263.     jmp    cmky7        ;Succeed.
  264. cmky3x:    mov    dl, al        ;Save al's char here.
  265.     call    cmgtch
  266.     inc    cl        ;Read in another char.
  267.     mov    al, dl
  268.     cmp    ah, 'a'
  269.     jl    cmky31
  270.     cmp    ah, 'z'+1
  271.     jns    cmky31
  272.     and    ah, 137O
  273. cmky31:    cmp    ah, esc+80H    ;Escape Recognition (escape w/minus bit on)?
  274.     je    cmky3y
  275.     cmp    ah, '?'+80H    ;A question mark?
  276.     je    cmky3y
  277.     cmp    ah, ' '+80H    ;A space?
  278.     je    cmky3y
  279.     cmp    ah, cr+80H    ;Carriage return?
  280.     je    cmky3y
  281.     jmp    cmky38
  282. cmky3y:    mov    cmkptr, bx    ;Save bx here.
  283.     mov    cmsiz, cx    ;Save size info.
  284.     mov    cmchr, ah    ;Save char for latter.
  285.     call    cmambg        ;See if input is ambiguous or not.
  286.         jmp    cmky32    ;Succeeded (not ambiguous).
  287.     mov    ah, cmchr
  288.     cmp    ah, esc+80H    ;Escape?
  289.  
  290. ; Display keyword choices and reparse if ambiguous        ;[8] begin
  291.     je    cmky3a
  292.     cmp    ah, ' '+80H    ;Space?
  293.     jne    cmky3b
  294. cmky3a:    dec    cmdptr        ;If so, back up over it.
  295. cmky3b:    mov    dx, offset cmin02 ;'One of the following:'
  296.     call    tcmsgc
  297.     mov    bx, cmkptr    ;Find beginning of current keyword
  298.     mov    cx, cmsiz
  299. cmky3c:    dec    bx        ;We are 'cl' characters into it
  300.     dec    cl
  301.     jnz    cmky3c
  302.     inc    bx
  303.     mov    cmkptr, bx    ;Save beginning of keyword
  304. cmky3d:    mov    dl, tab        ;Precede each keyword with a tab
  305.     call    bout
  306.     mov    dx,cmkptr    ;and display the keyword
  307.     call    tmsg
  308.     mov    bx, cmkptr    ;Move to the next keyword
  309. cmky3e:    inc    bx
  310.     cmp    byte ptr [bx], '$'
  311.     jnz    cmky3e
  312.     add    bx,4        ;Bypass '$', 2-byte return value, next length
  313.     mov    di, cmkptr    ;Get previous keyword for comparison
  314.     mov    cmkptr, bx    ;and save beginning of this keyword
  315.     mov    cx, cmsiz    ;Get number of characters to match
  316.     dec    ch        ;Are we at end of table?
  317.     js    cmky3g        ;  Yes, quit displaying
  318.     mov    cmsiz, cx
  319. cmky3f:    dec    cl
  320.     jz    cmky3d        ;This keyword also matches to 'cl' places
  321.     mov    ah,[bx]        ;Compare this keyword to last
  322.     cmp    ah,[di]
  323.     jne    cmky3g
  324.     inc    di
  325.     inc    bx
  326.     jmps    cmky3f
  327. cmky3g:    jmp    cmky50        ;Not equal or end of table, redisplay prompt
  328.                                 ;[8] end
  329.  
  330. cmky32:    mov    cx, cmsiz    ;Restore info.
  331.     mov    bx, cmkptr    ;Our place in the keyword table.
  332. cmk32a:    cmp    cmchr, ' '+80H    ;Space?            ;[8]
  333.     je    cmky35
  334.     cmp    cmchr, cr+80H    ;Carriage return?
  335.     je    cmky35
  336.     dec    cmcptr        ;Pointer into buffer of input.
  337.     mov    dx, cmcptr
  338. cmky33:    mov    ah, [bx]    ;Get next char in keyword.
  339.     cmp    ah, '$'        ;Are we done yet?
  340.     jz    cmky34
  341.     mov    di,dx
  342.     mov    [di], ah
  343.     inc    bx
  344.     inc    dx
  345.     inc    cmccnt
  346.     jmp    cmky33
  347. cmky34:    push    bx        ;Save pointer to return value    ;[8]
  348.     mov    ah, ' '
  349.     mov    di, dx
  350.     mov    [di], ah    ;Put a blank in the buffer.
  351.     inc    dx
  352.     mov    cmdptr, dx                        ;[8] begin
  353.     cmp    cmchr, '?'+80H    ;Question mark?
  354.     jne    cmk34a
  355.     mov    ah, '?'
  356.     mov    di,dx
  357.     mov    [di], ah
  358.     inc    dx
  359.     inc    cmccnt
  360.     push    dx
  361.     mov    dl, 08H        ;Erase question mark from display
  362.     call    bout
  363.     pop    dx
  364. cmk34a:    mov    cx, cmcptr    ;Remember where we were (for printing below).
  365.     mov    cmcptr, dx    ;Update our pointers.        ;[8] end
  366.     mov    ah, '$'
  367.     mov    di, dx
  368.     mov    [di], ah    ;Add '$' for printing.
  369.     mov    dx, cx        ;Point to beginning of filled in data.
  370.     call    tmsg
  371.     pop    bx        ;Recover pointer to return value ;[8]
  372.     inc    bx        ;Point to address we'll need.
  373.     mov    bx, [bx]
  374.     cmp    cmchr, 0BFH    ;Question mark?        ;[8] begin
  375.     je    cmk34b
  376.     mov    cmaflg, 0     ;If esc, turn off action flag
  377.     mov    cmsflg, 0FFH    ;   and pretend they typed a space
  378. cmk34b:    jmp    rskp                        ;[8] end
  379.  
  380. cmky35:    mov    ah, [bx]    ;Find end of keyword.    
  381.     inc    bx
  382.     cmp    ah, '$'
  383.     jne    cmky35    
  384.     mov    bx, [bx]    ;Address of next routine to call.
  385.     jmp    rskp
  386.  
  387. cmky38:    cmp    ah, al
  388.     jne    cmky6        ;Go to end of keyword and try next.
  389.     jmp    cmky3
  390.        
  391. cmky4:    and    ah, 7FH        ;Turn off minus bit.
  392.     cmp    ah, '?'        ;Need help?
  393.     je    cmky5
  394.     cmp    ah, ' '        ;Just a space - no error.
  395.     je    cmky51
  396.     cmp    ah, cr
  397.     je    cmky51
  398.     cmp    ah, esc        ;Ignore escape?
  399.     je    cmky43
  400. cmky41:    mov    dx, offset cmer03
  401.     call    tcrmsg
  402.     jmp    prserr        ;Parse error - give up.
  403.  
  404. cmky43:    mov    dl, bell    ;Ring a bell.
  405.     call    bout
  406.     mov    bx, cmcptr
  407.     dec    bx
  408.     mov    cmcptr, bx
  409.     mov    cmdptr, bx
  410.     dec    cmccnt        ;Don't count the escape.
  411.     mov    cmaflg, 0    ;Reset action flag.
  412.     inc    ch        ;Account for a previous 'dec'.
  413.     jmp    cmky1        ;Start over.
  414.  
  415. cmky5:    mov    dx,cmhlp    ;Print the help text.
  416.     call    tcmsgc
  417. cmky50:    call    reprompt    ;Reprint the prompt        ;[32a]
  418.     mov    bx,cmdptr    ;Get pointer into buffer.
  419.     mov    al, '$'
  420.     mov    [bx], al    ;Add dollar sign for printing.
  421.     mov    dx, offset cmdbuf
  422.     call    tmsg
  423.     mov    bx, cmdptr    ;[8] begin
  424.     mov    cmcptr, bx
  425.     mov    dx, offset cmdbuf
  426.     sub    bx, dx
  427.     mov    cmccnt, bl
  428.     mov    cmaflg, 0    ;Turn off the action flag.
  429.     jmp    repars
  430.  
  431. cmky51:    jmp    prserr
  432.  
  433. cmky6:    inc    bx        ;Find end of keyword.
  434.     mov    al, [bx]
  435.     cmp    al, '$'
  436.     jne    cmky6          
  437.     add    bx, 3        ;Beginning of next command.
  438.     mov    dx, cmsptr    ;Get old cmdptr.
  439.     mov    cmdptr, dx    ;Restore.
  440.     mov    cmsflg, 0FFH
  441.     jmp    cmky1        ;Keep trying.
  442.  
  443. cmky7:    call    cmgtch        ;Get char.
  444.     cmp    ah, 0
  445.     js    cmky71        ;Ok if a terminator.
  446.     dec    bx
  447.     jmp    cmky6        ;No match - try next keyword.
  448. cmky71:    mov    cmchr, ah                        ;[8] begin
  449.     jmp    cmk32a
  450.  
  451.  
  452. ; See if keyword is ambiguous from what the user has typed in.
  453.  
  454. cmambg:    cmp    ch, 0        ;Any keywords left to check?
  455.     jne    cmamb0
  456.     ret            ;If not then not ambiguous.
  457. cmamb0:    inc    bx        ;Go to end of keyword ...
  458.     mov    al, [bx]    ;So we can check the next one.
  459.     cmp    al, '$'
  460.     jne    cmamb0
  461.     add    bx, 4        ;Point to start of next keyword.
  462.     dec    cl        ;Don't count escape.
  463.     mov    dx, cmsptr    ;Buffer with input typed by user.
  464. cmamb1:    mov    ah, [bx]    ;Keyword char.    
  465.     mov    di, dx
  466.     mov    al, [di]    ;Input char.
  467.     cmp    al, 'a'        ;Do capitalizing.
  468.     jl    cmam11
  469.     cmp    al, 'z'+1
  470.     jns    cmam11
  471.     and    al, 137O
  472. cmam11:    cmp    ah, al        ;Keyword bigger than input (alphabetically)?
  473.     jle    cmamb2        ;No - keep checking.
  474.     ret            ;Yes - not ambiguous.
  475. cmamb2:    inc    bx        ;Advance one char.
  476.     inc    dx
  477.     dec    cl
  478.     jnz    cmamb1
  479.     jmp    rskp        ;Fail - it's ambiguous.
  480.  
  481. ; Parse an input file spec.
  482.  
  483. cmifil:    mov    wldflg, 0    ;Set to no wildcards.        ;[9]
  484.     mov    bx, dx        ;Get the fcb address in bx.
  485.     mov    cmfcb, bx    ;Save it.
  486.     mov    ch, 0        ;Initialize char count.
  487.     mov    ah, 0
  488.     mov    [bx], ah    ;Set the drive to default to current.
  489.     inc    bx
  490.     mov    cmfcb2, bx
  491.     mov    cl, ' '
  492. cmifi0:    mov    [bx], cl    ;Blank the FCB.
  493.     inc    bx
  494.     inc    ah
  495.     cmp    ah, 0BH        ;Twelve?
  496.     jl    cmifi0
  497. cmifi1:    call    cmgtch        ;Get another char.
  498.     cmp    ah, 0        ;Is it an action character.
  499.     jns    cmifi2
  500.     and    ah, 7FH        ;Turn off the action bit.
  501.     cmp    ah, '?'        ;A question mark?
  502.     jne    cmif12
  503.     mov    cmaflg, 0    ;Blank the action flag.
  504. ; '?' is a legal character in wildcard filenames.        ;[9] begin
  505. ; Make ESC take its place by giving info instead of beeping.    ;[32b]
  506.     mov    wldflg, 0FFH    ;Say we have a wildcard.
  507.     inc    cmdptr
  508.     jmp    cmifi8        ;Accept a '?'
  509. cmif12:    cmp    ah, esc        ;An escape?
  510.     jne    cmif13
  511.     dec    cmdptr
  512. cmf12a:    mov    cmaflg, 0    ;Turn off the action flag    ;[9] end
  513.     dec    cmcptr        ;Decrement the buffer pointer.
  514.     dec    cmccnt        ;Decrement count.
  515.     mov    dx, offset cmin01 ;Help message.
  516.     call    tmsg
  517.     call    reprompt    ;Reprint the prompt        ;[32a]
  518.     mov    bx, cmdptr
  519.     mov    al, '$'
  520.     mov    [bx], al    ;Put in dollar sign for printing.
  521.     mov    dx, offset cmdbuf
  522.     call    tmsg
  523.     jmp    repars
  524.  
  525. cmif13:    mov    ah, ch        ;It must be a terminator.
  526. ; The check for 0-length filenames will be performed by the    ;[32c]
  527. ; caller so as to allow the file specification to be optional.
  528.     cmp    ah, 0DH
  529.     js    cmf3y
  530.     jmp    cmifi9        ;If too long complain.
  531. cmf3y:    jmp    rskp        ;Otherwise we have succeeded.
  532. cmifi2:    cmp    ah, '.'
  533.     jne    cmifi3
  534.     inc    ch
  535.     mov    ah, ch
  536.     cmp    ah, 1H        ;Any chars yet?
  537.              jnz cmf2x
  538.     jmp    cmifi9        ;No, give error.
  539. cmf2x:    cmp    ah, 0AH        ;Tenth char?
  540.           js    cmf2y
  541.     jmp    cmifi9        ;Past it, give an error.
  542. cmf2y:    mov    dl, 9H
  543.     mov    dh, 0
  544.     mov    bx, cmfcb
  545.     add    bx, dx        ;Point to file type field.
  546.     mov    cmfcb2, bx
  547.     mov    ch, 9H        ;Say we've gotten nine.
  548.     jmp    cmifi1        ;Get the next char.
  549. cmifi3:    cmp    ah, ':'
  550.     jne    cmifi4
  551.     inc    ch
  552.     cmp    ch, 2H        ;Is it in right place for a drive?
  553.     je    cmif3x
  554.     jmp    cmifi9        ;If not, complain.
  555. cmif3x:    mov    ch, 0        ;Reset char count.
  556.     mov    bx, cmfcb2
  557.     dec    bx
  558.     mov    ah, [bx]    ;Get the drive name.
  559.     cmp    ah,'A'        ;Make sure it's in range A-P    ;[9] begin
  560.     jb    cmif3y
  561.     cmp    ah,'P'
  562.     jbe    cmif3z
  563. cmif3y:    jmp    cmifi9
  564. cmif3z:    sub    ah,'@'        ;Get the drive number.        ;[9] end
  565.     mov    cmfcb2, bx
  566.      mov bx, cmfcb
  567.     mov    [bx], ah    ;Put it in the fcb.
  568.     jmp    cmifi1
  569. cmifi4:    cmp    ah, '*'
  570.     jne    cmifi7
  571.     mov    ah, ch
  572.     cmp    ah, 8H        ;Is this in the name or type field?
  573.     jz    cmifi9        ;If its where the dot should be give up.
  574.     jns    cmifi5        ;Type.
  575.     mov    cl, 8H        ;Eight chars.
  576.     jmp    cmifi6
  577. cmifi5:    mov    cl, 0CH        ;Three chars.
  578. cmifi6:    mov    wldflg, 0FFH    ;Remember we had a wildcard.
  579.     mov    bx, cmfcb2    ;Get a pointer into the FCB.
  580.     mov    ah, '?'
  581.     mov    [bx], ah    ;Put a question mark in.
  582.     inc    bx
  583.     mov    cmfcb2, bx
  584.     inc    ch
  585.     mov    ah, ch
  586.     cmp    ah, cl
  587.     jl    cmifi6        ;Go fill in another.
  588.     jmp    cmifi1        ;Get the next char.
  589. cmifi7:
  590.  
  591. cmif7x:    cmp    ah,'0'
  592.     jb    cmif8x
  593.     cmp    ah,'9'
  594.     jbe    cmifi8
  595.     cmp    ah,'A'
  596.     jb    cmif8x
  597.     cmp    ah,'Z'
  598.     jbe    cmifi8
  599.     cmp    ah,'a'
  600.     jb    cmif8x
  601.     cmp    ah,'z'
  602.     ja    cmif8x                        ;[9] end
  603.     and    ah, 137O    ;Capitalize.
  604. cmifi8:    mov    bx, cmfcb2    ;Get the pointer into the FCB.
  605.     mov    [bx], ah    ;Put the char there.
  606.     inc    bx
  607.     mov    cmfcb2, bx
  608.     inc    ch
  609.     jmp    cmifi1
  610.  
  611. cmif8x:    push    es        ;Check list of special characters
  612.     mov    cx, ds        ;   which are legal in filenames
  613.     mov    es, cx        ;Scan uses ES register.
  614.     mov    di, offset spchar ;Special chars.
  615.     mov    cx, 20        ;Twenty of them.
  616.     mov    al, ah        ;Char is in al.
  617.     repnz    scasb        ;Search string for input char.
  618.     cmp    cx, 0        ;Was it there?
  619.     pop    es
  620.     jnz    cmifi8
  621.  
  622. cmifi9:    mov    dx, offset cmer02
  623.     call    tcrmsg
  624.     ret
  625.  
  626. cmofil:    jmp    cmifil        ;For now, the same as CMIFI.
  627.  
  628. ; Parse arbitrary text up to a CR.  Put chars into data buffer sent to
  629. ; the host (pointed to by BX).     Return updated pointer in BX and 
  630. ; input size in AH.
  631.  
  632. cmtext:    mov    cmptab, bx    ;Save pointer to data buffer.
  633.     mov    cl, 0        ;Init the char count.
  634. cmtxt1:    call    cmgtch        ;Get a char.
  635.     cmp    ah, 0        ;Terminator?
  636.     jns    cmtxt5        ;Nope, put into the buffer.
  637.     and    ah, 07FH
  638.     cmp    ah, esc        ;An escape?
  639.     jne    cmtxt2
  640.     mov    dl, bell    ;Ring a bell.
  641.     call    bout
  642.     mov    cmaflg, 0    ;Reset action flag.
  643.     dec    cmcptr        ;Move pointer to before the escape.
  644.     dec    cmdptr
  645.     dec    cmccnt        ;Decrement count.
  646.     jmp    cmtxt1        ;Try again.
  647. cmtxt2:    cmp    ah, '?'        ;Asking a question?
  648.     jz    cmtx2y                        ;[32b]
  649.     cmp    ah, ' '        ;Space?                ;[32b]
  650.     jz    cmtxt3
  651.     cmp    ah, ff        ;Formfeed?
  652.     jne    cmtx2x
  653.     call    clrscr
  654. cmtx2x:    mov    ah, cl        ;Return count in AH.
  655.     mov    bx, cmptab    ;Return updated pointer.
  656.     jmp    rskp
  657. cmtx2y:    inc    cmdptr                        ;[32b]
  658. cmtxt3:    mov    cmaflg, 0    ;Reset action flag to zero.
  659. cmtxt5:    inc    cl        ;Increment the count.
  660.     mov    bx, cmptab    ;Pointer into destination array.
  661.     mov    [bx], ah    ;Put char into the buffer.
  662.     inc    bx
  663.     mov    cmptab, bx
  664.     jmp    cmtxt1
  665.  
  666.  
  667. cminbf:    push    dx
  668.     push    bx
  669.     mov    cx, dx        ;Save value here too.
  670.     mov    ah, cmaflg    ;Is the action char flag set?
  671.     cmp    ah, 0
  672.     je    cminb1
  673.     jmp    cminb9        ;If so get no more chars.
  674. cminb1:    inc    cmccnt        ;Increment the char count.
  675.     call    bin
  676.     mov    ah, al        ;Keep char in 'ah'.
  677.     mov    bx, cmcptr    ;Get the pointer into the buffer.
  678.     mov    [bx], ah    ;Put it in the buffer.
  679.     inc    bx
  680.     mov    cmcptr, bx
  681.     cmp    ah, 15h        ;Is it a ^U?
  682.     je    cmnb12                        ;[30b]
  683.     cmp    ah, 18h        ;     or ^X?            ;[30b]
  684.     jne    cminb2
  685. cmnb12:    call    clrlin                        ;[30c]
  686.     call    repmt2        ;Reprint the prompt (no crlf)    ;[32a]
  687.     mov    bx, offset cmdbuf
  688.     mov    cmcptr, bx    ;Reset the point to the start.
  689.     mov    cmccnt, 0    ;Zero the count.
  690.     mov    dx, cx        ;Preserve original value of    dx.
  691.     jmp    repars        ;Go start over.
  692. cminb2:    cmp    ah, 08h        ;Is it a backspace?        ;[30b]
  693.     jz    cminb3
  694.     cmp    ah, 7fh        ;     or delete?        ;[30b]
  695.     jne    cminb4
  696.     mov    dx, offset delstr
  697.     call    tmsg
  698. cminb3:    mov    ah, cmccnt    ;Decrement the char count by two.
  699.     dec    ah
  700.     dec    ah
  701.     cmp    ah, 0        ;Have we gone too far?
  702.     jns    cmnb32        ;If not proceed.
  703.     mov    dl, bell    ;Ring the bell.
  704.     call    bout
  705.     jmp    cmnb12        ;Go reprint prompt and reparse.
  706. cmnb32:    mov    cmccnt, ah    ;Save the new char count.
  707.     mov    dx, offset clrspc ;Erase the character.
  708.     call    tmsg
  709.     mov    bx, cmcptr    ;Get the pointer into the buffer.
  710.     dec    bx        ;Back up in the buffer.
  711.     dec    bx
  712.     mov    cmcptr, bx
  713.     jmp    repars        ;Go reparse everything.
  714. cminb4:    cmp    ah, '?'        ;Is it a question mark.
  715.     jz    cminb6
  716.     cmp    ah, esc        ;Is it an escape?
  717.     jz    cminb6
  718.     cmp    ah, cr        ;Is it a carriage return?
  719.     jz    cminb5
  720.     cmp    ah, lf        ;Is it a line feed?
  721.     jz    cminb5
  722.     cmp    ah, ff        ;Is it a formfeed?
  723.     jne    cminb7
  724.     call    clrscr
  725. cminb5:    mov    ah, cmccnt    ;Have we parsed any chars yet?
  726.     cmp    ah, 1
  727.     jnz    cminb6
  728.     jmp    prserr        ;If not, just start over.
  729. cminb6:    mov    cmaflg, 0FFH    ;Set the action flag.
  730.     jmp    cminb9
  731. cminb7:    jmp    cminb1        ;Get another char.
  732.  
  733. cminb9:    pop    bx
  734.     pop    dx
  735.     ret
  736.  
  737. cmgtch:    push    cx
  738.     push    bx
  739.     push    dx
  740. cmgtc1:    mov    ah, cmaflg
  741.     cmp    ah, 0        ;Is it set.
  742.     jne    cmgt10
  743.     call    cminbf        ;If the action char flag is not set get more.
  744. cmgt10:    mov    bx, cmdptr    ;Get a pointer into the buffer.
  745.     mov    ah, [bx]    ;Get the next char.
  746.     inc    bx
  747.     mov    cmdptr, bx
  748.     cmp    ah, ' '        ;Is it a space?
  749.     jz    cmgtc2
  750.     cmp    ah, tab        ;Or a tab?
  751.     jne    cmgtc3
  752. cmgtc2:    mov    ah, cmsflg    ;Get the space flag.
  753.     cmp    ah, 0        ;Was the last char a    space?
  754.     jne cmgtc1        ;Yes, get another char.
  755.     mov    cmsflg, 0FFH    ;Set the space flag.
  756.     mov    ah, ' '
  757.     pop    dx
  758.     pop    bx
  759.     jmp    cmgtc5
  760. cmgtc3:    mov    cmsflg, 0    ;Zero the space flag.
  761.     pop    dx
  762.     pop    bx
  763.     cmp    ah, esc
  764.     jz    cmgtc5
  765.     cmp    ah, '?'        ;Is the user curious?
  766.     jz    cmgtc4
  767.     cmp    ah, cr
  768.     jz    cmgtc4
  769.     cmp    ah, lf
  770.     jz    cmgtc6                        ;[8]
  771.     cmp    ah, ff
  772.     je    cmgtc6                        ;[8]
  773.     pop    cx
  774.     ret            ;Not an action char, just return.
  775. cmgtc6:    mov    ah, cr        ;Convert lf & ff to cr        ;[8]
  776. cmgtc4:    dec    cmdptr
  777. cmgtc5:    or    ah, 80H        ;Make the char negative to indicate
  778.     pop    cx        ;it is a terminator.
  779.     ret
  780.  
  781. ; Parse a single character    ;[25] start
  782. ;    this is for setting the escape character
  783.  
  784. cmchar:
  785.     call    cmgtch        ;get a char
  786.     cmp    ah, 0
  787.     jns    cmchr1        ;go if not negative
  788.     and    ah, 7FH        ;turn off sign bit
  789.     cmp    ah, '?'        ;user curious?
  790.     jne    cmchr0        ;no - an error
  791.     mov    dx, bx        ;help string pointer was in bx
  792.     call    tmsg        ;print help stuff        ;[32a]
  793.     call    reprompt    ;Reprint the prompt        ;[32a]
  794.     mov    bx, cmdptr
  795.     mov    al, '$'
  796.     mov    [bx], al    ;add a "$" to what was typed
  797.     mov    dx, offset cmdbuf
  798.     call    tmsg        ;type it again
  799.     dec    cmcptr        ;but don't leave "$" ..
  800.     dec    cmccnt        ;in buffer
  801.     mov    cmaflg, 0    ;turn off action flag
  802.     jmp    repars        ;try again
  803. cmchr0:    mov    dx, offset erms20
  804.     call    tcrmsg        ;"illegal value" error
  805.     ret
  806. cmchr1:    mov    temp, ax    
  807.     call    cmcfrm        ;get a confirm
  808.      jmp    cmchr0        ;or else complain
  809.     mov    ax, temp
  810.     mov    bl, ah        ;return the character
  811.     jmp    rskp
  812.  
  813. ;    parse a (decimal) number.  Maximum allowed value in dx
  814. cmnumr:    
  815.     mov    temp1, 001H    ;initial multiplier of 1
  816.     mov    temp2, dx    ;storage for maximum
  817.     mov    temp, 0        ;zero running sum
  818.     call    cmgtch        ;get a char
  819.     cmp    ah, 0
  820.     jns    cmnum1        ;go if not negative
  821.     and    ah, 7FH        ;turn off sign bit
  822.     cmp    ah, '?'        ;user curious?
  823.     jne    cmnum0        ;no - an error
  824.     mov    dx, bx        ;help string pointer was in bx
  825.     call    tmsg        ;print help stuff        ;[32a]
  826.     call    reprompt    ;Reprint the prompt        ;[32a]
  827.     mov    bx, cmdptr
  828.     mov    al, '$'
  829.     mov    [bx], al    ;add a "$" to what was typed
  830.     mov    dx, offset cmdbuf
  831.     call    tmsg        ;type it again
  832.     dec    cmcptr        ;but don't leave "$" ..
  833.     dec    cmccnt        ;in buffer
  834.     mov    cmaflg, 0    ;turn off action flag
  835.     jmp    repars        ;try again
  836.     call    cmcfrm        ;get character (or confirm)
  837.      jmp    cmnum1        ;got a character
  838.                 ;fall through - too early for confirm
  839. cmnum0:    mov    dx, offset erms20
  840.     call    tcrmsg        ;"illegal value" message
  841.     ret
  842. cmnum1:    sub    ah, 030H    ;ASCII -> binary
  843.     jl    cmnum0        ;too small
  844.     cmp    ah, 09H
  845.     jg    cmnum0        ;too big
  846.     mov    bl, ah
  847.     mov    bh, 0        ;get number in low part of bx
  848.     mov    ax, temp    ;get running sum
  849.     mul    temp1        ;multiply by decimal place value
  850.     add    ax, bx        ;add in this digit
  851.     cmp    ax, temp2    ;over the maximum
  852.     jg    cmnum0        ;yes - error
  853.     mov    temp, ax    ;save running sum
  854.     mov    ax, temp1    ;get multiplier
  855.     mul    cmten        ;multiply multiplier by 10
  856.     mov    temp1, ax    ;save it
  857.     call    cmcfrm        ;get another character
  858.      jmp    cmnum1        ;not terminator - process it
  859.     mov    bx, temp    ;get value of number
  860.     jmp    rskp        ;return success
  861.                         ;[25] end
  862.  
  863.