home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / MSKERMIT.ZIP / MSCMD.ASM next >
Encoding:
Assembly Source File  |  1986-05-17  |  30.1 KB  |  1,107 lines

  1.     public comnd, cmcfrm, prserr, repars, cmgtch, drives, comand, fcbcpy
  2.     include msdefs.h
  3.  
  4. datas    segment public 'datas'
  5.     extrn    flags:byte, trans:byte, fcb:byte, buff:byte
  6.     extrn    taklev:byte, takadr:word, dosnum:byte
  7.  
  8. comand    cmdinfo <>
  9. cmer00    db    cr,lf,'?Program error   Invalid COMND call$'
  10. cmer01    db    cr,lf,'?Ambiguous$'
  11. cmer02    db    cr,lf,'?Illegal input file spec$'
  12. cmer03    db    cr,lf,'?Invalid command$'                ; [19e]
  13. cmer04    db    cr,lf,'?Invalid command or operand$'     ; [1]
  14. cmer06    db    cr,lf,'?Wildcard not allowed$'           ; [21a]
  15. cmer07    db    cr,lf,'?Invalid drive specificaton$'     ; [21a]
  16. cmin00    db    ' Confirm with carriage return$'
  17. cmin01    db    ' One of the following:',cr,lf,'$'
  18.  
  19. cmthlp    dw    0        ; Text of help message for random input.
  20. drives    db    0        ; How many drives we have. [21a]
  21. crlf    db    cr,lf,'$'
  22. ctcmsg    db    '^C$'
  23. prsp    db    ' $'                    ; Print a space.
  24. hlpmsg    dw    0            ; Address of help message.
  25. spchar    db    24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  26.     db    3CH,3EH,7BH,7DH,5FH,5CH,5EH,7EH,7CH,60H
  27. spclen    equ    $-spchar
  28. spchar2 db    24H,26H,23H,40H,21H,25H,27H,28H,29H,2DH
  29.     db    7BH,7DH,5FH,5EH,7EH,60H
  30. spc2len equ    $-spchar2
  31. escspc    db    10O,' ',10O,'$'         ; Clear escape.
  32. clrspc    db    ' ',10O,'$'             ; Clear space.
  33. filbuf    db    60H DUP(?)        ; Character buffer.
  34. tbuff    db    80  DUP(?)
  35. cmdstk    dw    ?
  36. datas    ends
  37.  
  38. code    segment public
  39.     extrn    dodel:near, ctlu:near, cmblnk:near, locate:near, takrd:near
  40.     extrn    clearl:near
  41.     assume    cs:code,ds:datas,es:datas
  42.  
  43. ;    This routine parses the specified function in AH. Any additional
  44. ;    information is in DX and BX.
  45. ;    Returns +1 on success
  46. ;        +4 on failure (assumes a JMP follows the call)
  47.  
  48. CMND    PROC NEAR
  49. comnd:    mov comand.cmstat,ah    ; Save what we are presently parsing.
  50.     mov cmdstk,sp        ; save stack ptr locally.
  51.     call cminbf        ; Get chars until an action or a erase char.
  52.     mov ah,comand.cmstat    ; Restore 'ah' for upcoming checks.
  53.     cmp ah,cmcfm        ; Parse a confirm?
  54.     jz cmcfrm        ; Go get one.
  55.     cmp ah,cmkey        ; Parse a keyword?
  56.     jnz cm1
  57.     jmp cmkeyw         ; Try and get one.
  58. cm1:    cmp ah,cmifi        ; Parse an input file spec?
  59.     jnz cm2
  60.     jmp cmifil        ; Go get one.
  61. cm2:    cmp ah,cmofi        ; Output file spec?
  62.     jnz cm3
  63.     jmp cmofil        ; Go get one.
  64. cm3:    cmp ah,cmtxt        ; Parse arbitrary text.   [8]
  65.     jnz cm4
  66.     jmp cmtext
  67. cm4:    mov ah,prstr        ; Else give error.
  68.     mov dx,offset cmer00    ; "?Unrecognized COMND call"
  69.     int dos
  70.     ret
  71.  
  72. ; This routine gets a confirm.
  73.  
  74. cmcfrm: call cmgtch        ; Get a char.
  75.     cmp ah,0        ; Is it negative (a terminator; a space or
  76.                 ; a tab will not be returned here as they
  77.                 ; will be seen as leading white space.)
  78.     js cmcfr0
  79.     ret            ; If not, return failure.
  80. cmcfr0: and ah,7FH            ; Turn off the minus bit.
  81.     cmp ah,esc            ; Is it an escape?
  82.     jne cmcfr2
  83.     mov ah,conout
  84.     mov dl,bell        ; Get a bell.
  85.     int dos
  86.     mov ah,0
  87.     mov comand.cmaflg,ah    ; Turn off the action flag.
  88.     mov bx,comand.cmcptr    ; Move the pointer to before thee scape.
  89.     dec bx
  90.     mov comand.cmcptr,bx
  91.     mov comand.cmdptr,bx
  92.     dec comand.cmccnt    ; Decremrnt the char count.
  93.     jmp cmcfrm        ; Try again.
  94. cmcfr2: cmp ah,'?'              ; Curious?
  95.     jne cmcfr3
  96.     mov ah,prstr        ; Print something useful.
  97.     mov dx,offset cmin00
  98.     int dos
  99.     mov ah,prstr
  100.     mov dx,offset crlf    ; Print a crlf.
  101.     int dos
  102.     mov ah,prstr
  103.     mov dx,comand.cmprmp    ; Reprint the prompt.
  104.     int dos
  105.     mov bx,comand.cmdptr    ; Get the pointer into the buffer.
  106.     mov ah,'$'              ; Put a $ there for printing.
  107.     mov [bx],ah
  108.     mov bx,comand.cmcptr
  109.     dec bx            ; Decrement & save the buffer pointer.
  110.     mov comand.cmcptr,bx
  111.     mov ah,prstr
  112.     mov dx,offset comand.cmdbuf
  113.     int dos
  114.     mov ah,0            ; Turn off the action flag.
  115.     mov comand.cmaflg,ah
  116.     jmp repars        ; Reparse everything.
  117.  
  118. cmcfr3: cmp ah,ff            ; Is it a form feed?
  119.     jne cmcfr4
  120.     call cmblnk        ; If so blank the screen.
  121. cmcfr4: jmp rskp
  122.  
  123. ;    This routine parses a keyword from the table pointed
  124. ;    to in DX.  The format of the table is as follows:
  125. ;
  126. ;    addr:    db    n    ; Where n is the # of entries in the table.
  127. ;        db    m    ; M is the size of the keyword.
  128. ;        db    'string$' ; Where string is the keyword.
  129. ;        dw    ab    ; Where ab is data to be returned.
  130. ;
  131. ;    The keywords must be in alphabetical order.
  132.  
  133.  
  134. cmkeyw: mov comand.cmhlp,bx    ; Save the help.
  135.     mov comand.cmptab,dx    ; Save the beginning of keyword table.
  136.     mov bx,dx
  137.     mov ch,[bx]        ; Get number of entries in table.
  138.     inc bx
  139.     mov dx,comand.cmdptr    ; Save command pointer.
  140.     mov comand.cmsptr,dx    ; Save pointer's here.
  141. cmky1:    cmp ch,0        ; Any commands left to check?
  142.     jne cmky2
  143.     jmp cmky41        ; no, go complain
  144. cmky2:    dec ch
  145.     mov cl,0        ; Keep track of how many chars read in so far.
  146.     call cmgtch        ; Get a char.
  147.     cmp ah,0        ; Do we have a terminator?
  148.     jns cmky2x
  149.     jmp cmky4        ; Negative number means we do.
  150. cmky2x: inc bx            ; Point to first letter of keyword.
  151.     inc cl            ; Read in another char.
  152.     mov al,[bx]
  153.     cmp ah,'a'              ; Less than a?
  154.     jl cmky21        ; If so, don't capitalize.
  155.     cmp ah,'z'+1            ; More than z?
  156.     jns cmky21
  157.     and ah,137O        ; Capitalize the letter.
  158. cmky21: cmp ah,al
  159.     je cmky3
  160.     jg cmky2y
  161.     jmp cmky41        ; Fail if ah preceeds al alphabetically.
  162. cmky2y: jmp cmky6        ; Not this keyword - try the next.
  163. cmky3:    inc bx            ; We match here, how 'bout next char?
  164.     mov al,[bx]
  165.     cmp al,'$'               ; End of keyword?
  166.     jne cmky3x
  167.     jmp cmky7         ; Succeed.
  168. cmky3x: mov dl,al        ; Save al's char here.
  169.     call cmgtch
  170.     inc cl            ; Read in another char.
  171.     mov al,dl
  172.     cmp ah,'a'
  173.     jl cmky31
  174.     cmp ah,'z'+1
  175.     jns cmky31
  176.     and ah,137O
  177. cmky31: cmp ah,esc+80H        ; Escape Recognition (escape w/minus bit on)?
  178.     je cmky3y
  179.     cmp ah,'?'+80H          ; A question mark?    [3]
  180.     je cmky3y
  181.     cmp ah,' '+80H          ; A space?
  182.     je cmky3y
  183.     cmp ah,cr+80H        ; Carriage return?
  184.     je cmky3y
  185.     jmp cmky38
  186. cmky3y: mov comand.cmkptr,bx    ; Save bx here.
  187.     mov comand.cmsiz,cx    ; Save size info.
  188.     mov comand.cmchr,ah    ; Save char for latter.
  189.     call cmambg        ; See if input is ambiguous or not.
  190.      jmp cmky32        ; Succeeded (not ambiguous).
  191.     mov ah,comand.cmchr
  192.     cmp ah,esc+80H        ; Escape?
  193.     je cmky3z
  194.     cmp ah,'?'+80H          ; maybe question mark?
  195.     je cmkyj1        ; yes, go handle
  196.     jmp cmky41        ; Else fail.
  197. cmky3z: mov ah,conout        ; Ring a bell.
  198.     mov dl,bell
  199.     int dos
  200.     mov bx,comand.cmcptr    ; Move pointer to before the escape.
  201.     dec bx
  202.     mov comand.cmcptr,bx
  203.     mov comand.cmdptr,bx
  204.     dec comand.cmccnt    ; Decrement char count.
  205.     mov bx,comand.cmkptr    ; Failed - pretend user never typed ....
  206.     mov cx,comand.cmsiz    ; ... in a char.
  207.     dec cl            ; Don't count the escape.
  208.     dec bx
  209.     mov comand.cmaflg,0    ; Reset the action flag.
  210.     jmp cmky3        ; Keep checking.
  211. ; ambiguous.  Print out all the keywords that match
  212. cmkyj1: mov dx,offset cmin01
  213.     mov ah,prstr
  214.     int dos
  215.     mov bx,comand.cmkptr    ; this is current keyword
  216.     mov cx,comand.cmsiz    ; we are cl chars into it
  217.     mov ch,0
  218.     sub bx,cx        ; back up to beginning
  219.     inc bx            ; not counting ?
  220.     mov comand.cmkptr,bx    ; save beginning of kw
  221. cmkyj2: mov dl,tab        ; put a tab before each keyword
  222.     mov ah,conout
  223.     int dos
  224.     mov dx,comand.cmkptr    ; get current keyword
  225.     mov ah,prstr
  226.     int dos         ; print it
  227.     mov bx,comand.cmkptr    ; get keyword back
  228.     dec bx
  229.     mov al,[bx]        ; get length
  230.     mov ah,0
  231.     add ax,5        ; skip length, $, value, next length
  232.     add bx,ax        ; this is next keyword
  233.     mov si,bx
  234.     mov di,comand.cmkptr    ; compare with last keyword
  235.     mov comand.cmkptr,bx    ; update this
  236.     mov cx,comand.cmsiz
  237.     dec ch            ; are we at end of table?
  238.     jl cmkyj3        ; yes, don't go on
  239.     mov comand.cmsiz,cx    ; else update count
  240.     mov ch,0
  241.     dec cl            ; this includes ?
  242.     jcxz cmkyj2        ; empty, just print it
  243.     repe cmpsb        ; compare to previous string
  244.     je cmkyj2        ; same, go print this one
  245. cmkyj3: jmp cmky50        ; else go finish up
  246.  
  247. cmky32: mov cx,comand.cmsiz    ; Restore info.
  248.     mov bx,comand.cmkptr    ; Our place in the keyword table.
  249.     cmp comand.cmchr,0A0H    ; Space?
  250.     je cmky35
  251.     cmp comand.cmchr,0BFH    ; Question mark?     [3]
  252.     je cmky35
  253.     cmp comand.cmchr,8DH    ; Carriage return?
  254.     je cmky35
  255.     dec comand.cmcptr    ; Pointer into buffer of input.
  256.     mov dx,comand.cmcptr
  257. cmky33: mov ah,[bx]        ; Get next char in keyword.
  258.     cmp ah,'$'              ; Are we done yet?
  259.     jz cmky34
  260.     mov di,dx
  261.     mov [di],ah
  262.     inc bx
  263.     inc dx
  264.     inc comand.cmccnt
  265.     jmp cmky33
  266. cmky34: mov ah,' '
  267.     mov di,dx
  268.     mov [di],ah        ; Put a blank in the buffer.
  269.     inc dx
  270.     mov cx,comand.cmcptr    ; Remember where we were.
  271.     mov comand.cmcptr,dx    ; Update our pointers.
  272.     mov comand.cmdptr,dx
  273.     mov ah,'$'
  274.     mov di,dx
  275.     mov [di],ah        ; Add '$' for printing.
  276.     mov ah,prstr
  277.     mov dx,cx        ; Point to beginning of filled in data.
  278.     int dos
  279.     inc bx            ; Point to address we'll need.
  280.     mov bx,[bx]
  281.     mov comand.cmaflg,0    ; Turn off action flag.
  282.     jmp rskp
  283.  
  284. cmky35: inc bx
  285.     mov ah,[bx]        ; Find end of keyword.
  286.     cmp ah,'$'
  287.     jne cmky35
  288.     inc bx
  289.     mov bx,[bx]        ; Address of next routine to call.
  290. ;    mov comand.cmaflg,0    ; Zero the action flag.
  291.     jmp rskp
  292.  
  293. cmky38: cmp ah,al
  294.     je cmky39
  295.     jmp cmky6        ; Go to end of keyword and try next.
  296. cmky39: jmp cmky3        ; Check next letter.
  297.  
  298. cmky4:    and ah,7FH        ; Turn off minus bit.
  299.     cmp ah,'?'              ; Need help?
  300.     je cmky5
  301.     cmp ah,' '              ; Just a space - no error.
  302.     je cmky51
  303.     cmp ah,cr
  304.     je cmky51
  305.     cmp ah,tab
  306.     je cmky51
  307.     cmp ah,esc        ; Ignore escape?
  308.     je cmky43
  309. cmky41: mov ah,prstr
  310.     mov dx,offset cmer03
  311.     int dos
  312.     jmp prserr        ; Parse error - give up.
  313.  
  314. cmky43: mov ah,conout        ; Ring a bell.
  315.     mov dl,bell
  316.     int dos
  317.     dec comand.cmcptr    ;[ESC] don't trash BX here.
  318.     dec comand.cmdptr    ;[ESC] ditto
  319.     dec comand.cmccnt    ; Don't count the escape.
  320.     mov comand.cmaflg,0    ; Reset action flag.
  321.     inc ch            ; Account for a previous 'dec'.
  322.     jmp cmky1        ; Start over.
  323.  
  324. cmky5:    inc bx            ; point to actual keyword
  325.     mov comand.cmkptr,bx    ; remember current kw
  326.     mov cl,1        ; code above expects to count ?
  327.     mov comand.cmsiz,cx    ; and size
  328.     mov dx,comand.cmhlp
  329.     or dx,dx        ; was any help given?
  330.     jnz cmky5a        ; yes, use it
  331.     jmp cmkyj1        ; else make our own message
  332. cmky5a: mov ah,prstr
  333.     int dos
  334. cmky50: mov ah,prstr
  335.     mov dx,offset crlf
  336.     int dos
  337.     mov dx,comand.cmprmp    ; Address of prompt.
  338.     int dos
  339.     mov bx,comand.cmdptr    ; Get pointer into buffer.
  340.     mov al,'$'
  341.     mov [bx],al        ; Add dollar sign for printing.
  342.     mov dx,offset comand.cmdbuf
  343.     int dos
  344.     dec comand.cmcptr    ; Don't keep it in the buffer.
  345.     dec comand.cmccnt    ; Don't conut it.
  346.     mov comand.cmaflg,0    ; Turn off the action flag.
  347.     jmp repars
  348.  
  349. cmky51: cmp comand.cmcr,1    ; Are bare CR's allowed?
  350.     je cmky52        ; Yes.
  351.     mov ah,prstr
  352.     mov dx,offset cmer04    ; Complain.
  353.     int dos
  354. cmky52: jmp prserr
  355.  
  356. cmky6:    inc bx            ; Find end of keyword.
  357.     mov al,[bx]
  358.     cmp al,'$'
  359.     jne cmky6
  360.     inc bx            ; Beginning of next command.
  361.     inc bx
  362.     inc bx
  363.     mov dx,comand.cmsptr    ; Get old cmdptr.
  364.     mov comand.cmdptr,dx    ; Restore.
  365.     mov comand.cmsflg,0FFH
  366.     jmp cmky1        ; Keep trying.
  367.  
  368. cmky7:    call cmgtch        ; Get char.
  369.     cmp ah,0
  370.     js cmky71        ; Ok if a terminator.
  371.     dec bx
  372.     jmp cmky6        ; No match - try next keyword.
  373. cmky71: inc bx            ; Get necessary data.
  374.     mov bx,[bx]
  375.     cmp ah,9BH        ; An escape?
  376.     jne cmky72
  377.     mov ah,prstr
  378.     mov dx,offset prsp    ; Print a space.
  379.     int dos
  380.     mov di,comand.cmcptr
  381.     dec di
  382.     mov ah,20H
  383.     mov [di],ah        ; Replace escape char with space.
  384.     mov comand.cmaflg,0
  385.     mov comand.cmsflg,0FFH    ; Pretend they typed a space.
  386. cmky72: jmp rskp
  387.  
  388. ; See if keyword is unambiguous or not from what the user has typed in.
  389.  
  390. cmambg: cmp ch,0        ; Any keywords left to check?
  391.     jne cmamb0
  392.     ret            ; If not then not ambiguous.
  393. cmamb0: inc bx            ; Go to end of keyword ...
  394.     mov al,[bx]        ; So we can check the next one.
  395.     cmp al,'$'
  396.     jne cmamb0
  397.     add bx,4        ; Point to start of next keyword.
  398.     dec cl            ; Don't count escape.
  399.     mov dx,comand.cmsptr    ; Buffer with input typed by user.
  400. cmamb1: mov ah,[bx]        ; Keyword char.
  401.     mov di,dx
  402.     mov al,[di]        ; Input char.
  403.     cmp al,'a'              ; Do capitalizing.
  404.     jl cmam11
  405.     cmp al,'z'+1
  406.     jns cmam11
  407.     and al,137O
  408. cmam11: cmp ah,al        ; Keyword bigger than input (alphabetically)?
  409.     jle cmamb2        ; No - keep checking.
  410.     ret            ; Yes - not ambiguous.
  411. cmamb2: inc bx            ; Advance one char.
  412.     inc dx
  413.     dec cl
  414.     jnz cmamb1
  415.     jmp rskp        ; Fail - it's ambiguous.
  416.  
  417. cmifil: mov hlpmsg,bx        ; Address of help message.
  418.     mov bx,dx        ; Get the fcb address in bx.
  419.     mov comand.cmfcb,bx    ; Save it.
  420.     mov ch,0        ; Initialize char count.
  421.     mov ah,0
  422.     mov [bx],ah        ; Set the drive to default to current.
  423.     inc bx
  424.     mov comand.cmfcb2,bx
  425.     mov cl,' '
  426. cmifi0: mov [bx],cl        ; Blank the FCB.
  427.     inc bx
  428.     inc ah
  429.     cmp ah,0BH        ; Twelve?
  430.     jl cmifi0
  431. cmifi1: call cmgtch        ; Get another char.
  432.     cmp ah,0        ; Is it an action character.
  433.     js cmif1x        ; Jump out of range. [21a]
  434.     jmp cmifi2        ; Ditto. [21a]
  435. cmif1x: and ah,7FH        ; Turn off the action bit. [21a]
  436.     cmp ah,'?'              ; A question mark?
  437.     jne cmif12
  438.     mov al,0
  439.     mov comand.cmaflg,al    ; Blank the action flag.
  440.     dec comand.cmcptr    ; Decrement the buffer pointer.
  441.     dec comand.cmccnt    ; Decrement count.
  442.     mov ah,prstr
  443.     mov dx,hlpmsg        ; Help    message.
  444.     int dos
  445.     mov dx,offset crlf
  446.     int dos
  447.     mov dx,comand.cmprmp
  448.     int dos
  449.     mov bx,comand.cmdptr
  450.     mov al,'$'
  451.     mov [bx],al        ; Put in dollar sign for printing.
  452.     mov dx,offset comand.cmdbuf
  453.     int dos
  454.     jmp repars
  455. cmif12: cmp ah,esc        ; An escape?
  456.     je cm12x
  457.     jmp cmif13
  458. cm12x:    mov comand.cmaflg,0    ; Turn off the action flag.
  459.     dec comand.cmcptr    ; Move pointers to before the escape.
  460.     dec comand.cmdptr
  461.     dec comand.cmccnt    ; Decrement char count.
  462.     mov comand.cmchr,ch    ; Save current character count.
  463.     cmp ch,9        ; Past '.'?
  464.      jl cmf120        ; No.
  465.     dec ch            ; Yes, don't count point.
  466. cmf120: mov di,comand.cmfcb2    ; Fill the rest with CP/M wildcards.
  467.     mov ah,'?'
  468.  
  469. cmf121: cmp ch,11        ; Done?
  470.      jge cmf122        ; Yes.
  471.     mov [di],ah
  472.     inc di
  473.     inc ch
  474.     jmp cmf121
  475.  
  476. cmf122: mov ah,sfirst        ; Find first matching file?
  477.     mov dx,comand.cmfcb    ;[jd] use pointer to PASSED fcb
  478.     int dos
  479.     cmp al,0FFH        ; Any found?
  480.     jne cmf123        ; Yes.
  481.      jmp cmf12b        ; No, lose.
  482. cmf123: mov di,offset filbuf    ; Copy first file spec from DTA to buffer.
  483.     mov bx,offset buff+1
  484.     mov cl,11
  485.     call fcbcpy
  486.     mov di,offset filbuf+10H ; Get another copy (if not ambiguous).
  487.     mov bx,offset buff+1
  488.     mov cl,11
  489.     call fcbcpy
  490.     mov ah,snext        ; More matching specs?
  491.     mov dx,comand.cmfcb    ;[jd] use PASSED fcb...
  492.     int dos
  493.     cmp al,0FFH
  494.      je cmf124        ; Only one.
  495.     mov di,offset filbuf+10H ; Copy second file spec.
  496.     mov bx,offset buff+1
  497.     mov cl,11
  498.     call fcbcpy
  499.  
  500. cmf124: mov si,offset filbuf    ; Start comparing file names.
  501.     mov bx,offset filbuf+10H
  502.     mov di,comand.cmcptr    ; Command buffer pointer
  503.     mov cl,comand.cmchr    ; Bypass characters typed.
  504.     cmp cl,9        ; Past '.'?
  505.      jl cmf125        ; No.
  506.     dec cl            ; Yes, don't count point.
  507. cmf125: mov ch,0        ; Adjust pointers.
  508.     add si,cx
  509.     add bx,cx
  510.     mov ch,cl        ; Update character count
  511.  
  512. cmf126: cmp ch,11        ; All done?
  513.     jne cmf127        ; No.
  514.      jmp cmf12a        ; Yes.
  515. cmf127: cmp ch,8        ; End of file name?
  516.      jne cmf128        ; No.
  517.     cmp comand.cmchr,9    ; Exactly at point?
  518.      je cmf128        ; Yes, don't output a second point.
  519.     mov ah,'.'              ; Output separator.
  520.     mov [di],ah
  521.     inc di
  522.     inc comand.cmccnt
  523. cmf128: mov ah,[si]        ; Get a character from first file spec.
  524.     inc si
  525.     mov al,[bx]        ; Get another from second spec.
  526.     inc bx
  527.     cmp ah,al        ; Compare.
  528.      jne cmf12a        ; Ambiguous.
  529.     inc ch            ; Same, count.
  530.     cmp ah,' '              ; Blank?
  531.      je cmf129        ; Yes, don't output.
  532.     mov [di],ah
  533.     inc di
  534.     inc comand.cmccnt
  535. cmf129: jmp cmf126        ; Repeat.
  536.  
  537. cmf12a: mov comand.cmchr,ch    ; Save count of characters processed.
  538.     mov ah,'$'              ; Put terminator into buffer.
  539.     mov [di],ah
  540.     mov comand.cmcptr,di    ; Save pointer for recognized characters.
  541.     mov ah,prstr
  542.     mov dx,comand.cmdptr
  543.     int dos
  544.     mov ch,comand.cmchr    ; Characters processed.
  545.     cmp ch,11        ; Complete file name.
  546.      je cmf12c        ; Yes, don't beep.
  547.  
  548. cmf12b: mov ah,conout        ; Beep, if not recognized.
  549.     mov dl,bell
  550.     int dos         ; Ring the bell.
  551. cmf12c: jmp repars
  552.  
  553. cmif13: mov ah,ch        ; It must be a terminator.
  554.     cmp ah,0        ; Test the length of the file name.
  555.     jnz cmf3x
  556.     cmp comand.cmcr,1    ; Is zero length OK? [21a]
  557.     je cmf3z        ; Return successfully. [21a]
  558.     jmp cmifi9        ; If zero complain.
  559. cmf3x:    cmp ah,0DH
  560.     js cmf3y
  561.     jmp cmifi9        ; If too long complain.
  562. cmf3y:    jmp rskp        ; Otherwise we have succeeded.
  563. cmf3z:    push es
  564.     mov ax,ds
  565.     mov es,ax
  566.     mov di,comand.cmfcb
  567.     inc di
  568.     mov cx,11
  569.     mov al,'?'
  570.     repne stosb
  571.     pop es
  572.     mov flags.wldflg,0FFH    ; Remember we had a wildcard.
  573.     jmp rskp
  574. cmifi2: cmp ah,'.'
  575.     jne cmifi3
  576.     inc ch
  577.     mov ah,ch
  578.     cmp ah,1H        ; Any chars yet?
  579.     jnz cmf2x
  580.     jmp cmifi9        ; No, give error.
  581. cmf2x:    cmp ah,0AH        ; Tenth char?
  582.     js cmf2y
  583.     jmp cmifi9        ; Past it, give an error.
  584. cmf2y:    mov dl,9H
  585.     mov dh,0
  586.     mov bx,comand.cmfcb
  587.     add bx,dx        ; Point to file type field.
  588.     mov comand.cmfcb2,bx
  589.     mov ch,9H        ; Say we've gotten nine.
  590.     jmp cmifi1        ; Get the next char.
  591. cmifi3: cmp ah,':'
  592.     jne cmifi4
  593.     inc ch
  594.     cmp ch,2H        ; Is it in right place for a drive?
  595.     je cmif3x
  596.     jmp cmifi9        ; If not, complain.
  597. cmif3x: mov ch,0        ; Reset char count.
  598.     mov flags.droflg,1    ; Override default drive. [21a]
  599.     mov flags.nmoflg,0    ; Not so fast. [21a]
  600.     mov bx,comand.cmfcb2
  601.     mov al,':'              ; Use for parsing drive name.
  602.     mov [bx],al
  603.     dec bx            ; Point to drive spec.
  604.     mov si,bx
  605.     push es
  606.     mov ax,ds
  607.     mov es,ax
  608.     mov di,offset tbuff    ; Borrow this buffer.
  609.     mov ah,prsfcb
  610.     int dos
  611.     pop es
  612.     cmp al,0        ; OK return code?
  613.     je cmif3y        ; Yes, keep going.
  614. ;     mov ah,[bx]        ; Get the drive name.
  615. ;     sub ah,'@'              ; Get the drive number.
  616. ;    cmp ah,drives        ; Did user specify a non-existant drive? [21a]
  617. ;    jle cmif3y        ; Nope, so continue. [21a]
  618.     mov dx,offset cmer07    ; Fail with this error message. [21a]
  619.     jmp cmif9x        ; [21a]
  620. cmif3y: mov comand.cmfcb2,bx    ; Put rest of filename starting here. [21a]
  621.     mov ah,[bx]        ; Pick up drive specified.
  622.     sub ah,'@'              ; Get real value.
  623.     mov bx,comand.cmfcb
  624.     mov [bx],ah        ; Put it in the fcb.
  625.     push bx
  626.     mov al,' '              ; Overwrite the drive and ":".
  627.     inc bx
  628.     mov [bx],al
  629.     inc bx
  630.     mov [bx],al
  631.     pop bx
  632.     jmp cmifi1
  633. cmifi4: cmp ah,'*'
  634.     jne cmifi7
  635.     cmp comand.cmrflg,1    ; In receive mode?  [21a]
  636.     jne cmif4x        ; Jump out of range. [21a]
  637.     mov dx,offset cmer06    ; Set the error message. [21a]
  638.     jmp cmif9x        ; Fail - no wildcard allowed. [21a]
  639. cmif4x: mov ah,ch        ; [21a]
  640.     cmp ah,8H        ; Is this in the name or type field?
  641.     jns cmifi5        ; Type.
  642.     mov cl,8H        ; Say we have eight chars.
  643.     js cmifi6        ; Name field.
  644.     jmp cmifi9        ; If its where the dot should be give up.
  645. cmifi5: mov cl,0CH        ; Three chars.
  646. cmifi6: mov flags.wldflg,0FFH    ; Remember we had a wildcard.
  647.     mov bx,comand.cmfcb2    ; Get a pointer into the FCB.
  648.     mov ah,'?'
  649.     mov [bx],ah        ; Put a question mark in.
  650.     inc bx
  651.     mov comand.cmfcb2,bx
  652.     inc ch
  653.     mov ah,ch
  654.     cmp ah,cl
  655.     jl cmifi6        ; Go fill in another.
  656.     jmp cmifi1        ; Get the next char.
  657. cmifi7: cmp ah,03DH        ; Equals sign (wildcard)?
  658.     jne cmif7x
  659.     cmp comand.cmrflg,1    ; In receive mode?  [21a]
  660.     jne cmif7y        ; No, so it's ok. [21a]
  661.     mov dx,offset cmer06    ; Set the error message. [21a]
  662.     jmp cmif9x        ; Fail - no wildcard allowed. [21a]
  663. cmif7y: mov ah,'?'              ; New label. [21a]
  664.     mov flags.wldflg,0FFH    ; Say we have a wildcard.
  665.     jmp cmifi8        ; Put into FCB.
  666. cmif7x: cmp ah,'0'
  667.     jl cmif8x
  668.     cmp ah,'z'+1
  669.     jns cmif8x
  670.     cmp ah,'A'              ; Don't capitalize non-alphabetics.
  671.     jl cmifi8
  672.     and ah,137O        ; Capitalize.
  673. cmifi8: mov bx,comand.cmfcb2    ; Get the pointer into the FCB.
  674.     mov [bx],ah        ; Put the char there.
  675.     inc bx
  676.     mov comand.cmfcb2,bx
  677.     mov flags.nmoflg,1    ; Overriding name from host. [21a]
  678.     inc ch
  679.     jmp cmifi1
  680.  
  681. cmif8x: push es
  682.     mov cx,ds
  683.     mov es,cx        ; Scan uses ES register.
  684.     mov di,offset spchar    ; Special chars.
  685.     mov cx,spclen        ; How many of them.
  686.     cmp dosnum,0        ; Under version 2.0
  687.     je cmif8y
  688.     mov di,offset spchar2
  689.     mov cx,spc2len
  690. cmif8y: mov al,ah        ; Char is in al.
  691.     repnz scasb        ; Search string for input char.
  692.     cmp cx,0        ; Was it there?
  693.     pop es
  694.     jnz cmifi8
  695.  
  696. cmifi9: mov dx,offset cmer02
  697. cmif9x: mov ah,prstr
  698.     int dos
  699.     mov flags.droflg,0    ; Not overriding drive. [21a]
  700.     mov flags.nmoflg,0    ; Or name to save file under. [21a]
  701.     mov comand.cmrflg,0    ; Reset this flag too. [21a]
  702.     ret
  703.  
  704. cmofil: jmp cmifil        ; For now, the same as CMIFI.
  705.  
  706. ; Parse arbitrary text up to a CR.  Put chars into data buffer sent to
  707. ; the host (pointed to by BX).     Called with text of help message in DX.
  708. ; Return updated pointer in BX and input size in AH.
  709.  
  710. cmtext: mov comand.cmptab,bx    ; Save pointer to data buffer.     [8 start]
  711.     mov cmthlp,dx        ; Save the help message.
  712.     mov cl,0        ; Init the char count.
  713. cmtxt1: mov comand.cmsflg,0    ; Get all spaces. [25]
  714.     call cmgtch        ; Get a char.
  715.     test ah,80H        ; is high-order bit on?
  716.     jz cmtxt5        ; Nope, put into the buffer.
  717.     and ah,07FH
  718.     cmp ah,' '
  719.     je cmtxt5
  720.     cmp ah,esc        ; An escape?
  721.     jne cmtxt2
  722.     mov ah,conout
  723.     mov dl,bell        ; Ring a bell.
  724.     int dos
  725.     mov comand.cmaflg,0    ; Reset action flag.
  726.     dec comand.cmcptr    ; Move pointer to before the escape.
  727.     dec comand.cmdptr
  728.     dec comand.cmccnt    ; Decrement count.
  729.     jmp cmtxt1        ; Try again.
  730. cmtxt2: cmp ah,'?'              ; Asking a question?
  731.     jz cmtx30
  732.     cmp ah,ff        ; Formfeed?
  733.     jne cmtx2x
  734.     call cmblnk
  735. cmtx2x: mov ah,cl        ; Return count in AH.
  736.     mov bx,comand.cmptab    ; Return updated pointer.
  737.     jmp rskp
  738. cmtx30: mov comand.cmaflg,0    ; Reset action flag to zero.
  739.     inc comand.cmdptr    ; count the ?
  740.     cmp cl,0        ; Is "?" first char?
  741.     jne cmtxt5        ; No, just add to buffer.
  742.     dec comand.cmcptr    ;[ESC] (moved 3 lines) Don't keep in buffer.
  743.     dec comand.cmccnt    ;[ESC] Don't conut it.
  744.     dec comand.cmdptr    ;[ESC] don't count if printing help.
  745.     mov ah,prstr        ; Else, give some help.
  746.     mov dx,cmthlp        ; Address of help message.
  747.     int dos
  748.     mov ah,prstr
  749.     mov dx,offset crlf    ; Print a crlf.
  750.     int dos
  751.     mov ah,prstr
  752.     mov dx,comand.cmprmp    ; Reprint the prompt.
  753.     int dos
  754.     mov bx,comand.cmdptr    ; Get the pointer into the buffer.
  755.     mov byte ptr [bx],'$'
  756.     mov ah,prstr
  757.     mov dx,offset comand.cmdbuf
  758.     int dos
  759.     jmp cmtxt1        ; And keep going.
  760. cmtxt5: inc cl            ; Increment the count.
  761.     mov bx,comand.cmptab    ; Pointer into destination array.
  762.     mov [bx],ah        ; Put char into the buffer.
  763.     inc bx
  764.     mov comand.cmptab,bx
  765.     jmp cmtxt1                    ; [8 end]
  766.  
  767. cmgetc: cmp taklev,0
  768.     jne cmget1
  769.     jmp cmge10            ; no take file, get from keyboard
  770. cmget1: push bx
  771.     push si
  772.     mov bx,takadr
  773.     mov ax,[bx].takcnt
  774.     or ax,[bx].takcnt+2
  775.     jnz cmget5
  776. cmget2: mov al,byte ptr [bx].takfcb    ; get first byte of fcb
  777.     cmp al,0ffh            ; is it really a macro?
  778.     je cmget4            ; yes, better not try to close it
  779.     cmp al,0feh            ; or maybe a file handle?
  780.     je cmget3            ; yes, close w/2.0 call
  781.     mov ah,closf
  782.     lea dx,[bx].takfcb
  783.     int dos
  784.     jmp short cmget4            ; skip over alternate close
  785. cmget3: mov bx,word ptr [bx].takfcb+1    ; this is where file handle is stored
  786.     mov ah,close2            ; use 2.0 close
  787.     int dos
  788. cmget4: dec taklev
  789.     sub takadr,size takinfo
  790.     pop si
  791.     pop bx
  792.     mov al,cr        ; end with carriage return...
  793.     ret
  794.  
  795. cmget5: cmp [bx].takchl,0    ; Any chars left in buffer?
  796.     jne cmget6
  797.     call takrd
  798. cmget6: dec [bx].takchl
  799.     sub [bx].takcnt,1    ; DEC doesn't set carry!!
  800.     sbb [bx].takcnt+2,0
  801.     mov si,[bx].takptr
  802.     lodsb
  803.     mov [bx].takptr,si
  804.     cmp al,ctlz        ; maybe control-z?
  805.     je cmget2        ; yes, close take file (has to be before pops)
  806.     pop si
  807.     pop bx
  808.     cmp al,lf        ; linefeed?
  809.     jne cmget7
  810.     cmp flags.takflg,0
  811.     je cmgetc        ; yes, ignore it
  812. cmget7: cmp al,';'              ; maybe a semicolon?
  813.     je cmget9
  814.     cmp flags.takflg,0    ; Echo contents of take file?
  815.     je cmget8
  816.     push dx
  817.     mov dl,al
  818.     mov ah,conout
  819.     int dos
  820.     pop dx
  821. cmget8: ret            ; else just return...
  822. ; semicolon seen, ignore chars until cr
  823. cmget9: call cmgetc        ; get a character?
  824.     cmp al,cr        ; carriage return?
  825.     jne cmget9        ; no, keep reading
  826.     ret            ; else return it
  827.  
  828. cmge10: mov ah,coninq        ; Get a char.
  829.     cmp flags.debug,0    ; in debug mode?
  830.     je cmge11        ; yes, go on
  831.     mov ah,8        ; else use read that recognizes ^C
  832. cmge11: int dos
  833.     push ax         ; save the char
  834.     cmp al,bs        ; backspace?
  835.     je cmge13        ; yes, skip echo
  836.     cmp al,' '              ; printable?
  837.     jae cmge12        ; yes, no translation needed
  838.     cmp al,cr        ; this is printable
  839.     je cmge12
  840.     cmp al,lf
  841.     je cmge12
  842.     cmp al,tab
  843.     je cmge12
  844.     mov al,' '              ; else echo a space
  845. cmge12: mov dl,al        ; put char here
  846.     mov ah,conout
  847.     int dos         ; echo it ourselves...
  848. cmge13: pop ax            ; and return it
  849.     cmp al,'C'-40H          ; control-C?
  850.     je cmge15        ; yes, go handle
  851.     cmp al,';'              ; semicolon?
  852.     je cmget9        ; yes, ignore rest of line...
  853.     cmp al,tab
  854.     jne cmge14
  855.     mov al,' '
  856. cmge14: ret
  857. cmge15: mov dx,offset ctcmsg
  858.     mov ah,prstr
  859.     int dos
  860.     mov flags.cxzflg,'C'    ; remember ^C'd
  861.     mov sp,cmdstk        ; restore command stack ptr
  862.     ret            ; and fail
  863.  
  864. ; Come here is user types ^W when during input.
  865. cntrlw: mov ah,prstr
  866.     mov dx,offset escspc
  867.     int dos
  868.     dec comand.cmccnt    ; Don't include it in the count.
  869.     dec comand.cmcptr    ; Back up past the ^W.
  870.     mov cl,comand.cmccnt
  871.     mov ch,0
  872.     jcxz ctlw2
  873.     pushf
  874.     push es
  875.     std            ; Scan backwards.
  876.     mov ax,ds
  877.     mov es,ax        ; Point to the data area.
  878.     mov di,comand.cmcptr    ; Looking from here.
  879.     dec di
  880.     mov al,' '
  881.     repe scasb        ; Look for non-space.
  882.     je ctlw1        ; All spaces, nothing else to do
  883.     inc di            ; move back to non-space
  884.     inc cx
  885.     repne scasb        ; look for a space
  886.     jne ctlw1        ; no space, leave ptrs alone
  887.     inc di
  888.     inc cx            ; skip back over space
  889. ctlw1:    inc di
  890.     mov comand.cmccnt,cl    ; update count
  891.     mov cx,comand.cmcptr    ; remember old ptr
  892.     mov comand.cmcptr,di    ; update pointer
  893.     sub cx,di        ; this is characters moved
  894.     mov al,bs        ; backspace
  895.     cld
  896.     mov di,offset tbuff    ; temporary buffer
  897.     rep stosb        ; put enough spaces in
  898.     mov byte ptr [di],'$'   ; end buffer
  899.     mov dx,offset tbuff
  900.     mov ah,prstr
  901.     int dos         ; back up cursor
  902.     call clearl        ; clear line
  903.     pop es
  904.     popf
  905.     ret            ; and return
  906. ctlw2:    mov ah,conout
  907.     mov dl,bell
  908.     int dos
  909.     ret
  910.  
  911. cminbf: push dx
  912.     push bx
  913.     mov cx,dx        ; Save value here too.
  914.     mov ah,comand.cmaflg    ; Is the action char flag set?
  915.     cmp ah,0
  916.     je cminb1
  917.     jmp cminb9        ; If so get no more chars.
  918. cminb1: inc comand.cmccnt    ; Increment the char count.
  919.     call cmgetc
  920.     mov ah,al        ; Keep char in 'ah'.
  921.     mov bx,comand.cmcptr    ; Get the pointer into the buffer.
  922.     mov [bx],ah        ; Put it in the buffer.
  923.     inc bx
  924.     mov comand.cmcptr,bx
  925.     cmp ah,'W'-64           ; Is it a ^W?
  926.     jne cmnb11
  927.     call cntrlw        ; Kill the previous word.
  928.     jmp repars
  929. cmnb11: cmp ah,25O        ; Is it a ^U?
  930.     jne cminb2
  931. cmnb12: call ctlu        ; Clear out the line.
  932.     mov ah,prstr
  933.     mov dx,comand.cmprmp    ; Print the prompt.
  934.     int dos
  935.     mov bx,offset comand.cmdbuf
  936.     mov comand.cmcptr,bx    ; Reset the point to the start.
  937.     mov comand.cmccnt,0    ; Zero the count.
  938.     mov dx,cx        ; Preserve original value of dx.
  939.     jmp repars        ; Go start over.
  940. cminb2: cmp ah,bs           ; Or backspace?
  941.     jz cminb3
  942.     cmp ah,del        ; Delete?
  943.     jne cminb4
  944. cminb3: call dodel        ; Delete a character.
  945.     mov ah,comand.cmccnt    ; Decrement the char count by two.
  946.     dec ah
  947.     dec ah
  948.     cmp ah,0            ; Have we gone too far?
  949.     jns cmnb32        ; If not proceed.
  950.     mov ah,conout        ; Ring the bell.
  951.     mov dl,bell
  952.     int dos
  953.     jmp cmnb12        ; Go reprint prompt and reparse.
  954. cmnb32: mov comand.cmccnt,ah    ; Save the new char count.
  955.     mov ah,prstr        ; Erase the character.
  956.     mov dx,offset clrspc
  957.     int dos
  958.     mov bx,comand.cmcptr    ; Get the pointer into the buffer.
  959.     dec bx            ; Back up in the buffer.
  960.     dec bx
  961.     mov comand.cmcptr,bx
  962.     jmp repars        ; Go reparse everything.
  963. cminb4: cmp ah,'?'              ; Is it a question mark.
  964.     jz cminb6
  965.     cmp ah,esc        ; Is it an escape?
  966.     jz cminb8
  967.     cmp ah,cr        ; Is it a carriage return?
  968.     jz cminb5
  969.     cmp ah,lf        ; Is it a line feed?
  970.     jz cminb5
  971.     cmp ah,ff        ; Is it a formfeed?
  972.     jne cminb7
  973.     call cmblnk
  974.     call locate
  975. cminb5: mov ah,comand.cmccnt    ; Have we parsed any chars yet?
  976.     cmp ah,1
  977.     jnz cminb6
  978.     jmp prserr        ; If not, just start over.
  979. cminb6: mov ah,0FFH        ; Set the action flag.
  980.     mov comand.cmaflg,ah
  981.     jmp cminb9
  982. cminb7: jmp cminb1        ; Get another char.
  983.  
  984. cminb8: mov ah,prstr        ; Don't print the escape char.
  985.     mov dx,offset escspc
  986.     int dos
  987.     jmp cminb6
  988.  
  989. cminb9: pop bx
  990.     pop dx
  991.     ret
  992.  
  993. cmgtch: push cx
  994.     push bx
  995.     push dx
  996. cmgtc1: mov ah,comand.cmaflg
  997.     cmp ah,0            ; Is it set.
  998.     jne cmgt10
  999.     call cminbf        ; If the action char flag is not set get more.
  1000. cmgt10: mov bx,comand.cmdptr    ; Get a pointer into the buffer.
  1001.     mov ah,[bx]        ; Get the next char.
  1002.     inc bx
  1003.     mov comand.cmdptr,bx
  1004.     cmp ah,' '              ; Is it a space?
  1005.     jz cmgtc2
  1006.     cmp ah,tab        ; Or a tab?
  1007.     jne cmgtc3
  1008. cmgtc2: mov ah,comand.cmsflg    ; Get the space flag.
  1009.     cmp ah,0        ; Was the last char a space?
  1010.     jne cmgtc1        ; Yes, get another char.
  1011.     mov ah,0FFH        ; Set the space flag.
  1012.     mov comand.cmsflg,ah
  1013.     mov ah,' '
  1014.     pop dx
  1015.     pop bx
  1016.     jmp cmgtc5
  1017. cmgtc3: mov al,0
  1018.     mov comand.cmsflg,al    ; Zero the space flag.
  1019.     pop dx
  1020.     pop bx
  1021.     cmp ah,esc
  1022.     jz cmgtc5
  1023.     cmp ah,'?'              ; Is the user curious?
  1024.     jz cmgtc4
  1025.     cmp ah,cr
  1026.     jz cmgtc4
  1027.     cmp ah,lf
  1028.     jz cmgtc4
  1029.     cmp ah,ff
  1030.     je cmgtc4
  1031.     pop cx
  1032.     ret            ; Not an action char, just return.
  1033. cmgtc4: dec comand.cmdptr
  1034. cmgtc5: or ah,80H        ; Make the char negative to indicate
  1035.     pop cx
  1036.     ret            ; it is a terminator.
  1037. CMND    ENDP
  1038.  
  1039. ;    This address is jumped to on reparse.
  1040.  
  1041. PARSE    PROC NEAR
  1042. repars: mov sp,comand.cmostp   ; new sp <-- old sp
  1043.     mov bx,offset comand.cmdbuf
  1044.     mov comand.cmdptr,bx
  1045.     mov ah,0FFH
  1046.     mov comand.cmsflg,ah
  1047.     jmp comand.cmrprs    ; go back to reparse address
  1048.  
  1049. ;    This address can be jumped to on a parsing error.
  1050.  
  1051. prserr: mov sp,comand.cmostp    ; Set new sp to old one.
  1052.     mov bx,offset comand.cmdbuf
  1053.     mov comand.cmcptr,bx    ; Initialize the command pointer.
  1054.     mov comand.cmdptr,bx
  1055.     mov ah,0
  1056.     mov comand.cmaflg,ah    ; Zero the flags.
  1057.     mov comand.cmccnt,ah
  1058.     mov comand.cmsflg,0FFH
  1059.     cmp taklev,0        ; in take cmd?
  1060.     jne prser1        ; yes, don't print prompt
  1061.     mov ah,prstr
  1062.     mov dx,offset crlf
  1063.     int dos
  1064.     mov ah,prstr        ; Print the prompt.
  1065.     mov dx,comand.cmprmp    ; Get the prompt.
  1066.     int dos
  1067. ; Instead return to before the prompt call.
  1068. prser1: jmp comand.cmrprs
  1069. PARSE    ENDP
  1070.  
  1071. ;    FCB must be remembered if found "*" in filename.      [7 start]
  1072. ;    Copy from place addressed by BX to place addressed by DI.
  1073. ;    Also use to get the filename to the FCB from the DTA.
  1074.  
  1075. FCBCPY    PROC    NEAR
  1076.     push    es
  1077.     push    si
  1078.     mov    ax,ds
  1079.     mov    es,ax        ; make sure destination segment is correct
  1080.     mov    ch,0        ; high-order part of length
  1081.     jcxz    fcbcp1        ; zero argument (is this necessary???)
  1082.     mov    si,bx        ; this is source
  1083.     rep    movsb        ; copy the whole thing
  1084. fcbcp1: pop    si
  1085.     pop    es
  1086.     ret            ; and return
  1087. FCBCPY    ENDP
  1088.  
  1089. ; Jumping to this location is like retskp.  It assumes the instruction
  1090. ;   after the call is a jmp addr.
  1091.  
  1092. RSKP    PROC    NEAR
  1093.     pop bp
  1094.     add bp,3
  1095.     push bp
  1096.     ret
  1097. RSKP    ENDP
  1098.  
  1099. ; Jumping here is the same as a ret.
  1100.  
  1101. R    PROC    NEAR
  1102.     ret
  1103. R    ENDP
  1104.  
  1105. code    ends
  1106.     end
  1107.