home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
modem
/
cp405src.ark
/
CP4CMD.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-12-25
|
23KB
|
884 lines
; CP4CMD.ASM
; KERMIT - (Celtic for "FREE")
;
; This is the CP/M-80 implementation of the Columbia University
; KERMIT file transfer protocol.
;
; Version 4.0
;
; Copyright June 1981,1982,1983,1984,1985
; Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others.
;
; This file provides a user oriented way of parsing commands.
; It is similar to that of the COMND JSYS in TOPS-20.
;
; revision history (latest first):
; edit 5: 6-Feb-85 by Charles Carvalho
; Make ffussy a runtime (rather than assembly-time) switch, to
; eliminate conditional assembly in system-independent module.
; Don't allow _%|()/\ in filenames if ffussy set; my CP/M manual
; disallows those, too.
;
; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
;
;pcc006 2-jan-85 VJC modules:cp4cmd,cp4utl
; Problems with "?" in filespecs. On reparse, may cause action
; flag to be reset at wrong point, requiring multiple <CR>'s
; to terminate the line or other weird stuff. Also need to
; check flag and complain if wild-cards illegal.
;pcc007 2-Jan-85 vjc modules:cp4def,cp4cmd
; Cmifil is too fussy about what characters to accept in a
; filespec. My CP/M manual says any printable character is ok
; except <>.,;:?*[], and lower case. In practice, even those work
; sometimes. Kermit itself uses '&' if file warning is on,
; and then won't let you reference the file. Allow all
; printable characters except those above. Add conditional
; ffussy, so that if not ffussy, all special characters will be
; allowed, just convert lower to upper-case.
; edit 3: July 8, 1984 (CJC)
; integrate Toad Hall changes for LASM compatibility: CP4CPM is linked
; by CP4WLD, and links CP4UTL.
;
; edit 2: June 5, 1984 (CJC)
; formatting and documentation; delete unnecessary code at cminb7; add
; module version string.
;
; edit 1: May, 1984 (CJC)
; extracted from CPMBASE.M80 version 3.9; modifications are described in
; the accompanying .UPD file.
cmdver: db 'CP4CMD.ASM (5) 6-Feb-85$' ; name, edit number, date
; This routine prints the prompt in DE and specifies the reparse
; address.
; called by: kermit
prompt: pop h ;Get the return address.
push h ;Put it on the stack again.
shld cmrprs ;Save it as the address to go to on reparse.
lxi h,0 ;Clear out hl pair.
dad sp ;Get the present stack pointer.
shld cmostp ;Save for later restoral.
xchg ;Save the pointer to the prompt.
shld cmprmp
xchg
lxi h,cmdbuf
shld cmcptr ;Initialize the command pointer.
shld cmdptr
xra a
sta cmaflg ;Zero the flags.
sta cmccnt
mvi a,0FFH ;Try it this way (Daphne.)
sta cmsflg
call prcrlf ;Print a CR/LF [Toad Hall]
jmp prprmp ;Print the prompt. [Toad Hall]
;
; This address is jumped to on reparse.
; here from: cmcfrm, cmkeyw, cmifil, cminbf
repars: lhld cmostp ;Get the old stack pointer.
sphl ;Make it the present one.
lxi h,cmdbuf
shld cmdptr
mvi a,0FFH ;Try it this way (Daphne.)
sta cmsflg
lhld cmrprs ;Get the reparse address.
pchl ;Go there.
; This address can be jumped to on a parsing error.
; here from: cmkeyw, cminbf
prserr: lhld cmostp ;Get the old stack pointer.
sphl ;Make it the present one.
lxi h,cmdbuf
shld cmcptr ;Initialize the command pointer.
shld cmdptr
xra a
sta cmaflg ;Zero the flags.
sta cmccnt
mvi a,0FFH ;Try it this way (Daphne.)
sta cmsflg
call prcrlf ;Print a CR/LF [Toad Hall]
call prprmp ;Print the prompt [Toad Hall]
;* Instead return to before the prompt call.
lhld cmrprs
pchl
;
; This routine parses the specified function in A. Any additional
; information is in DE and HL.
; Returns +1 on success
; +4 on failure (assumes a JMP follows the call)
; called by: log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd
comnd: sta cmstat ;Save what we are presently parsing.
call cminbf ;Get chars until an action or a erase char.
cpi cmcfm ;Parse a confirm?
jz cmcfrm ;Go get one.
cpi cmkey ;Parse a keyword?
jz cmkeyw ;Try and get one.
cpi cmifi ;Parse an input file spec?
jz cmifil ;Go get one.
cpi cmifin ;Input file-spec silent?
jz cmifil ;do as he wishes
cpi cmofi ;Output file spec?
jz cmofil ;Go get one.
cpi cmtxt ;Parse arbitrary text?
jz cmtext ;Go do it.
lxi d,cmer00 ;"?Unrecognized COMND call"
call prtstr
ret
;
; This routine parses arbitrary text up to a CR.
; Accepts DE: address to put text
; Returns in A: number of chars in text (may be 0)
; DE: updated pointer
; called by: comnd
cmtext: xchg ;Put the pointer to the dest in HL.
shld cmptab ;Save the pointer.
mvi b,0 ;Init the char count
cmtxt1: call cmgtch ;Get a char.
ora a ;Terminator?
jp cmtxt5 ;No, put in user space.
ani 7FH ;Turn off minus bit.
cpi esc ;An escape?
jnz cmtxt2 ;No.
mvi c,conout
mvi e,bell ;Get a bell.
call bdos
xra a
sta cmaflg ;Turn off the action flag.
lhld cmcptr ;Move the pointer to before the escape.
dcx h
shld cmcptr
shld cmdptr
lxi h,cmccnt ;Get the char count.
dcr m ;Decrement it by one.
jmp cmtxt1 ;Try again.
cmtxt2: cpi '?' ;Is it a question mark?
jz cmtxt3 ;If so put it in the text.
cpi ff ;Is it a formfeed?
cz clrtop ;If so blank the screen.
mov a,b ;Return the count.
lhld cmptab ;Return updated pointer in HL.
xchg
jmp rskp ;Return success.
cmtxt3: lxi h,cmaflg ;Point to the action flag.
mvi m,0 ;Set it to zero.
cmtxt5: inr b ;Increment the count.
lhld cmptab ;Get the pointer.
mov m,a ;Put the char in the array.
inx h
shld cmptab ;Save the updated pointer.
jmp cmtxt1 ;Get another char.
;
; This routine gets a confirm.
; called by: comnd
cmcfrm: call cmgtch ;Get a char.
ora a ;Is it negative (a terminator;a space or
;a tab will not be returned here as they
;will be seen as leading white space.)
rp ;If not, return failure.
ani 7FH ;Turn off the minus bit.
cpi esc ;Is it an escape?
jnz cmcfr2
mvi c,conout
mvi e,bell ;Get a bell.
call bdos
xra a
sta cmaflg ;Turn off the action flag.
lhld cmcptr ;Move the pointer to before the escape.
dcx h
shld cmcptr
shld cmdptr
lxi h,cmccnt ;Get the char count.
dcr m ;Decrement it by one.
jmp cmcfrm ;Try again.
cmcfr2: cpi '?' ;Curious?
jnz cmcfr3
lxi d,cmin00 ;Print something useful.
call prtstr
call prcrlf ;Print a crlf. [Toad Hall]
call prprmp ;Reprint the prompt [Toad Hall]
lhld cmdptr ;Get the pointer into the buffer.
mvi a,'$' ;Put a $ there for printing.
mov m,a
lhld cmcptr
dcx h ;Decrement and save the buffer pointer.
shld cmcptr
lxi d,cmdbuf
call prtstr
xra a ;Turn off the action flag.
sta cmaflg
jmp repars ;Reparse everything.
cmcfr3: cpi ff ;Is it a form feed?
cz clrtop ;If so blank the screen.
jmp rskp
;
; This routine parses a keyword from the table pointed
; to in DE. 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.
; db a,b ;Where a & b are pieces of data
; ;to be returned. (Must be two of them.)
;
; The keywords must be in alphabetical order.
;**** Note: The data value a is returned in registers A and E. The
;**** data value b is returned in register D. This allows the two data
; bytes to be stored as:
; dw xxx
; and result in a correctly formatted 16-bit value in register pair
; DE.
; called by: comnd
cmkeyw: shld cmhlp ;Save the help.
xchg ;Get the address of the table.
shld cmptab ;Save the beginning of keyword tab for '?'.
mov b,m ;Get the number of entries in the table.
inx h
shld cmkptr
lhld cmdptr ;Save the command pointer.
shld cmsptr
cmkey2: mov a,b ;Get the number of entries left.
ora a ;Any left?
rz ;If not we failed.
lhld cmkptr
mov e,m ;Get the length of the keyword.
inx h
cmkey3: dcr e ;Decrement the number of chars left.
mov a,e
cpi 0FFH ;Have we passed the end?
jm cmkey5 ;If so go to the next.
call cmgtch ;Get a char.
ora a ;Is it a terminator?
jp cmkey4 ;If positive, it is not.
ani 7FH ;Turn off the minus bit.
cpi '?'
jnz cmky31
xra a
sta cmaflg ;Turn off the action flag.
lxi h,cmccnt ;Decrement the char count.
dcr m
;* Must go through the keyword table and print them.
lhld cmhlp ;For now print the help text.
xchg
call prtstr
call prcrlf ;Print a crlf [Toad Hall]
call prprmp ;Reprint the prompt [Toad Hall]
lhld cmdptr ;Get the pointer into the buffer.
mvi a,'$' ;Put a $ there for printing.
mov m,a
lhld cmcptr
dcx h ;Decrement and save the buffer pointer.
shld cmcptr
lxi d,cmdbuf
call prtstr
jmp repars ;Reparse everything.
cmky31: cpi esc ;Is it an escape?
jnz cmky35
xra a
sta cmaflg ;Turn off the action flag.
push d
push b
push h
call cmambg
jmp cmky32 ;Not ambiguous.
mvi c,conout
mvi e,bell
call bdos ;Ring the bell.
lhld cmcptr ;Move the pointer to before the escape.
dcx h
shld cmcptr
shld cmdptr
lxi h,cmccnt ;Get the char count.
dcr m ;Decrement it by one.
pop h
pop b
pop d
inr e ;Increment the left to parse char count.
jmp cmkey3
cmky32: lhld cmcptr ;Pointer into buffer.
dcx h ;Backup to the escape.
xchg
pop h
push h
cmky33: mov a,m ;Get the next char.
cpi '$' ;Finished?
jz cmky34
inx h
xchg
mov m,a ;Move it into the buffer.
inx h
xchg
lda cmccnt ;Increment the char count.
inr a
sta cmccnt
jmp cmky33
cmky34: lda cmccnt ;Get the character count.
inr a ;Increment and save it.
sta cmccnt
xchg ;Put the command buffer pointer in HL.
mvi a,' ' ;Get a blank.
mov m,a ;Put it in the command buffer.
inx h ;Increment the pointer
shld cmcptr ;Save the updated pointer.
shld cmdptr
pop h
push h
xchg
call prtstr ;Print the rest of the keyword.
mvi c,conout
mvi e,' '
call bdos ;Print a blank.
pop h
pop b
pop d
jmp cmky37
cmky35: push h
push d
call cmambg
jmp cmky36
lxi d,cmer01
call prtstr ;Say its ambiguous.
jmp prserr ;Give up.
cmky36: pop d
pop h
cmky37: inr e ;Add one incase it is negative.
mvi d,0
dad d ;Increment past the keyword.
inx h ;Past the $.
mov e,m ;Get the data.
inx h
mov d,m
mov a,e
jmp rskp
cmkey4: cpi 'a' ;Is it less than a?
jm cmky41 ;If so don't capitalize it.
cpi 'z'+1 ;Is it more than z?
jp cmky41 ;If so don't capitalize it.
ani 137O ;Capitalize it.
cmky41: mov d,m ;Get the next char of the keyword.
inx h
cmp d ;Match?
jz cmkey3 ;If so get the next letter.
cmkey5: mvi d,0
mov a,e ;Get the number of chars left.
ora a ;Is it negative?
jp cmky51
mvi d,0FFH ;If so, sign extend.
cmky51: dad d ;Increment past the keyword.
lxi d,0003H ;Plus the $ and data.
dad d
shld cmkptr
dcr b ;Decrement the number of entries left.
lhld cmsptr ;Get the old cmdptr.
shld cmdptr ;Restore it.
;* check so we don't pass it.
jmp cmkey2 ;Go check the next keyword.
;
; Test keyword for ambiguity.
; returns: nonskip if ambiguous, skip if OK.
; called by: cmkeyw
cmambg: dcr b ;Decrement the number of entries left.
rm ;If none left then it is not ambiguous.
inr e ;This is off by one;adjust.
mov c,e ;Save the char count.
mov a,e
ora a ;Any chars left?
rz ;No, it can't be ambiguous.
mvi d,0
dad d ;Increment past the keyword.
mvi e,3 ;Plus the $ and data.
dad d
mov b,m ;Get the length of the keyword.
inx h
xchg
lhld cmkptr ;Get pointer to keyword entry.
mov a,m ;Get the length of the keyword.
sub c ;Subtract how many left.
mov c,a ;Save the count.
cmp b
jz cmamb0
rp ;If larger than the new word then not amb.
cmamb0: lhld cmsptr ;Get the pointer to what parsed.
cmamb1: dcr c ;Decrement the count.
jm rskp ;If we are done then it is ambiguous.
xchg ;Exchange the pointers.
mov b,m ;Get the next char of the keyword
inx h
xchg ;Exchange the pointers.
mov a,m ;Get the next parsed char.
inx h
cpi 'a' ;Is it less than a?
jm cmamb2 ;If so don't capitalize it.
cpi 'z'+1 ;Is it more than z?
jp cmamb2 ;If so don't capitalize it.
ani 137O
cmamb2: cmp b ;Are they equal?
rnz ;If not then its not ambiguous.
jmp cmamb1 ;Check the next char.
;
; cmofil - parse output filespec
; cmifil - parse input filespec
; here from: comnd
cmofil: mvi a,0 ;Don't allow wildcards.
; jmp cmifil ;For now, the same as CMIFI.
cmifil: sta cmfwld ;Set wildcard flag
xchg ;Get the fcb address.
shld cmfcb ;Save it.
mvi e,0 ;Initialize char count.
mvi m,0 ;Set the drive to default to current.
inx h
shld cmfcb2
xra a ;Initialize counter.
cmifi0: mvi m,' ' ;Blank the FCB.
inx h
inr a
cpi 0CH ;Twelve?
jm cmifi0
cmifi1: call cmgtch ;Get another char.
ora a ;Is it an action character?
jp cmifi2
ani 7FH ;Turn off the action bit.
cpi '?' ;A question mark?
jnz cmif12
lda cmfwld ;[pcc006] Wildcards allowed?
ora a ;[pcc006]
jz cmif11 ;[pcc006] complain if not
lhld cmdptr ;[jd] Increment buffer pointer
inx h ;[jd] that was decremented in cmgtch
shld cmdptr ;[jd] since we want this chr
lda cmcptr ;[pcc006] get lsb of real input pointer
cmp l ;[pcc006] is this the last chr input?
jnz cmif1a ;[pcc006] no, don't reset action flag
xra a ;[pcc006] yes, reset action flag
sta cmaflg ;[pcc006]
cmif1a: mvi a,'?' ;[pcc006] get it back in A
jmp cmifi8 ;Treat like any other character
cmif12: cpi esc ;An escape?
jnz cmif13
;Try to recognize file-spec a'la TOPS-20
xra a
sta cmaflg ;Turn off the action flag.
lhld cmcptr ;Move the pointer to before the escape.
dcx h
shld cmcptr
shld cmdptr
lxi h,cmccnt ;Get the char count.
dcr m ;Decrement it by one.
mov a,e ;Save character count up to now.
sta temp1
cpi 9 ;Past '.'?
jm cmfrec ;No.
dcr a ;Yes, don't count point.
cmfrec: lhld cmfcb2 ;Fill the rest with CP/M wildcards.
cmfrc1: cpi 11 ;Done?
jp cmfrc2 ;Yes.
mvi m,'?'
inx h
inr a
jmp cmfrc1
cmfrc2: mvi c,sfirst ;Find first matching file?
lhld cmfcb
xchg
call bdos
cpi 0FFH
jz cmfrc9 ;No, lose.
lxi h,fcbblk ;Copy first file spec.
call fspcop
lxi h,fcbblk+10H ;Get another copy (in case not ambiguous).
call fspcop
mvi c,snext ;More matching specs?
lhld cmfcb
xchg
call bdos
cpi 0FFH
jz cmfrc3 ;Only one.
lxi h,fcbblk+10H ;Copy second file spec.
call fspcop
cmfrc3: lxi d,fcbblk ;Start comparing file names.
lxi h,fcbblk+10H
lda temp1 ;Bypass characters typed.
cpi 9 ;Past '.'?
jm cmfrc4 ;No.
dcr a ;Yes, don't count point.
cmfrc4: mvi c,0
cmfrl1: cmp c ;Bypassed?
jz cmfrl2 ;Yes.
inx d
inx h
inr c
jmp cmfrl1 ;Repeat.
cmfrl2: mov a,c ;Get file name characters processed.
cpi 11 ;All done?
jz cmfrc5 ;Yes.
cpi 8 ;End of file name?
jnz cmfrl3 ;No.
lda temp1 ;Exactly at point?
cpi 9
jz cmfrl3 ;Yes, don't output a second point.
mvi a,'.' ;Output separator.
call cmfput
cmfrl3: ldax d ;Get a character from first file spec.
inx d
mov b,m ;Get from second file spec.
inx h
cmp b ;Compare.
jnz cmfrc5 ;Ambiguous.
inr c ;Same, count.
cpi ' ' ;Blank?
jz cmfrl2 ;Yes, don't output.
call cmfput ;Put character into buffer.
jmp cmfrl2 ;Repeat.
cmfrc5: mov a,c ;Get count of characters processed.
sta temp1 ;Save it.
mvi a,'$' ;Get terminator.
call cmfput ;Put it into buffer.
lhld cmdptr ;Output recognized characters.
xchg
mvi c,prstr
call bdos
lhld cmcptr ;Remove terminator from buffer.
dcx h
shld cmcptr
lxi h,cmccnt
dcr m
lda temp1 ;Characters processed.
cpi 11 ;Complete file name.
jz repars ;Yes, don't beep.
cmfrc9: mvi c,conout
mvi e,bell
call bdos ;Ring the bell.
jmp repars
;
; Continue file spec parsing.
cmif13: mov a,e ;It must be a terminator.
ora a ;Test the length of the file name.
jz cmifi9 ;If zero complain.
cpi 0DH
jp cmifi9 ;If too long complain.
jmp rskp ;Otherwise we have succeeded.
cmifi2: cpi '.'
jnz cmifi3
inr e
mov a,e
cpi 1H ;Any chars yet?
jz cmifi9 ;No, give error.
cpi 0AH ;Tenth char?
jp cmifi9 ;Past it, give an error.
mvi c,9H
mvi b,0
lhld cmfcb
dad b ;Point to file type field.
shld cmfcb2
mvi e,9H ;Say we've gotten nine.
jmp cmifi1 ;Get the next char.
cmifi3: cpi ':'
jnz cmifi4
inr e
mov a,e
cpi 2H ;Is it in the right place for a drive?
jnz cmifi9 ;If not, complain.
lhld cmfcb2
dcx h ;Point to previous character.
mov a,m ;Get the drive name.
sui '@' ;Get the drive number.
shld cmfcb2 ;Save pointer to beginning of name field.
dcx h ;Point to drive number.
mov m,a ;Put it in the fcb.
mvi e,0 ;Start character count over.
jmp cmifi1
cmifi4: cpi '*'
jnz cmifi7
lda cmfwld ;Wildcards allowed?
cpi 0
jz cmif11 ;No,complain
mov a,e
cpi 8H ;Is this in the name or type field?
jz cmifi9 ;If its where the dot should be give up.
jp cmifi5 ;Type.
mvi b,8H ;Eight chars.
jmp cmifi6
cmifi5: mvi b,0CH ;Three chars.
cmifi6: lhld cmfcb2 ;Get a pointer into the FCB.
mvi a,'?'
mov m,a ;Put a question mark in.
inx h
shld cmfcb2
inr e
mov a,e
cmp b
jm cmifi6 ;Go fill in another.
jmp cmifi1 ;Get the next char.
cmifi7: cpi '!' ;[pcc007] control chr or space?
jm cmifi9 ;[pcc007] yes, illegal
mov h,a ;[5] stash input char for a bit
lda ffussy ;[5] while we check the fussy flag
ora a ;[5] set the flags accordingly
mov a,h ;[5] restore the input character
jz cmif7a ;[5] if ffussy=0, allow <>.,;:?*[]
;[5] So far, we've eliminated "action characters" (including question),
;[5] period, colon, asterisk, control characters, and space.
;[5] That leaves us %(),/;<=>[\]_| to check for.
cpi '%' ;[5]
jz cmifi9 ;[5]
cpi '(' ;[5]
jz cmifi9 ;[5]
cpi ')' ;[5]
jz cmifi9 ;[5]
cpi ',' ;[pcc007] weed out comma
jz cmifi9 ;[pcc007]
cpi '/' ;[5]
jz cmifi9 ;[5]
cpi '9'+1 ;[pcc007] anything else 21H-39H is ok
jm cmifi8 ;[pcc007] except '*' never gets here
cpi '@' ;[pcc007] all of 3AH-3FH is illegal
jm cmifi9 ;[pcc007]
cpi '[' ;[pcc007] [\] also illegal
jm cmifi8 ;[pcc007]
cpi ']'+1 ;[pcc007]
jm cmifi9 ;[pcc007]
cpi '_' ;[5]
jz cmifi9 ;[5] (If I was doing CP/M, I would have
cpi '|' ;[5] just eliminated all them funny chars
jz cmifi9 ;[5] instead of a random selection)
cmif7a: ;[5]
cpi 'a' ;[pcc007] if not lower case its ok
jm cmifi8 ;[pcc007] (DEL never gets here)
cpi 'z'+1 ;[pcc007] only convert letters
jp cmifi8 ;[pcc007]
ani 137O ;Capitalize.
cmifi8: lhld cmfcb2 ;Get the pointer into the FCB.
mov m,a ;Put the char there.
inx h
shld cmfcb2
inr e
jmp cmifi1
cmifi9: lda cmstat
cpi cmifin ;"silent"?
jz r ;Yes,let him go w/o check
lxi d,cmer02
cmif10: mvi c,prstr
call bdos
ret
cmif11: lxi d,cmer03 ;Complain about wildcards.
jmp cmif10
;
; copy filename from buffer
; called with HL = destination, A = position (0-3) in buffer
; called by: cmifil
fspcop: push psw ;Save A.
lxi d,buff ;Get the right offset in the buffer.
rlc
rlc
rlc
rlc
rlc
add e
inr a ;Bypass drive spec.
mov e,a
mvi b,11 ;Copy file name.
fspcp1: ldax d
inx d
mov m,a
inx h
dcr b
jnz fspcp1
pop psw ;Restore A.
ret
; append character in A to command buffer
; called by: cmifil
cmfput: push h ;Save H.
lhld cmcptr ;Get buffer pointer.
mov m,a ;Store in buffer.
inx h
shld cmcptr
lxi h,cmccnt ;Count it.
inr m
pop h ;Restore H.
ret
;
; Read characters from the command buffer.
; called by: cmtext, cmcfrm, cmkeyw, cmifil
cmgtch: push h
push b
cmgtc1: lda cmaflg
ora a ;Is it set.
cz cminbf ;If the action char flag is not set get more.
lhld cmdptr ;Get a pointer into the buffer.
mov a,m ;Get the next char.
inx h
shld cmdptr
cpi ' ' ;Is it a space?
jz cmgtc2
cpi tab ;Or a tab?
jnz cmgtc3
cmgtc2: lda cmsflg ;Get the space flag.
ora a ;Was the last char a space?
jnz cmgtc1 ;Yes, get another char.
mvi a,0FFH ;Set the space flag.
sta cmsflg
mvi a,' '
pop b
pop h
jmp cmgtc5
cmgtc3: push psw
xra a
sta cmsflg ;Zero the space flag.
pop psw
pop b
pop h
cpi esc
jz cmgtc5
cpi '?' ;Is the user curious?
jz cmgtc4
cpi cr
jz cmgtc4
cpi lf
jz cmgtc4
cpi ff
rnz ;Not an action char, just return.
cmgtc4: push h
lhld cmdptr
dcx h
shld cmdptr
pop h
cmgtc5: ori 80H ;Make the char negative to indicate it is
ret ;a terminator.
;
; Read characters from console into command buffer, processing
; editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del).
; called by: comnd, cmgtch
cminbf: push psw
push d
push h
lda cmaflg ;Is the action char flag set?
ora a
jnz cminb9 ;If so get no more chars.
cminb1: lxi h,cmccnt ;Increment the char count.
inr m
mvi c,conin ;Get a char.
call bdos
lhld cmcptr ;Get the pointer into the buffer.
mov m,a ;Put it in the buffer.
inx h
shld cmcptr
cpi 25O ;Is it a ^U?
jz cmnb12 ;Yes.
cpi 30O ;Is it a ^X?
jnz cminb2
cmnb12: call clrlin ;Clear the line.
call prprmp ;Print the prompt [Toad Hall]
lxi h,cmdbuf
shld cmcptr ;Reset the point to the start.
lxi h,cmccnt ;Zero the count.
mvi m,0
jmp repars ;Go start over.
cminb2: cpi 10O ;Backspace?
jz cminb3
cpi del ;or Delete?
jnz cminb4
call delchr ;Print the delete string.
cminb3: lda cmccnt ;Decrement the char count by two.
dcr a
dcr a
ora a ;Have we gone too far?
jp cmnb32 ;If not proceed.
mvi c,conout ;Ring the bell.
mvi e,bell
call bdos
jmp cmnb12 ;Go reprint prompt and reparse.
cmnb32: sta cmccnt ;Save the new char count.
call clrspc ;Erase the character.
lhld cmcptr ;Get the pointer into the buffer.
dcx h ;Back up in the buffer.
dcx h
shld cmcptr
jmp repars ;Go reparse everything.
cminb4: cpi '?' ;Is it a question mark.
jz cminb6
cpi esc ;Is it an escape?
jz cminb6
cpi cr ;Is it a carriage return?
jz cminb5
cpi lf ;Is it a line feed?
jz cminb5
cpi ff ;Is it a formfeed?
jnz cminb1 ;no - just store it and get another character.
call clrtop
cminb5: lda cmccnt ;Have we parsed any chars yet?
cpi 1
jz prserr ;If not, just start over.
cminb6: mvi a,0FFH ;Set the action flag.
sta cmaflg
jmp cminb9
cminb9: pop h
pop d
pop psw
ret
;
;Little utility to print the prompt. (We do a LOT of these.) [Toad Hall]
;Enters with nothing.
;Destroys HL (and I suppose B and DE and A).
prprmp: lhld cmprmp ;Get the prompt.
xchg
call prtstr
ret
IF lasm
LINK CP4UTL
ENDIF ;lasm [Toad Hall]