2 ; KERMIT - (Celtic for "FREE")
4 ; This is the CP/M-80 implementation of the Columbia University
5 ; KERMIT file transfer protocol.
9 ; Copyright June 1981,1982,1983,1984,1985
12 ; Originally written by Bill Catchings of the Columbia University Center for
13 ; Computing Activities, 612 W. 115th St., New York, NY 10025.
15 ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
16 ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
20 ; This file provides a user oriented way of parsing commands.
21 ; It is similar to that of the COMND JSYS in TOPS-20.
23 ; revision history (latest first):
25 ;edit 13, 17-Jan-1991 by MF. Modified "cmifil" routine to zero the entire
26 ; fcb (not just the extent) to fix a bug in the COPY command which
27 ; prevented successive COPY commands from working properly.
28 ;edit 12, 16-Jan-1991 by MF. Modified routine "cmkeyw" to ignore leading
29 ; spaces/tabs before a keyword. This apparently was the intent in
30 ; "prompt" and "repars" (at least for command-lines) as the variable
31 ; "cmsflg "is set upon command parse and reparse. The intent was ,
32 ; subverted, however, as "cmkeyw" did not reset the flag to ignore
33 ; leading white space for each search thru the key tables (even though
34 ; the buffer pointer to the keyword entered was reset). The fix was
35 ; to reset the "spaces seen" flag (cmsflg) after "cmkey2" so that
36 ; it is reset each time a new table entry is compared to the text
37 ; the user has entered from the keyboard/TAKE-file etc. The upshot
38 ; of all this is that the kluge code in "cminbf" at "cminb0" designed
39 ; to force Kermit to ignore leading white space on command-lines in
40 ; TAKE-files and on the CP/M command-line is no longer needed and,
41 ; therefore, has been eliminated. Also modify "comnd" to expect leading
42 ; spaces for functions other than "get keyword".
43 ;edit 11, 26-Dec-1990 by MF. Modified routines to ignore leading white space
44 ; in lines from TAKE-files as well as during input from the CP/M
45 ; command-line (form-feeds are now considered white space under these
47 ;edit 10, 8-Sep-1990 by Mike Freeman. Modified routines to ignore leading
48 ; spaces/tabs when processing Kermit commands from the CP/M
50 ; Added flag CMBFLG to allow initial word on a command-line
51 ; to be blank (useful for Remote commands such as Remote CWD etc).
52 ; Added flag cmqflg to prevent character-echoing while entering
53 ; commands so Remote CWD etc can have nonechoing password entry.
54 ; edit 9, 15 June, 1987 by OBSchou. Bug fixing to allow a second filename
55 ; (quiet) be entered as d:<blank>. Previous revision put the drive name
56 ; in first character of FCB, I put that character back to a space.
58 ; edit 8, 12 June, 1987 by OBSchou. Addedin code in cmkeyw to print
59 ; 20 lines of help, then pause for a key from the user befor
60 ; proceeding with help.
62 ; edit 7, 11 March, 1987 by OBSchou for Richard Russell, BBC. He writes:
63 ; Bug in cmtext which prevented use of octal characters (\nnn) fixed.
65 ; edit 6, 18 June, 1986 by OBSchou, Loughborough University, Leics. UK
66 ; added code to parse a number from user input. Added check to make
67 ; sure the input command buffer does not overflow the limit.
69 ; edit 5a: 7 March, 1986. OBSchou. Added stuff rom MJ Carter. He writes:
70 ; 7th May 85, MJ Carter [majoc], Nottingham University
71 ; Code in cmifil() put one too many spaces in the FCB; this caused
72 ; the BDOS of the British Micro Mimi to search for exteny 32,
73 ; rather than extent 0, so era() always said "can't find file"
74 ; Puttig a null at the point in question ought to fix 9 it.
76 ; edit 5: 6-Feb-85 by Charles Carvalho
77 ; Make ffussy a runtime (rather than assembly-time) switch, to
78 ; eliminate conditional assembly in system-independent module.
79 ; Don't allow _%|()/\ in filenames if ffussy set; my CP/M manual
80 ; disallows those, too.
82 ; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809
84 ;pcc006 2-jan-85 VJC modules:cp4cmd,cp4utl
85 ; Problems with "?" in filespecs. On reparse, may cause action
86 ; flag to be reset at wrong point, requiring multiple <CR>'s
87 ; to terminate the line or other weird stuff. Also need to
88 ; check flag and complain if wild-cards illegal.
90 ;pcc007 2-Jan-85 vjc modules:cp4def,cp4cmd
91 ; Cmifil is too fussy about what characters to accept in a
92 ; filespec. My CP/M manual says any printable character is ok
93 ; except <>.,;:?*[], and lower case. In practice, even those work
94 ; sometimes. Kermit itself uses '&' if file warning is on,
95 ; and then won't let you reference the file. Allow all
96 ; printable characters except those above. Add conditional
97 ; ffussy, so that if not ffussy, all special characters will be
98 ; allowed, just convert lower to upper-case.
100 ; edit 3: July 8, 1984 (CJC)
101 ; integrate Toad Hall changes for LASM compatibility: CP4CPM is linked
102 ; by CP4WLD, and links CP4UTL.
104 ; edit 2: June 5, 1984 (CJC)
105 ; formatting and documentation; delete unnecessary code at cminb7; add
106 ; module version string.
108 ; edit 1: May, 1984 (CJC)
109 ; extracted from CPMBASE.M80 version 3.9; modifications are described in
110 ; the accompanying .UPD file.
112 cmdver: db 'CPSCMD.ASM (13) 17-Jan-1991$' ; name, edit number, date
114 ; This routine prints the prompt in DE and specifies the reparse
118 prompt: pop h ;Get the return address.
119 push h ;Put it on the stack again.
120 shld cmrprs ;Save it as the address to go to on reparse.
121 lxi h,0 ;Clear out hl pair.
122 dad sp ;Get the present stack pointer.
123 shld cmostp ;Save for later restoral.
124 xchg ;Save the pointer to the prompt.
128 shld cmcptr ;Initialize the command pointer.
131 sta cmaflg ;Zero the flags.
133 ; mvi a,0FFH ;Try it this way (Daphne.)
135 call prcrlf ;Print a CR/LF [Toad Hall]
136 jmp prprmp ;Print the prompt. [Toad Hall]
138 ; This address is jumped to on reparse.
139 ; here from: cmcfrm, cmkeyw, cmifil, cminbf
141 repars: lhld cmostp ;Get the old stack pointer.
142 sphl ;Make it the present one.
145 ; mvi a,0FFH ;Try it this way (Daphne.)
147 lhld cmrprs ;Get the reparse address.
150 ; This address can be jumped to on a parsing error.
151 ; here from: cmkeyw, cminbf
153 prserr: lhld cmostp ;Get the old stack pointer.
154 sphl ;Make it the present one.
156 shld cmcptr ;Initialize the command pointer.
159 sta cmaflg ;Zero the flags.
161 ; mvi a,0FFH ;Try it this way (Daphne.)
163 call prcrlf ;Print a CR/LF [Toad Hall]
164 call prprmp ;Print the prompt [Toad Hall]
165 ;* Instead return to before the prompt call.
169 ; This routine parses the specified function in A. Any additional
170 ; information is in DE and HL.
171 ; Returns +1 on success
172 ; +4 on failure (assumes a JMP follows the call)
173 ; called by: log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd
176 comnd: sta cmstat ;Save what we are presently parsing.
177 call cminbf ;Get chars until an action or a erase char.
178 push psw ;[MF]Save function
179 mvi a,0ffh ;[MF]Expect leading spaces
181 pop psw ;[MF]Restore function
182 cpi cmcfm ;Parse a confirm?
183 jz cmcfrm ;Go get one.
184 cpi cmkey ;Parse a keyword?
185 jz cmkeyw ;Try and get one.
186 cpi cmifi ;Parse an input file spec?
187 jz cmifil ;Go get one.
188 cpi cmifin ;Input file-spec silent?
189 jz cmifil ;do as he wishes
190 cpi cmofi ;Output file spec?
191 jz cmofil ;Go get one.
192 cpi cmtxt ;Parse arbitrary text?
194 cpi cmnum ;[7] Parse a number?
195 jz cmnumb ;[7] go do it
196 lxi d,cmer00 ;"?Unrecognized COMND call"
200 ; This routine parses arbitrary text up to a CR.
201 ; Accepts DE: address to put text
202 ; Returns in A: number of chars in text (may be 0)
203 ; DE: updated pointer
206 cmtext: xra a ; clear counters erc for slashes etc
207 sta slshsn ; if we are in a slash sequence
208 sta slashn ; the octal number being entered
209 sta slashc ; number of characters entered
211 xchg ;Put the pointer to the dest in HL.
212 shld cmptab ;Save the pointer.
213 mvi b,0 ;Init the char count
214 cmtxt1: call cmgtch ;Get a char.
216 jp cmtx3 ;No, put in user space. [rtr] was cmtx5
217 ani 7FH ;Turn off minus bit.
221 mvi e,bell ;Get a bell.
224 sta cmaflg ;Turn off the action flag.
225 lhld cmcptr ;Move the pointer to before the escape.
229 lxi h,cmccnt ;Get the char count.
230 dcr m ;Decrement it by one.
231 jmp cmtxt1 ;Try again.
233 cmtxt2: cpi '?' ;Is it a question mark?
234 jz cmtxt4 ;If so put it in the text. [rtr] was cmtx3
235 cpi ff ;Is it a formfeed?
236 cz clrtop ;If so blank the screen.
237 mov a,b ;Return the count.
238 lhld cmptab ;Return updated pointer in HL.
240 jmp rskp ;Return success.
242 cmtx3: cpi '\' ; slash?
243 jnz cmtx3a ; nope, so try something else
244 lda slshsn ; a slash already entered?
247 jnz cmtx3a ; yes, so assume its a valid slash to enter
248 sta slshsn ; make sure the flag is set for next time routnd
249 jmp cmtxt1 ; get another character
252 ; lxi h,cmaflg ;Point to the action flag.
253 ; mvi m,0 ;Set it to zero.
254 mov e,a ; save it in case we are interpreting a slash
255 lda slshsn ; slash already entered?
257 mov a,e ; restore it in case...
258 jz cmtx5 ; not a slash seen, so enter as a normal character
260 jnz cmtx3b ; \\ not detected
261 lda slashn ; else get number
262 jmp cmtx5b ; and enter it ( in the case of \n or \nn)
263 ; here if an octal number of 1 or 2 digits
264 ; entered instead of 3, followed by \ again
267 sui 30h ; else it should be an octal number
268 jm cmtxt6 ; if not a digit complain
270 jp cmtxt6 ;[rtr] was cmtxt
271 mov e,a ; else add it to the number already entered
275 add a ; multiply by 8
278 lda slashc ; get the count
280 sta slashc ; plus one. If three then a number entered
282 lda slashn ; get the number in case...
284 jmp cmtxt1 ; else loop
286 cmtxt4: lhld cmdptr ;[rtr] Get a pointer into the buffer
287 inx h ;[rtr] Bump past '?'
290 jmp cmtxt1 ; put this into a subroutine
293 call cmtx5c ; here if we see \n\ or \nn\ rather than \nnn\
294 mvi a,'\' ; so send slash number to buffer,
295 sta slshsn ; re-store a slash seen
296 jmp cmtxt1 ; try next one
299 inr b ;Increment the count.
300 lhld cmptab ;Get the pointer.
301 mov m,a ;Put the char in the array.
303 shld cmptab ;Save the updated pointer.
304 xra a ; clear slash counters etc
310 cmtxt6: lxi d,cmer05 ; complain - not a valid \ parameter
312 jmp kermit ; and try another command
313 ds 20h ; for debugging
315 ; This routine gets a number from user input.
318 cmnumb: lxi h,0 ; make sure the number is zero to start with
320 cmnum0: call cmgtch ; get another character
321 ora a ; if negative then its an action
322 jp cmnum1 ; nope, so (possibly) valid input
323 ani 7fh ; else lets see what it is...
324 cpi esc ; do not know what to do with this one...
325 cpi ' ' ; if it is a space then either a return or more
327 jmp rskp ; space is a deliminter
328 dw 0 ; set three bytes aside for a jump/call
329 dw 0 ; and then another three just in case...
330 dw 0 ; making 6 bytes
331 cmnum2: cpi '?' ; user is curious
333 cpi cr ; end of input?
335 gnum1: jmp prserr ; did not under stand this, so error
340 gnum2: lhld number ; get the number.. if at all entered
342 ora h ; if hl = 0 then possibly no number entered
343 lxi d,cmin02 ; say confirm...or more on line
344 jnz gnum21 ; else say enter a return
345 lxi d,cmin01 ; say enter a number
346 gnum21: call prtstr ; say it
347 call prcrlf ; do a lf
348 call prprmp ; another reprompt
349 lhld cmdptr ; get pointer of string already entered
350 mvi m,'$' ; dollar it to set end of line
352 dcx h ; decrement and save the buffer pointer
355 call prtstr ; print what has already been entered
357 sta cmaflg ; turn the action flag off
358 jmp repars ; and try again
360 mvi a,cmcfm ; parse a confirm
365 dw 0 ; some space to patch...
368 cmnum1: ani 7fh ; here for a (potentially) valid number
369 sui '0' ; less ascii bias
371 cpi 10 ; if 10 or more its still bad
374 lhld number ; now multiply number by ten and add the new value
382 mov e,a ; add de to hl...
387 gnum3: lxi d,cmer04 ; invalid number...
393 ; This routine gets a confirm.
396 cmcfrm: call cmgtch ;Get a char.
397 ora a ;Is it negative (a terminator;a space or
398 ;a tab will not be returned here as they
399 ;will be seen as leading white space.)
400 rp ;If not, return failure.
401 ani 7FH ;Turn off the minus bit.
402 cpi esc ;Is it an escape?
405 mvi e,bell ;Get a bell.
408 sta cmaflg ;Turn off the action flag.
409 lhld cmcptr ;Move the pointer to before the escape.
413 lxi h,cmccnt ;Get the char count.
414 dcr m ;Decrement it by one.
415 jmp cmcfrm ;Try again.
417 cmcfr2: cpi '?' ;Curious?
419 lxi d,cmin00 ;Print something useful.
421 call prcrlf ;Print a crlf. [Toad Hall]
422 call prprmp ;Reprint the prompt [Toad Hall]
423 lhld cmdptr ;Get the pointer into the buffer.
424 mvi a,'$' ;Put a $ there for printing.
427 dcx h ;Decrement and save the buffer pointer.
431 xra a ;Turn off the action flag.
433 jmp repars ;Reparse everything.
435 cmcfr3: cpi ff ;Is it a form feed?
436 cz clrtop ;If so blank the screen.
439 ; This routine parses a keyword from the table pointed
440 ; to in DE. The format of the table is as follows:
442 ; addr: db n ;Where n is the # of entries in the table.
443 ; db m ;M is the size of the keyword.
444 ; db 'string$' ;Where string is the keyword.
445 ; db a,b ;Where a & b are pieces of data
446 ; ;to be returned. (Must be two of them.)
448 ; The keywords must be in alphabetical order.
449 ;**** Note: The data value a is returned in registers A and E. The
450 ;**** data value b is returned in register D. This allows the two data
451 ; bytes to be stored as:
453 ; and result in a correctly formatted 16-bit value in register pair
457 cmkeyw: shld cmhlp ;Save the help.
458 xchg ;Get the address of the table.
459 shld cmptab ;Save the beginning of keyword tab for '?'.
460 mov b,m ;Get the number of entries in the table.
463 lhld cmdptr ;Save the command pointer.
465 cmkey2: mov a,b ;Get the number of entries left.
467 rz ;If not we failed.
468 mvi a,0ffh ;[MF]Make sure we ignore leading spaces
471 mov e,m ;Get the length of the keyword.
473 cmkey3: dcr e ;Decrement the number of chars left.
475 cpi 0FFH ;Have we passed the end?
476 jm cmkey5 ;If so go to the next.
477 call cmgtch ;Get a char.
478 ora a ;Is it a terminator?
479 jp cmkey4 ;If positive, it is not.
480 ani 7FH ;Turn off the minus bit.
484 sta cmaflg ;Turn off the action flag.
485 lxi h,cmccnt ;Decrement the char count.
487 ;* Must go through the keyword table and print them.
488 lhld cmhlp ;For now print the help text.
490 call p20ln ;[8] print at most 20 lines then pause
492 call prcrlf ;Print a crlf [Toad Hall]
493 call prprmp ;Reprint the prompt [Toad Hall]
494 lhld cmdptr ;Get the pointer into the buffer.
495 mvi a,'$' ;Put a $ there for printing.
498 dcx h ;Decrement and save the buffer pointer.
502 jmp repars ;Reparse everything.
504 cmky31: cpi esc ;Is it an escape?
507 sta cmaflg ;Turn off the action flag.
512 jmp cmky32 ;Not ambiguous.
515 call bdos ;Ring the bell.
516 lhld cmcptr ;Move the pointer to before the escape.
520 lxi h,cmccnt ;Get the char count.
521 dcr m ;Decrement it by one.
525 inr e ;Increment the left to parse char count.
528 cmky32: lhld cmcptr ;Pointer into buffer.
529 dcx h ;Backup to the escape.
533 cmky33: mov a,m ;Get the next char.
538 mov m,a ;Move it into the buffer.
541 lda cmccnt ;Increment the char count.
546 cmky34: lda cmccnt ;Get the character count.
547 inr a ;Increment and save it.
549 xchg ;Put the command buffer pointer in HL.
550 mvi a,' ' ;Get a blank.
551 mov m,a ;Put it in the command buffer.
552 inx h ;Increment the pointer
553 shld cmcptr ;Save the updated pointer.
558 call prtstr ;Print the rest of the keyword.
561 call bdos ;Print a blank.
572 call prtstr ;Say its ambiguous.
577 cmky37: inr e ;Add one incase it is negative.
579 dad d ;Increment past the keyword.
581 mov e,m ;Get the data.
587 cmkey4: cpi 'a' ;Is it less than a?
588 jm cmky41 ;If so don't capitalize it.
589 cpi 'z'+1 ;Is it more than z?
590 jp cmky41 ;If so don't capitalize it.
591 ani 137O ;Capitalize it.
592 cmky41: mov d,m ;Get the next char of the keyword.
595 jz cmkey3 ;If so get the next letter.
598 mov a,e ;Get the number of chars left.
599 ora a ;Is it negative?
601 mvi d,0FFH ;If so, sign extend.
602 cmky51: dad d ;Increment past the keyword.
603 lxi d,0003H ;Plus the $ and data.
606 dcr b ;Decrement the number of entries left.
607 lhld cmsptr ;Get the old cmdptr.
608 shld cmdptr ;Restore it.
609 ;* check so we don't pass it.
610 jmp cmkey2 ;Go check the next keyword.
612 ; Test keyword for ambiguity.
613 ; returns: nonskip if ambiguous, skip if OK.
616 cmambg: dcr b ;Decrement the number of entries left.
617 rm ;If none left then it is not ambiguous.
618 inr e ;This is off by one;adjust.
619 mov c,e ;Save the char count.
621 ora a ;Any chars left?
622 rz ;No, it can't be ambiguous.
624 dad d ;Increment past the keyword.
625 mvi e,3 ;Plus the $ and data.
627 mov b,m ;Get the length of the keyword.
630 lhld cmkptr ;Get pointer to keyword entry.
631 mov a,m ;Get the length of the keyword.
632 sub c ;Subtract how many left.
633 mov c,a ;Save the count.
636 rp ;If larger than the new word then not amb.
637 cmamb0: lhld cmsptr ;Get the pointer to what parsed.
638 cmamb1: dcr c ;Decrement the count.
639 jm rskp ;If we are done then it is ambiguous.
640 xchg ;Exchange the pointers.
641 mov b,m ;Get the next char of the keyword
643 xchg ;Exchange the pointers.
644 mov a,m ;Get the next parsed char.
646 cpi 'a' ;Is it less than a?
647 jm cmamb2 ;If so don't capitalize it.
648 cpi 'z'+1 ;Is it more than z?
649 jp cmamb2 ;If so don't capitalize it.
651 cmamb2: cmp b ;Are they equal?
652 rnz ;If not then its not ambiguous.
653 jmp cmamb1 ;Check the next char.
655 ; cmofil - parse output filespec
656 ; cmifil - parse input filespec
659 cmofil: mvi a,0 ;Don't allow wildcards.
660 ; jmp cmifil ;For now, the same as CMIFI.
661 cmifil: sta cmfwld ;Set wildcard flag
662 xchg ;Get the fcb address.
664 mvi e,0 ;Initialize char count.
665 mvi m,0 ;Set the drive to default to current.
668 xra a ;Initialize counter.
669 cmifi0: mvi m,' ' ;Blank the FCB.
672 ; cpi 0CH ;Twelve? [5a dont use this]
673 cpi 0Bh ; [majoc 850585] Eleven?
675 cmif0a: ;[MF]Zero entire fcb, not just the extent
676 mvi m,0 ; [majoc 850507] Specify extent 0
677 inx h ;[MF]Increment fcb byte pointer
678 inr a ;[MF]Increment fcb byte count
679 cpi 32 ;[MF]Done with fcb?
680 jm cmif0a ;[MF]No, zero until done
681 cmifi1: call cmgtch ;Get another char.
682 ora a ;Is it an action character?
684 ani 7FH ;Turn off the action bit.
685 cpi '?' ;A question mark?
687 lda cmfwld ;[pcc006] Wildcards allowed?
689 jz cmif11 ;[pcc006] complain if not
690 lhld cmdptr ;[jd] Increment buffer pointer
691 inx h ;[jd] that was decremented in cmgtch
692 shld cmdptr ;[jd] since we want this chr
693 lda cmcptr ;[pcc006] get lsb of real input pointer
694 cmp l ;[pcc006] is this the last chr input?
695 jnz cmif1a ;[pcc006] no, don't reset action flag
696 xra a ;[pcc006] yes, reset action flag
698 cmif1a: mvi a,'?' ;[pcc006] get it back in A
699 jmp cmifi8 ;Treat like any other character
701 cmif12: cpi esc ;An escape?
703 ;Try to recognize file-spec a'la TOPS-20
705 sta cmaflg ;Turn off the action flag.
706 lhld cmcptr ;Move the pointer to before the escape.
710 lxi h,cmccnt ;Get the char count.
711 dcr m ;Decrement it by one.
712 mov a,e ;Save character count up to now.
716 dcr a ;Yes, don't count point.
717 cmfrec: lhld cmfcb2 ;Fill the rest with CP/M wildcards.
718 cmfrc1: cpi 11 ;Done?
725 cmfrc2: mvi c,sfirst ;Find first matching file?
731 lxi h,fcbblk ;Copy first file spec.
733 lxi h,fcbblk+10H ;Get another copy (in case not ambiguous).
735 mvi c,snext ;More matching specs?
741 lxi h,fcbblk+10H ;Copy second file spec.
743 cmfrc3: lxi d,fcbblk ;Start comparing file names.
745 lda temp1 ;Bypass characters typed.
748 dcr a ;Yes, don't count point.
750 cmfrl1: cmp c ;Bypassed?
757 cmfrl2: mov a,c ;Get file name characters processed.
760 cpi 8 ;End of file name?
762 lda temp1 ;Exactly at point?
764 jz cmfrl3 ;Yes, don't output a second point.
765 mvi a,'.' ;Output separator.
767 cmfrl3: ldax d ;Get a character from first file spec.
769 mov b,m ;Get from second file spec.
772 jnz cmfrc5 ;Ambiguous.
775 jz cmfrl2 ;Yes, don't output.
776 call cmfput ;Put character into buffer.
779 cmfrc5: mov a,c ;Get count of characters processed.
781 mvi a,'$' ;Get terminator.
782 call cmfput ;Put it into buffer.
783 lhld cmdptr ;Output recognized characters.
787 lhld cmcptr ;Remove terminator from buffer.
792 lda temp1 ;Characters processed.
793 cpi 11 ;Complete file name.
794 jz repars ;Yes, don't beep.
798 call bdos ;Ring the bell.
801 ; Continue file spec parsing.
803 cmif13: mov a,e ;It must be a terminator.
804 ora a ;Test the length of the file name.
805 jz cmifi9 ;If zero complain.
807 jp cmifi9 ;If too long complain.
808 jmp rskp ;Otherwise we have succeeded.
814 cpi 1H ;Any chars yet?
815 jz cmifi9 ;No, give error.
817 jp cmifi9 ;Past it, give an error.
821 dad b ;Point to file type field.
823 mvi e,9H ;Say we've gotten nine.
824 jmp cmifi1 ;Get the next char.
830 cpi 2H ;Is it in the right place for a drive?
831 jnz cmifi9 ;If not, complain.
833 dcx h ;Point to previous character.
834 mov a,m ;Get the drive name.
835 sui '@' ;Get the drive number.
836 shld cmfcb2 ;Save pointer to beginning of name field.
837 mvi m,space ;[obs] restore a space in FCB
838 dcx h ;Point to drive number.
839 mov m,a ;Put it in the fcb.
840 mvi e,0 ;Start character count over.
845 lda cmfwld ;Wildcards allowed?
847 jz cmif11 ;No,complain
849 cpi 8H ;Is this in the name or type field?
850 jz cmifi9 ;If its where the dot should be give up.
852 mvi b,8H ;Eight chars.
855 cmifi5: mvi b,0CH ;Three chars.
856 cmifi6: lhld cmfcb2 ;Get a pointer into the FCB.
858 mov m,a ;Put a question mark in.
864 jm cmifi6 ;Go fill in another.
865 jmp cmifi1 ;Get the next char.
867 cmifi7: cpi '!' ;[pcc007] control chr or space?
868 jm cmifi9 ;[pcc007] yes, illegal
869 mov h,a ;[5] stash input char for a bit
870 lda ffussy ;[5] while we check the fussy flag
871 ora a ;[5] set the flags accordingly
872 mov a,h ;[5] restore the input character
873 jz cmif7a ;[5] if ffussy=0, allow <>.,;:?*[]
874 ;[5] So far, we've eliminated "action characters" (including question),
875 ;[5] period, colon, asterisk, control characters, and space.
876 ;[5] That leaves us %(),/;<=>[\]_| to check for.
883 cpi ',' ;[pcc007] weed out comma
887 cpi '9'+1 ;[pcc007] anything else 21H-39H is ok
888 jm cmifi8 ;[pcc007] except '*' never gets here
889 cpi '@' ;[pcc007] all of 3AH-3FH is illegal
891 cpi '[' ;[pcc007] [\] also illegal
896 jz cmifi9 ;[5] (If I was doing CP/M, I would have
897 cpi '|' ;[5] just eliminated all them funny chars
898 jz cmifi9 ;[5] instead of a random selection)
900 cpi 'a' ;[pcc007] if not lower case its ok
901 jm cmifi8 ;[pcc007] (DEL never gets here)
902 cpi 'z'+1 ;[pcc007] only convert letters
904 ani 137O ;Capitalize.
905 cmifi8: lhld cmfcb2 ;Get the pointer into the FCB.
906 mov m,a ;Put the char there.
913 cpi cmifin ;"silent"?
914 jz r ;Yes,let him go w/o check
920 cmif11: lxi d,cmer03 ;Complain about wildcards.
925 ; copy filename from buffer
926 ; called with HL = destination, A = position (0-3) in buffer
929 fspcop: push psw ;Save A.
930 lxi d,buff ;Get the right offset in the buffer.
937 inr a ;Bypass drive spec.
939 mvi b,11 ;Copy file name.
949 ; append character in A to command buffer
952 cmfput: push h ;Save H.
953 lhld cmcptr ;Get buffer pointer.
954 mov m,a ;Store in buffer.
957 lxi h,cmccnt ;Count it.
962 ; Read characters from the command buffer.
963 ; called by: cmtext, cmcfrm, cmkeyw, cmifil
969 cz cminbf ;If the action char flag is not set get more.
970 lhld cmdptr ;Get a pointer into the buffer.
971 mov a,m ;Get the next char.
974 cpi ' ' ;Is it a space?
978 cmgtc2: lda cmsflg ;Get the space flag.
979 ora a ;Was the last char a space?
980 jnz cmgtc1 ;Yes, get another char.
981 mvi a,0FFH ;Set the space flag.
990 sta cmsflg ;Zero the space flag.
996 cpi '?' ;Is the user curious?
1003 rnz ;Not an action char, just return.
1009 cmgtc5: ori 80H ;Make the char negative to indicate it is
1012 ; Read characters from console into command buffer, processing
1013 ; editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del).
1014 ; called by: comnd, cmgtch
1019 lda cmaflg ;Is the action char flag set?
1021 jnz cminb9 ;If so get no more chars.
1022 cminb1: lxi h,cmccnt ;Increment the char count.
1024 mvi c,conin ;Get a char.
1025 lda cmqflg ;[MF]but do we want it echoed?
1027 jz cmin1b ;[MF]Yup, proceed normally
1028 cmin1c: mvi e,0ffH ;[MF]Nope, do it with Direct
1029 mvi c,dconio ;[MF]Console I/O
1031 ora a ;[MF]Did the user type anything?
1032 jz cmin1c ;[MF]No, don't go on until he/she does.
1033 jmp cmin1a ;[MF]We got a character
1035 cmin1a: lhld cmcptr ;Get the pointer into the buffer.
1036 mov m,a ;Put it in the buffer.
1039 cpi 25O ;Is it a ^U?
1041 cpi 30O ;Is it a ^X?
1043 cmnb12: call clrlin ;Clear the line.
1044 call prprmp ;Print the prompt [Toad Hall]
1046 shld cmcptr ;Reset the point to the start.
1047 lxi h,cmccnt ;Zero the count.
1049 jmp repars ;Go start over.
1051 cminb2: cpi 10O ;Backspace?
1055 lda cmqflg ;[MF]If we are echoing characters,
1057 cz delchr ;Print the delete string. [MF]
1058 cminb3: lda cmccnt ;Decrement the char count by two.
1061 ora a ;Have we gone too far?
1062 jp cmnb32 ;If not proceed.
1063 mvi c,conout ;Ring the bell.
1066 jmp cmnb12 ;Go reprint prompt and reparse.
1068 cmnb32: sta cmccnt ;Save the new char count.
1069 lda cmqflg ;[MF]Echoing characters?
1070 ora a ;[MF]If we are, then
1071 cz clrspc ;Erase the character. [MF]
1072 lhld cmcptr ;Get the pointer into the buffer.
1073 dcx h ;Back up in the buffer.
1076 jmp repars ;Go reparse everything.
1078 cminb4: cpi '?' ;Is it a question mark.
1080 cpi esc ;Is it an escape?
1082 cpi cr ;Is it a carriage return?
1084 cpi lf ;Is it a line feed?
1086 cpi ff ;Is it a formfeed?
1087 jnz cminb8 ;no - just store it and
1088 ;test if buffer overflowing, else get another character.
1090 cminb5: lda cmbflg ;[MF]Allowing initial blank word (<cr>)?
1093 lda cmccnt ;Have we parsed any chars yet?
1095 jz prserr ;If not, just start over.
1096 cminb6: mvi a,0FFH ;Set the action flag.
1101 lda cmccnt ; get the command character count
1102 cpi cmbufl ; check for comand buffer length
1103 jm cminb1 ; if less, then all ok
1104 mvi e,bell ; else beep at user
1105 call outcon ; send it to the console
1106 lda cmccnt ; back up one character
1109 lhld cmcptr ; ditto pointer
1111 shld cmcptr ; save it again
1112 jmp cminb1 ; and try again
1119 ;Little utility to print the prompt. (We do a LOT of these.) [Toad Hall]
1120 ;Enters with nothing.
1121 ;Destroys HL (and I suppose B and DE and A).
1123 prprmp: mvi e,cr ; do a cr first
1126 lhld cmprmp ;Get the prompt.
1131 ; Little code to allow some expansion of code without changing
1132 ; every futher address, only up to the end of this file.
1133 ; TO BE REMOVED FOR RELEASE!
1135 ; org ($+100h) AND 0FF00H
1140 ENDIF ;lasm [Toad Hall]