home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix CD 2.0
/
Phoenix_CD.cdr
/
01e
/
msk230s1.zip
/
MSSCMD.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-02-12
|
43KB
|
942 lines
NAME msscmd
; File MSSCMD.ASM
; Edit history:
; Last edit 1 Jan 1988
; 1 Jan 1988 version 2.30
; 8 Oct 1987 Add syntax of "\;" is a literal semicolon and not a comment
; introducer (; prints as space, \; prints as ;) but only when doing a
; TAKE file or macro. [jrd]
; 28 Aug 1987 Show Kermit prompt when in Take file and echoing Take cmd. [jrd]
; 18 Aug 1987 Change ESC to escape, for MASM 4.5+ [jrd]
; 27 June 1987 Add allowance for bare c/r's (comand.cmcr != 0) in cminbf.
; Add global byte "intake" to say if reading from Take file (non-zero). [jrd]
; 1 Oct 1986 Version 2.29a
; 20 August 1986 Protect against buffer overflow and stop deleting of prompt
; 16 August 1986 Remove unneeded buffer tbuff. [jrd]
; 22 May 1986 Echo tabs as just a space, avoids corrupted cmd line. [jrd]
; [2.29] code frozen on 6 May 1986 [jrd]
public comnd, cmcfrm, prserr, repars, cmgtch, comand
public cmgetc, intake
include mssdef.h
datas segment public 'datas'
extrn flags:byte, trans:byte
extrn taklev:byte, takadr:word, dosnum:byte
comand cmdinfo <>
cmer00 db cr,lf,'?Program error Invalid COMND call$'
cmer03 db cr,lf,'?Invalid command$'
cmer04 db cr,lf,'?Invalid command or operand$'
cmin00 db ' Confirm with carriage return$'
cmin01 db ' One of the following:',cr,lf,'$'
cmthlp dw 0 ; Text ptr to help message for cmds
crlf db cr,lf,'$'
ctcmsg db '^C$'
prsp db ' $' ; Print a space.
hlpmsg dw 0 ; Address of help message.
escspc db BS,' ',BS,'$' ; Clear escape.
clrspc db ' ',BS,'$' ; Clear space.
temp db ? ; temp (counts char/line so far)
cmdstk dw ?
intake db ? ; last command line was from Take
prevch db 0 ; previous char read by cmgetc
noparse db 0 ; semicolons not special, if non-zero
datas ends
code segment public 'code'
extrn dodel:near, ctlu:near, cmblnk:near, locate:near, takrd:near
extrn clearl:near
assume cs:code, ds:datas, es:datas
; This routine parses the specified function in AH. Any additional
; information is in DX and BX.
; Returns +1 on success
; +4 on failure (assumes a JMP follows the call)
CMND PROC NEAR
comnd: mov comand.cmstat,ah ; Save what we are presently parsing.
mov cmdstk,sp ; save stack ptr locally.
mov prevch,0 ; clear old previous char
mov noparse,0 ; say recognize semicolons in Take files
call cminbf ; Get chars until an action or a erase char
mov ah,comand.cmstat ; Restore 'ah' for upcoming checks.
cmp ah,cmcfm ; Parse a confirm?
jz cmcfrm ; Go get one.
cmp ah,cmkey ; Parse a keyword?
jnz cm3
jmp cmkeyw ; Try and get one.
cm3: cmp ah,cmtxt ; Parse arbitrary text.
jnz cm4
jmp cmtext
cm4: cmp ah,cmfile ; parse text surrounded by whitespace
jnz cm5
jmp cmfil0
cm5: mov ah,prstr ; Else give error
mov dx,offset cmer00 ; "?Unrecognized COMND call"
int dos
ret
; This routine gets a confirm.
cmcfrm: call cmgtch ; Get a char.
cmp ah,0 ; Is it negative? (a terminator; a space or
; a tab will not be returned here as they
; will be seen as leading white space.)
js cmcfr0
mov comand.cmstat,cmcfm-1 ; make sure status isn't = cmcfm
ret ; If not, return failure.
cmcfr0: and ah,7FH ; Turn off the minus bit.
cmp ah,escape ; Is it an escape?
jne cmcfr2
mov ah,conout
mov dl,bell ; Get a bell.
int dos
mov comand.cmaflg,0 ; Turn off the action flag.
mov bx,comand.cmcptr ; Move pointer to before the escape.
dec bx
mov comand.cmcptr,bx
mov comand.cmdptr,bx
dec comand.cmccnt ; Decrement the char count.
jmp cmcfrm ; Try again.
cmcfr2: cmp ah,'?' ; Curious?
jne cmcfr3
mov ah,prstr ; Print something useful.
mov dx,offset cmin00
int dos
mov dx,offset crlf ; Print a crlf.
int dos
mov dx,comand.cmprmp ; Reprint the prompt.
int dos
mov bx,comand.cmdptr ; Get the pointer into the buffer.
mov byte ptr[bx],'$' ; Put a $ there for printing.
dec comand.cmcptr ; Decrement & save the buffer pointer
mov dx,offset comand.cmdbuf
int dos
mov comand.cmaflg,0 ; Turn off the action flag.
jmp repars ; Reparse everything.
cmcfr3: cmp ah,ff ; Is it a form feed?
jne cmcfr4
call cmblnk ; If so blank the screen.
cmcfr4: jmp rskp
; This routine parses a keyword from the table pointed
; to in DX. The format of the table is as follows:
;
; addr: db n ; Where n is the # of entries in the table.
; db m ; M is the size of the keyword.
; db 'string$' ; Where string is the keyword.
; dw ab ; Where ab is data to be returned.
;
; The keywords must be in alphabetical order,
; but they may be of mixed case. [jrd]
cmkeyw: mov comand.cmhlp,bx ; Save the help.
mov comand.cmptab,dx ; Save the beginning of keyword table
mov bx,dx
mov ch,[bx] ; Get number of entries in table.
inc bx
mov dx,comand.cmdptr ; Save command pointer.
mov comand.cmsptr,dx ; Save pointer's here.
cmky1: cmp ch,0 ; Any commands left to check?
jne cmky2
jmp cmky41 ; no, go complain
cmky2: dec ch
mov cl,0 ; Keep track of how many chars read in so far
call cmgtch ; Get a char from the user
cmp ah,0 ; Do we have a terminator?
jns cmky2x ; ns = no
jmp cmky4 ; Negative number means we do.
cmky2x: inc bx ; Point to first letter of keyword.
inc cl ; count the user's char
mov al,[bx]
call tolowr ; convert al (key) and ah (user)
cmp ah,al ; do they match?
je cmky3 ; e = yes
jg cmky2y ; g = keychar < user's (keep looking)
jmp cmky41 ; Fail if ah preceeds al alphabetically
cmky2y: jmp cmky6 ; Not this keyword - try the next.
cmky3: inc bx ; We match here, how 'bout next char?
mov al,[bx]
call tolowr ; lower case the key word char
cmp al,'$' ; End of keyword?
jne cmky3x ; ne = not yet
jmp cmky7 ; Succeed.
cmky3x: mov dl,al ; Save al's char here.
call cmgtch
inc cl ; Read in another char.
mov al,dl
call tolowr ; lower case
cmp ah,escape+80H ; Escape Recognition (escape w/minus bit on)?
je cmky3y
cmp ah,' '+80H ; A space?
je cmky3y
cmp ah,cr+80H ; Carriage return?
je cmky3y
cmp ah,'?'+80H ; A question mark?
je cmky3y
cmp ah,al ; user = keyword char?
je cmky3 ; e = yes. Check next letter
jmp cmky6 ; no. Go to end of keyword and try next
cmky3y: mov comand.cmkptr,bx ; Save bx here.
mov comand.cmsiz,cx ; Save size info.
mov comand.cmchr,ah ; Save char for latter.
cmp ah,'?'+80h ; question mark?
je cmkyj1 ; yes, always print possibilities
call cmambg ; See if input is ambiguous or not.
jmp cmky32 ; Succeeded (not ambiguous).
mov ah,comand.cmchr
cmp ah,escape+80H ; Escape?
je cmky3z
jmp cmky41 ; Else fail.
cmky3z: mov ah,conout ; Ring a bell.
mov dl,bell
int dos
mov bx,comand.cmcptr ; Move pointer to before the escape.
dec bx
mov comand.cmcptr,bx
mov comand.cmdptr,bx
dec comand.cmccnt ; Decrement char count.
mov bx,comand.cmkptr ; Failed - pretend user never typed
mov cx,comand.cmsiz ; ... in a char.
dec cl ; Don't count the escape.
dec bx
mov comand.cmaflg,0 ; Reset the action flag.
jmp cmky3 ; Keep checking.
; Question mark entered by user. Print out all the keywords that match
cmkyj1: mov dx,offset cmin01
mov ah,prstr
int dos
mov temp,0 ; count # chars printed on this line
mov bx,comand.cmkptr ; this is current keyword
mov cx,comand.cmsiz ; we are cl chars into it
mov ch,0
sub bx,cx ; back up to beginning
inc bx ; not counting ?
mov comand.cmkptr,bx ; save beginning of kw
cmkyj2: mov bx,comand.cmkptr ; start of keyword
dec bx
mov al,[bx] ; its length
add temp,al ; count chars printed so far
cmp temp,76 ; will this take us beyond column 78?
jle cmkyj3 ; le = ok so far
mov ah,prstr ; print string
mov dx,offset crlf ; break the line
int dos
mov temp,0 ; and reset the count
cmkyj3: mov dl,spc ; put two spaces before each keyword
mov ah,conout
int dos
inc temp ; count output chars
int dos
inc temp
mov dx,comand.cmkptr ; get current keyword
mov ah,prstr
int dos ; print it
mov bx,comand.cmkptr ; get keyword back
dec bx
mov al,[bx] ; get length
mov ah,0
add ax,5 ; skip length, $, value, next length
add bx,ax ; this is next keyword
mov si,bx
mov di,comand.cmkptr ; compare with last keyword
mov comand.cmkptr,bx ; update this
mov cx,comand.cmsiz
dec ch ; are we at end of table?
jl cmkyj4 ; l = yes, don't go on
mov comand.cmsiz,cx ; else update count
mov ch,0
dec cl ; this includes ?
jcxz cmkyj2 ; empty, just print it
repe cmpsb ; compare to previous string
je cmkyj2 ; same, go print this one
cmkyj4: jmp cmky50 ; else go finish up
cmky32: mov cx,comand.cmsiz ; Restore info.
mov bx,comand.cmkptr ; Our place in the keyword table.
cmp comand.cmchr,' '+80H ; Space?
je cmky35
cmp comand.cmchr,'?'+80H ; Question mark?
je cmky35
cmp comand.cmchr,cr+80H ; Carriage return?
je cmky35
dec comand.cmcptr ; Pointer into buffer of input.
mov dx,comand.cmcptr
cmky33: mov ah,[bx] ; Get next char in keyword.
call tolowr ; convert it to lower case
cmp ah,'$' ; Are we done yet?
jz cmky34
mov di,dx
mov [di],ah
inc bx
inc dx
inc comand.cmccnt
jmp cmky33
cmky34: mov ah,' '
mov di,dx
mov [di],ah ; Put a blank in the buffer.
inc dx
mov cx,comand.cmcptr ; Remember where we were.
mov comand.cmcptr,dx ; Update our pointers.
mov comand.cmdptr,dx
mov ah,'$'
mov di,dx
mov [di],ah ; Add '$' for printing.
mov ah,prstr
mov dx,cx ; Point to beginning of filled in data
int dos
inc bx ; Point to address we'll need.
mov bx,[bx]
mov comand.cmaflg,0 ; Turn off action flag.
jmp rskp
cmky35: inc bx
mov ah,[bx] ; Find end of keyword.
cmp ah,'$'
jne cmky35
inc bx
mov bx,[bx] ; Address of next routine to call.
jmp rskp
cmky4: and ah,7FH ; Turn off minus bit.
cmp ah,'?' ; Need help?
je cmky5
cmp ah,' ' ; Just a space - no error.
je cmky51
cmp ah,cr
je cmky51
cmp ah,tab
je cmky51
cmp ah,escape ; Ignore escape?
je cmky43
cmky41: mov ah,prstr
mov dx,offset cmer03
int dos
jmp prserr ; Parse error - give up.
cmky43: mov ah,conout ; Ring a bell.
mov dl,bell
int dos
dec comand.cmcptr ;[ESC] don't trash BX here.
dec comand.cmdptr ;[ESC] ditto
dec comand.cmccnt ; Don't count the escape.
mov comand.cmaflg,0 ; Reset action flag.
inc ch ; Account for a previous 'dec'.
jmp cmky1 ; Start over.
cmky5: inc bx ; point to actual keyword
mov comand.cmkptr,bx ; remember current kw
mov cl,1 ; code above expects to count '?'
mov comand.cmsiz,cx ; and size
mov dx,comand.cmhlp
or dx,dx ; was any help given?
jnz cmky5a ; yes, use it
jmp cmkyj1 ; else make our own message
cmky5a: mov ah,prstr
int dos
cmky50: mov ah,prstr
mov dx,offset crlf
int dos
mov dx,comand.cmprmp ; Address of prompt.
int dos
mov bx,comand.cmdptr ; Get pointer into buffer.
mov al,'$'
mov [bx],al ; Add dollar sign for printing.
mov dx,offset comand.cmdbuf
int dos
dec comand.cmcptr ; Don't keep it in the buffer.
dec comand.cmccnt ; Don't count it.
mov comand.cmaflg,0 ; Turn off the action flag.
jmp repars
cmky51: cmp comand.cmcr,1 ; Are bare CR's allowed?
je cmky52 ; Yes.
mov ah,prstr
mov dx,offset cmer04 ; Complain.
int dos
cmky52: jmp prserr
cmky6: inc bx ; Find end of keyword.
cmp byte ptr [bx],'$'
jne cmky6
add bx,3 ; Beginning of next command.
mov dx,comand.cmsptr ; Get old cmdptr.
mov comand.cmdptr,dx ; Restore.
mov comand.cmsflg,0FFH
jmp cmky1 ; Keep trying.
cmky7: call cmgtch ; Get char.
cmp ah,0
js cmky71 ; Ok if a terminator.
dec bx
jmp cmky6 ; No match - try next keyword.
cmky71: cmp ah,'?'+80h ; question mark?
jne cmky72 ; yes, don't return yet
inc cl ; count the '?' Fix single char keywords
jmp cmky3y ; and process ? correctly
cmky72: inc bx ; Get necessary data.
mov bx,[bx]
cmp ah,escape+80h ; An escape?
jne cmky73
mov ah,prstr
mov dx,offset prsp ; Print a space.
int dos
mov di,comand.cmcptr
dec di
mov ah,20H
mov [di],ah ; Replace escape char with space.
mov comand.cmaflg,0
mov comand.cmsflg,0FFH ; Pretend they typed a space.
cmky73: jmp rskp
; See if keyword is unambiguous or not from what the user has typed in.
cmambg: cmp ch,0 ; Any keywords left to check?
jne cmamb0
ret ; If not then not ambiguous.
cmamb0: inc bx ; Go to end of keyword ...
mov al,[bx] ; So we can check the next one.
cmp al,'$'
jne cmamb0
add bx,4 ; Point to start of next keyword.
dec cl ; Don't count escape.
mov dx,comand.cmsptr ; Buffer with input typed by user.
cmamb1: mov ah,[bx] ; Keyword char.
mov di,dx
mov al,[di] ; Input char.
call tolowr ; convert to lower case
cmp ah,al ; Keyword bigger than input (alphabetically)?
jle cmamb2 ; No - keep checking.
ret ; Yes - not ambiguous.
cmamb2: inc bx ; Advance one char.
inc dx
dec cl
jnz cmamb1
jmp rskp ; Fail - it's ambiguous.
; Parse arbitrary text up to a CR. Put chars into data buffer sent to
; the host (pointed to by BX). Called with text of help message in DX.
; Produces asciiz string. Return updated pointer in BX and input size in AH.
cmtext: mov comand.cmptab,bx ; Save pointer to data buffer.
mov cmthlp,dx ; Save the help message.
mov cl,0 ; Init the char count.
cmtxt1: mov comand.cmsflg,0 ; Get all spaces.
call cmgtch ; Get a char.
test ah,80H ; is high-order bit on?
jz cmtxt5 ; Nope, put into the buffer.
and ah,07FH
cmp ah,' '
je cmtxt5
cmp ah,escape ; An escape?
jne cmtxt2
mov ah,conout
mov dl,bell ; Ring a bell.
int dos
mov comand.cmaflg,0 ; Reset action flag.
dec comand.cmcptr ; Move pointer to before the escape.
dec comand.cmdptr
dec comand.cmccnt ; Decrement count.
jmp cmtxt1 ; Try again.
cmtxt2: cmp ah,'?' ; Asking a question?
jz cmtx30
cmp ah,FF ; Formfeed?
jne cmtx2x
call cmblnk
cmtx2x: mov ah,cl ; Return count in AH.
mov bx,comand.cmptab ; Return updated pointer.
jmp rskp
cmtxt5: inc cl ; Increment the count.
mov bx,comand.cmptab ; Pointer into destination array.
mov [bx],ah ; Put char into the buffer.
inc bx
mov al,0
mov [bx],al ; insert null terminator
mov comand.cmptab,bx
jmp cmtxt1
cmtx30: mov comand.cmaflg,0 ; Reset action flag to zero.
inc comand.cmdptr ; count the ?
cmp cl,0 ; Is "?" first char?
jne cmtxt5 ; No, just add to buffer.
dec comand.cmcptr ;[ESC] (moved 3 lines) Don't keep in buffer.
dec comand.cmccnt ;[ESC] Don't count it.
dec comand.cmdptr ;[ESC] don't count if printing help.
mov ah,prstr ; Else, give some help.
mov dx,cmthlp ; Address of help message.
int dos
mov ah,prstr
mov dx,offset crlf ; Print a crlf.
int dos
mov ah,prstr
mov dx,comand.cmprmp ; Reprint the prompt.
int dos
mov bx,comand.cmdptr ; Get the pointer into the buffer.
mov byte ptr [bx],'$'
mov ah,prstr
mov dx,offset comand.cmdbuf
int dos
jmp cmtxt1 ; And keep going.
; [jrd]
; Parse arbitrary text up to whitespace. Put chars into data buffer sent to
; the host (pointed to by DX). Called with text of help message in BX.
; Produces asciiz string. Return updated pointer in DX and input size in AH.
; Skips leading whitespace.
; Does a return skip exit. Replaces old cmifi routine.
cmfil0: push dx
mov dx,bx ; interchange bx and bx internally
pop bx
mov comand.cmptab,bx ; Save pointer to data buffer.
mov cmthlp,dx ; Save the help message.
mov cl,0 ; Init the char count.
mov comand.cmsflg,0ffH ; skip over leading spaces and tabs.
cmfil1: call cmgtch ; Get a char.
test ah,80H ; is high-order bit on (i.e. terminator seen)?
jnz cmfi1a ; nz = yes
jmp cmfil5 ; z = no, put char into the buffer.
cmfi1a: and ah,07FH ; clear high order bit
cmp ah,escape ; An escape?
je cmfi1b ; e = yes.
cmp ah,' ' ; is it a space or control char?
jg cmfil2 ; g = no. keep it
jmp cmfi2x ; else, a space or control char; end here.
cmfi1b: mov ah,conout ; handle escape char; ie, complain
mov dl,bell ; Ring a bell.
int dos
mov comand.cmaflg,0 ; Reset action flag.
dec comand.cmcptr ; Move pointer to before the escape.
dec comand.cmdptr
dec comand.cmccnt ; Decrement count.
jmp cmfil1 ; Try again.
cmfil2: cmp ah,'?' ; Asking a question?
jz cmfil3 ; z = yes
cmp ah,ff ; Formfeed?
jne cmfi2x ; ne = no
call cmblnk ; a FF. clear the command line and end
cmfi2x: mov bx,comand.cmptab ; Pointer into destination array.
mov byte ptr[bx],0 ; Put null terminator into the buffer
inc bx
mov ah,cl ; Return count in AH.
mov dx,comand.cmptab ; Return updated pointer.
xchg dx,bx ; re-interchange bx and dx
jmp rskp
cmfil3: mov comand.cmaflg,0 ; Reset action flag to zero.
inc comand.cmdptr ; count the ?
cmp cl,0 ; Is "?" first char?
jne cmfil5 ; No, just add to buffer.
dec comand.cmcptr ;[ESC] (moved 3 lines) Don't keep in buffer.
dec comand.cmccnt ;[ESC] Don't count it.
dec comand.cmdptr ;[ESC] don't count if displaying help.
mov ah,prstr ; Else, give some help.
mov dx,cmthlp ; Address of help message.
int dos
mov dx,offset crlf ; Print a crlf.
int dos
mov dx,comand.cmprmp ; Reprint the prompt.
int dos
mov bx,comand.cmdptr ; Get the pointer into the buffer.
mov byte ptr [bx],'$'
mov dx,offset comand.cmdbuf
int dos
jmp cmfil1 ; And keep going.
cmfil5: inc cl ; Increment the count.
mov bx,comand.cmptab ; Pointer into destination array.
mov [bx],ah ; Put char into the buffer.
inc bx
mov comand.cmptab,bx
jmp cmfil1 ; the end of cmfil0.
cmgetc: mov ah,taklev ; get current Take level
mov intake,ah ; remember here for later callers
cmp ah,0 ; in a Take file?
jne cmget1 ; ne = yes
jmp cmge10 ; no take file, get from keyboard
cmget1: push bx
push si
mov bx,takadr
mov ax,[bx].takcnt ; size of item
or ax,[bx].takcnt+2 ; empty?
jnz cmget5 ; nz = no
cmget2: mov al,byte ptr [bx].taktyp ; get type of take
cmp al,0ffh ; is it really a macro?
je cmget4 ; yes, better not try to close it
mov bx,word ptr [bx].takhnd ; get file handle
mov ah,close2 ; use 2.0 close
int dos
cmget4: dec taklev
sub takadr,size takinfo
pop si
pop bx
mov al,cr ; end with carriage return...
mov prevch,al ; remember last read character
mov noparse,0
ret
cmget5: cmp [bx].takchl,0 ; Any chars left in buffer?
jne cmget6 ; ne = yes
call takrd ; else read another buffer
cmp [bx].takchl,0 ; anything in the file?
je cmget2 ; e = no, quit
cmget6: dec [bx].takchl
sub [bx].takcnt,1 ; DEC doesn't set carry!!
sbb [bx].takcnt+2,0
mov si,[bx].takptr
lodsb
mov [bx].takptr,si
cmp al,ctlz ; maybe control-z?
je cmget2 ; yes, close take file (has to be before pops)
pop si
pop bx
cmp al,lf ; linefeed?
jne cmget7
mov prevch,al ; remember last read character
jmp cmgetc ; yes, ignore it.
cmget7: cmp al,';' ; maybe a semicolon?
jne cmget7c ; ne = no, accept as-is
cmp prevch,5ch ; was previous char backslash escape?
jne cmget9 ; ne = no, semicolon starts a comment
cmp noparse,0 ; parsing this part of the command?
jne cmget7a ; ne = no, observe but do not store
pop bx
mov bx,comand.cmcptr ; Get the pointer into the cmd buffer.
mov byte ptr[bx-1],al ; stuff in the literal semicolon
pop bx
cmget7a:mov prevch,al ; remember last read character
cmp flags.takflg,0 ; echoing take files?
je cmget7b ; e = no
push dx ; backspace cursor over backslash
push ax ; and print the semicolon
mov ah,conout
mov dl,BS
int dos
mov dl,al
int dos
pop ax
cmget7b:pop dx
jmp cmgetc ; get next char
cmget7c:mov prevch,al ; normal character acceptance pathway
cmp flags.takflg,0 ; Echo contents of take file?
je cmget8 ; e = no
push dx
mov dl,al
mov ah,conout
int dos
pop dx
cmget8: ret ; else just return...
; semicolon seen, echo and ignore chars until cr
cmget9: push ax
mov al,spc ; replace semicolon with a space
call cmget7c ; echo the char
pop ax
cmget9a:mov prevch,al ; remember last read character
mov noparse,1 ; defeat semicolon parsing
call cmgetc ; get a character
cmp al,cr ; carriage return?
jne cmget9a ; no, keep reading
mov prevch,al ; remember last read character
mov noparse,0 ; done with escaped semicolon actions
ret ; else return it
cmge10: mov ah,coninq ; Get a char.
int dos
or al,al
jnz cmge11 ; ignore null bytes of special keys
int dos ; read and discard scan code byte
jmp cmge10 ; try again
cmge11: and al,7fh ; only allow 7-bit characters.
push ax ; save the char
cmp al,del
je cmgex
cmp al,' ' ; printable?
jae cmge12 ; yes, no translation needed
cmp al,cr ; this is printable
je cmge12
cmp al,lf
je cmge12
cmgex: mov al,' ' ; else echo a space
cmge12: mov dl,al ; put char here
cmp comand.cmquiet,0 ; quiet mode?
jnz cmge13 ; yes, skip echoing...
mov ah,conout
int dos ; echo it ourselves...
cmge13: pop ax ; and return it
cmp al,'C'-40H ; control-C?
je cmge15 ; yes, go handle
cmp al,tab
jne cmge14
mov al,' '
cmge14: ret
cmge15: mov dx,offset ctcmsg
mov ah,prstr
int dos
mov flags.cxzflg,'C' ; remember ^C'd
mov sp,cmdstk ; restore command stack ptr
ret ; and fail
; Come here is user types ^W when during input.
cntrlw: mov ah,prstr
mov dx,offset escspc
int dos
dec comand.cmccnt ; Don't include it in the count.
dec comand.cmcptr ; Back up past the ^W.
mov cl,comand.cmccnt
mov ch,0
jcxz ctlw2
pushf
push es
std ; Scan backward
mov ax,ds
mov es,ax ; Point to the data area.
mov di,comand.cmcptr ; Looking from here.
dec di
mov al,' '
repe scasb ; Look for non-space.
je ctlw1 ; All spaces, nothing else to do
inc di ; move back to non-space
inc cx
repne scasb ; look for a space
jne ctlw1 ; no space, leave ptrs alone
inc di
inc cx ; skip back over space
ctlw1: inc di
cld ; reset direction flag
mov comand.cmccnt,cl ; update count
mov cx,comand.cmcptr ; remember old ptr
mov comand.cmcptr,di ; update pointer
sub cx,di ; this is characters moved
mov dl,BS ; output backspaces
mov ah,conout
ctlw3: int dos ; backup cursor
loop ctlw3
call clearl ; clear line
pop es
popf
ret ; and return
ctlw2: mov ah,conout
mov dl,bell
int dos
ret
cminbf: push dx
push bx
mov cx,dx ; Save value here too.
cmp comand.cmaflg,0 ; Is the action char flag set?
je cminb1
jmp cminb9 ; If so get no more chars.
cminb1: cmp comand.cmccnt,size cmdbuf ; max buffer size
jb cminb1a ; b = not full
push ax ; full.
push dx
mov ah,conout ; complain
mov dl,bell
int dos
pop dx
pop ax
jmp cminb6 ; set action flag
cminb1a:inc comand.cmccnt ; Increment the char count.
call cmgetc
mov ah,al ; Keep char in 'ah'.
mov bx,comand.cmcptr ; Get the pointer into the buffer.
mov [bx],ah ; Put it in the buffer.
inc bx
mov comand.cmcptr,bx
cmp ah,'W'-64 ; Is it a ^W?
jne cmnb11
call cntrlw ; Kill the previous word.
jmp repars
cmnb11: cmp ah,25O ; Is it a ^U?
jne cminb2
cmnb12: call ctlu ; Clear out the line.
mov ah,prstr
mov dx,comand.cmprmp ; Print the prompt.
int dos
mov bx,offset comand.cmdbuf
mov comand.cmcptr,bx ; Reset the point to the start.
mov comand.cmccnt,0 ; Zero the count.
mov dx,cx ; Preserve original value of dx.
jmp repars ; Go start over.
cminb2: cmp ah,bs ; Or backspace?
jz cminb3
cmp ah,del ; Delete?
jne cminb4
cminb3: mov ah,comand.cmccnt ; Decrement the char count by two (char + BS)
dec ah
dec ah
cmp ah,0 ; Have we gone too far?
jns cmnb32 ; If not proceed.
mov ah,conout ; Ring the bell.
mov dl,bell
int dos
jmp cmnb12 ; Go reprint prompt and reparse.
cmnb32: mov comand.cmccnt,ah ; Save the new char count.
call dodel ; Delete a character.
mov ah,prstr ; Erase the character.
mov dx,offset clrspc
int dos
dec comand.cmcptr ; Get the pointer into the buffer.
dec comand.cmcptr ; Back up in the buffer.
cmnb34: jmp repars ; Go reparse everything.
cminb4: cmp ah,'?' ; Is it a question mark.
jz cminb6
cmp ah,escape ; Is it an escape?
jz cminb8
cmp ah,cr ; Is it a carriage return?
jz cminb5
cmp ah,lf ; Is it a line feed?
jz cminb5
cmp ah,ff ; Is it a formfeed?
jne cminb7
call cmblnk ; FF: clear the screen and
call locate ; Home the cursor.
push bx ; make the FF parse like a cr
mov bx,comand.cmcptr ; permanent storage of next char
mov byte ptr [bx-1],cr ; pretend a carriage return were typed
pop bx
cminb5: cmp comand.cmccnt,1 ; Have we parsed any chars yet?
jnz cminb6
cmp comand.cmcr,0 ; bare cr's allowed?
jne cminb6 ; ne = yes
jmp prserr ; If not, just start over.
cminb6: mov comand.cmaflg,0FFH ; Set the action flag.
jmp cminb9
cminb7: jmp cminb1 ; Get another char.
cminb8: mov ah,prstr ; Don't print the escape char.
mov dx,offset escspc
int dos
jmp cminb6
cminb9: pop bx
pop dx
ret
cmgtch: push cx
push bx
push dx
cmgtc1: cmp comand.cmaflg,0 ; is action flag set?
jne cmgt10
call cminbf ; If the action char flag is not set get more.
cmgt10: mov bx,comand.cmdptr ; Get a pointer into the buffer.
mov ah,[bx] ; Get the next char.
inc bx
mov comand.cmdptr,bx
cmp ah,' ' ; Is it a space?
jz cmgtc2
cmp ah,tab ; Or a tab?
jne cmgtc3
cmgtc2: cmp comand.cmsflg,0 ; space flag, was last char a space?
jne cmgtc1 ; Yes, get another char.
mov comand.cmsflg,0FFH ; Set the space flag.
mov ah,' '
pop dx
pop bx
jmp cmgtc5
cmgtc3: mov al,0
mov comand.cmsflg,al ; Zero the space flag.
pop dx
pop bx
cmp ah,escape
jz cmgtc5
cmp ah,'?' ; Is the user curious?
jz cmgtc4
cmp ah,cr
jz cmgtc4
cmp ah,lf
jz cmgtc4
cmp ah,ff
je cmgtc4
pop cx
ret ; Not an action char, just return.
cmgtc4: dec comand.cmdptr
cmgtc5: or ah,80H ; Make the char negative to indicate
pop cx
ret ; it is a terminator.
CMND ENDP
; This address is jumped to on reparse.
PARSE PROC NEAR
repars: mov sp,comand.cmostp ; new sp <-- old sp
mov bx,offset comand.cmdbuf
mov comand.cmdptr,bx
mov comand.cmsflg,0ffh
jmp comand.cmrprs ; go back to reparse address
; This address can be jumped to on a parsing error.
prserr: mov sp,comand.cmostp ; Set new sp to old one.
mov bx,offset comand.cmdbuf
mov comand.cmcptr,bx ; Initialize the command pointer.
mov comand.cmdptr,bx
mov ah,0
mov comand.cmaflg,ah ; Zero the flags.
mov comand.cmccnt,ah
mov comand.cmsflg,0FFH
cmp taklev,0 ; in take cmd?
je prser2 ; e = no
cmp flags.takflg,0 ; echo contents of take file?
je prser1 ; e = no
prser2: mov ah,prstr
mov dx,offset crlf
int dos
mov ah,prstr ; Print the prompt.
mov dx,comand.cmprmp ; Get the prompt.
int dos
; Instead return to before the prompt call.
prser1: jmp comand.cmrprs
PARSE ENDP
; Convert ascii characters in al and ah to lowercase. [jrd]
; All registers are preserved except AX, of course.
TOLOWR PROC NEAR
test ah,80H ; sign bit set?
jnz tolow1 ; nz = yes
cmp ah,'A' ; less that cap A?
jl tolow1 ; l = yes. leave untouched
cmp ah,'Z'+1 ; more than cap Z?
jns tolow1 ; ns = yes.
or ah,20H ; convert to lowercase
tolow1: test al,80H ; sign bit set?
jnz tolow2 ; nz = yes
cmp al,'A' ; less that cap A?
jl tolow2 ; l = yes. leave untouched
cmp al,'Z'+1 ; more than cap Z?
jns tolow2 ; ns = yes.
or al,20H ; convert to lowercase
tolow2: ret
TOLOWR endp
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
code ends
end