]>
Commit | Line | Data |
---|---|---|
e58a7a25 L |
1 | ; CPSCMD.ASM\r |
2 | ; KERMIT - (Celtic for "FREE")\r | |
3 | ;\r | |
4 | ; This is the CP/M-80 implementation of the Columbia University\r | |
5 | ; KERMIT file transfer protocol.\r | |
6 | ;\r | |
7 | ; Version 4.0\r | |
8 | ;\r | |
9 | ; Copyright June 1981,1982,1983,1984,1985\r | |
10 | ; Columbia University\r | |
11 | ;\r | |
12 | ; Originally written by Bill Catchings of the Columbia University Center for\r | |
13 | ; Computing Activities, 612 W. 115th St., New York, NY 10025.\r | |
14 | ;\r | |
15 | ; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,\r | |
16 | ; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many\r | |
17 | ; others. \r | |
18 | ;\r | |
19 | ;\r | |
20 | ; This file provides a user oriented way of parsing commands.\r | |
21 | ; It is similar to that of the COMND JSYS in TOPS-20.\r | |
22 | ;\r | |
23 | ; revision history (latest first):\r | |
24 | ;\r | |
25 | ;edit 13, 17-Jan-1991 by MF. Modified "cmifil" routine to zero the entire\r | |
26 | ; fcb (not just the extent) to fix a bug in the COPY command which\r | |
27 | ; prevented successive COPY commands from working properly.\r | |
28 | ;edit 12, 16-Jan-1991 by MF. Modified routine "cmkeyw" to ignore leading\r | |
29 | ; spaces/tabs before a keyword. This apparently was the intent in\r | |
30 | ; "prompt" and "repars" (at least for command-lines) as the variable \r | |
31 | ; "cmsflg "is set upon command parse and reparse. The intent was ,\r | |
32 | ; subverted, however, as "cmkeyw" did not reset the flag to ignore\r | |
33 | ; leading white space for each search thru the key tables (even though\r | |
34 | ; the buffer pointer to the keyword entered was reset). The fix was\r | |
35 | ; to reset the "spaces seen" flag (cmsflg) after "cmkey2" so that\r | |
36 | ; it is reset each time a new table entry is compared to the text\r | |
37 | ; the user has entered from the keyboard/TAKE-file etc. The upshot\r | |
38 | ; of all this is that the kluge code in "cminbf" at "cminb0" designed\r | |
39 | ; to force Kermit to ignore leading white space on command-lines in\r | |
40 | ; TAKE-files and on the CP/M command-line is no longer needed and,\r | |
41 | ; therefore, has been eliminated. Also modify "comnd" to expect leading\r | |
42 | ; spaces for functions other than "get keyword".\r | |
43 | ;edit 11, 26-Dec-1990 by MF. Modified routines to ignore leading white space\r | |
44 | ; in lines from TAKE-files as well as during input from the CP/M\r | |
45 | ; command-line (form-feeds are now considered white space under these\r | |
46 | ; circumstances).\r | |
47 | ;edit 10, 8-Sep-1990 by Mike Freeman. Modified routines to ignore leading\r | |
48 | ; spaces/tabs when processing Kermit commands from the CP/M\r | |
49 | ; command-line.\r | |
50 | ; Added flag CMBFLG to allow initial word on a command-line\r | |
51 | ; to be blank (useful for Remote commands such as Remote CWD etc).\r | |
52 | ; Added flag cmqflg to prevent character-echoing while entering\r | |
53 | ; commands so Remote CWD etc can have nonechoing password entry.\r | |
54 | ; edit 9, 15 June, 1987 by OBSchou. Bug fixing to allow a second filename\r | |
55 | ; (quiet) be entered as d:<blank>. Previous revision put the drive name \r | |
56 | ; in first character of FCB, I put that character back to a space.\r | |
57 | ;\r | |
58 | ; edit 8, 12 June, 1987 by OBSchou. Addedin code in cmkeyw to print\r | |
59 | ; 20 lines of help, then pause for a key from the user befor\r | |
60 | ; proceeding with help.\r | |
61 | ;\r | |
62 | ; edit 7, 11 March, 1987 by OBSchou for Richard Russell, BBC. He writes:\r | |
63 | ; Bug in cmtext which prevented use of octal characters (\nnn) fixed.\r | |
64 | ;\r | |
65 | ; edit 6, 18 June, 1986 by OBSchou, Loughborough University, Leics. UK\r | |
66 | ; added code to parse a number from user input. Added check to make \r | |
67 | ; sure the input command buffer does not overflow the limit.\r | |
68 | ;\r | |
69 | ; edit 5a: 7 March, 1986. OBSchou. Added stuff rom MJ Carter. He writes:\r | |
70 | ; 7th May 85, MJ Carter [majoc], Nottingham University\r | |
71 | ; Code in cmifil() put one too many spaces in the FCB; this caused \r | |
72 | ; the BDOS of the British Micro Mimi to search for exteny 32,\r | |
73 | ; rather than extent 0, so era() always said "can't find file"\r | |
74 | ; Puttig a null at the point in question ought to fix 9 it.\r | |
75 | ;\r | |
76 | ; edit 5: 6-Feb-85 by Charles Carvalho\r | |
77 | ; Make ffussy a runtime (rather than assembly-time) switch, to\r | |
78 | ; eliminate conditional assembly in system-independent module.\r | |
79 | ; Don't allow _%|()/\ in filenames if ffussy set; my CP/M manual\r | |
80 | ; disallows those, too.\r | |
81 | ;\r | |
82 | ; edit 4: 13-Jan-85 by Vanya J.Cooper Pima Commun. College Tel: 602-884-6809\r | |
83 | ;\r | |
84 | ;pcc006 2-jan-85 VJC modules:cp4cmd,cp4utl\r | |
85 | ; Problems with "?" in filespecs. On reparse, may cause action\r | |
86 | ; flag to be reset at wrong point, requiring multiple <CR>'s\r | |
87 | ; to terminate the line or other weird stuff. Also need to\r | |
88 | ; check flag and complain if wild-cards illegal.\r | |
89 | \r | |
90 | ;pcc007 2-Jan-85 vjc modules:cp4def,cp4cmd\r | |
91 | ; Cmifil is too fussy about what characters to accept in a\r | |
92 | ; filespec. My CP/M manual says any printable character is ok\r | |
93 | ; except <>.,;:?*[], and lower case. In practice, even those work\r | |
94 | ; sometimes. Kermit itself uses '&' if file warning is on,\r | |
95 | ; and then won't let you reference the file. Allow all\r | |
96 | ; printable characters except those above. Add conditional\r | |
97 | ; ffussy, so that if not ffussy, all special characters will be\r | |
98 | ; allowed, just convert lower to upper-case.\r | |
99 | \r | |
100 | ; edit 3: July 8, 1984 (CJC)\r | |
101 | ; integrate Toad Hall changes for LASM compatibility: CP4CPM is linked\r | |
102 | ; by CP4WLD, and links CP4UTL.\r | |
103 | ; \r | |
104 | ; edit 2: June 5, 1984 (CJC)\r | |
105 | ; formatting and documentation; delete unnecessary code at cminb7; add\r | |
106 | ; module version string.\r | |
107 | ;\r | |
108 | ; edit 1: May, 1984 (CJC)\r | |
109 | ; extracted from CPMBASE.M80 version 3.9; modifications are described in\r | |
110 | ; the accompanying .UPD file.\r | |
111 | \r | |
112 | cmdver: db 'CPSCMD.ASM (13) 17-Jan-1991$' ; name, edit number, date\r | |
113 | \r | |
114 | ; This routine prints the prompt in DE and specifies the reparse\r | |
115 | ; address.\r | |
116 | ; called by: kermit\r | |
117 | \r | |
118 | prompt: pop h ;Get the return address.\r | |
119 | push h ;Put it on the stack again.\r | |
120 | shld cmrprs ;Save it as the address to go to on reparse.\r | |
121 | lxi h,0 ;Clear out hl pair.\r | |
122 | dad sp ;Get the present stack pointer.\r | |
123 | shld cmostp ;Save for later restoral.\r | |
124 | xchg ;Save the pointer to the prompt.\r | |
125 | shld cmprmp\r | |
126 | xchg\r | |
127 | lxi h,cmdbuf\r | |
128 | shld cmcptr ;Initialize the command pointer.\r | |
129 | shld cmdptr\r | |
130 | xra a\r | |
131 | sta cmaflg ;Zero the flags.\r | |
132 | sta cmccnt\r | |
133 | ; mvi a,0FFH ;Try it this way (Daphne.)\r | |
134 | ; sta cmsflg\r | |
135 | call prcrlf ;Print a CR/LF [Toad Hall]\r | |
136 | jmp prprmp ;Print the prompt. [Toad Hall]\r | |
137 | ;\f\r | |
138 | ; This address is jumped to on reparse.\r | |
139 | ; here from: cmcfrm, cmkeyw, cmifil, cminbf\r | |
140 | \r | |
141 | repars: lhld cmostp ;Get the old stack pointer.\r | |
142 | sphl ;Make it the present one.\r | |
143 | lxi h,cmdbuf\r | |
144 | shld cmdptr\r | |
145 | ; mvi a,0FFH ;Try it this way (Daphne.)\r | |
146 | ; sta cmsflg\r | |
147 | lhld cmrprs ;Get the reparse address.\r | |
148 | pchl ;Go there.\r | |
149 | \r | |
150 | ; This address can be jumped to on a parsing error.\r | |
151 | ; here from: cmkeyw, cminbf\r | |
152 | \r | |
153 | prserr: lhld cmostp ;Get the old stack pointer.\r | |
154 | sphl ;Make it the present one.\r | |
155 | lxi h,cmdbuf\r | |
156 | shld cmcptr ;Initialize the command pointer.\r | |
157 | shld cmdptr\r | |
158 | xra a\r | |
159 | sta cmaflg ;Zero the flags.\r | |
160 | sta cmccnt\r | |
161 | ; mvi a,0FFH ;Try it this way (Daphne.)\r | |
162 | ; sta cmsflg\r | |
163 | call prcrlf ;Print a CR/LF [Toad Hall]\r | |
164 | call prprmp ;Print the prompt [Toad Hall]\r | |
165 | ;* Instead return to before the prompt call.\r | |
166 | lhld cmrprs\r | |
167 | pchl\r | |
168 | ;\f\r | |
169 | ; This routine parses the specified function in A. Any additional\r | |
170 | ; information is in DE and HL.\r | |
171 | ; Returns +1 on success\r | |
172 | ; +4 on failure (assumes a JMP follows the call)\r | |
173 | ; called by: log, setcom, read, send, xmit, dir, era, keycmd, cfmcmd\r | |
174 | ; and CPSREM\r | |
175 | \r | |
176 | comnd: sta cmstat ;Save what we are presently parsing.\r | |
177 | call cminbf ;Get chars until an action or a erase char.\r | |
178 | push psw ;[MF]Save function\r | |
179 | mvi a,0ffh ;[MF]Expect leading spaces\r | |
180 | sta cmsflg ;[MF]...\r | |
181 | pop psw ;[MF]Restore function\r | |
182 | cpi cmcfm ;Parse a confirm?\r | |
183 | jz cmcfrm ;Go get one.\r | |
184 | cpi cmkey ;Parse a keyword?\r | |
185 | jz cmkeyw ;Try and get one.\r | |
186 | cpi cmifi ;Parse an input file spec?\r | |
187 | jz cmifil ;Go get one.\r | |
188 | cpi cmifin ;Input file-spec silent?\r | |
189 | jz cmifil ;do as he wishes\r | |
190 | cpi cmofi ;Output file spec?\r | |
191 | jz cmofil ;Go get one.\r | |
192 | cpi cmtxt ;Parse arbitrary text?\r | |
193 | jz cmtext ;Go do it.\r | |
194 | cpi cmnum ;[7] Parse a number?\r | |
195 | jz cmnumb ;[7] go do it\r | |
196 | lxi d,cmer00 ;"?Unrecognized COMND call"\r | |
197 | call prtstr\r | |
198 | ret\r | |
199 | ;\f\r | |
200 | ; This routine parses arbitrary text up to a CR.\r | |
201 | ; Accepts DE: address to put text\r | |
202 | ; Returns in A: number of chars in text (may be 0)\r | |
203 | ; DE: updated pointer\r | |
204 | ; called by: comnd\r | |
205 | \r | |
206 | cmtext: xra a ; clear counters erc for slashes etc\r | |
207 | sta slshsn ; if we are in a slash sequence\r | |
208 | sta slashn ; the octal number being entered\r | |
209 | sta slashc ; number of characters entered\r | |
210 | \r | |
211 | xchg ;Put the pointer to the dest in HL.\r | |
212 | shld cmptab ;Save the pointer.\r | |
213 | mvi b,0 ;Init the char count\r | |
214 | cmtxt1: call cmgtch ;Get a char.\r | |
215 | ora a ;Terminator?\r | |
216 | jp cmtx3 ;No, put in user space. [rtr] was cmtx5\r | |
217 | ani 7FH ;Turn off minus bit.\r | |
218 | cpi esc ;An escape?\r | |
219 | jnz cmtxt2 ;No.\r | |
220 | mvi c,conout\r | |
221 | mvi e,bell ;Get a bell.\r | |
222 | call bdos\r | |
223 | xra a\r | |
224 | sta cmaflg ;Turn off the action flag.\r | |
225 | lhld cmcptr ;Move the pointer to before the escape.\r | |
226 | dcx h\r | |
227 | shld cmcptr\r | |
228 | shld cmdptr\r | |
229 | lxi h,cmccnt ;Get the char count.\r | |
230 | dcr m ;Decrement it by one.\r | |
231 | jmp cmtxt1 ;Try again.\r | |
232 | \r | |
233 | cmtxt2: cpi '?' ;Is it a question mark?\r | |
234 | jz cmtxt4 ;If so put it in the text. [rtr] was cmtx3\r | |
235 | cpi ff ;Is it a formfeed?\r | |
236 | cz clrtop ;If so blank the screen.\r | |
237 | mov a,b ;Return the count.\r | |
238 | lhld cmptab ;Return updated pointer in HL.\r | |
239 | xchg\r | |
240 | jmp rskp ;Return success.\r | |
241 | \r | |
242 | cmtx3: cpi '\' ; slash?\r | |
243 | jnz cmtx3a ; nope, so try something else\r | |
244 | lda slshsn ; a slash already entered?\r | |
245 | ana a\r | |
246 | cma ;[rtr]\r | |
247 | jnz cmtx3a ; yes, so assume its a valid slash to enter\r | |
248 | sta slshsn ; make sure the flag is set for next time routnd\r | |
249 | jmp cmtxt1 ; get another character\r | |
250 | \r | |
251 | cmtx3a:\r | |
252 | ; lxi h,cmaflg ;Point to the action flag.\r | |
253 | ; mvi m,0 ;Set it to zero.\r | |
254 | mov e,a ; save it in case we are interpreting a slash\r | |
255 | lda slshsn ; slash already entered?\r | |
256 | ana a ; test flag\r | |
257 | mov a,e ; restore it in case...\r | |
258 | jz cmtx5 ; not a slash seen, so enter as a normal character\r | |
259 | cpi '\'\r | |
260 | jnz cmtx3b ; \\ not detected\r | |
261 | lda slashn ; else get number\r | |
262 | jmp cmtx5b ; and enter it ( in the case of \n or \nn)\r | |
263 | ; here if an octal number of 1 or 2 digits\r | |
264 | ; entered instead of 3, followed by \ again\r | |
265 | \r | |
266 | cmtx3b:\r | |
267 | sui 30h ; else it should be an octal number\r | |
268 | jm cmtxt6 ; if not a digit complain\r | |
269 | cpi 8 ; ditto\r | |
270 | jp cmtxt6 ;[rtr] was cmtxt\r | |
271 | mov e,a ; else add it to the number already entered\r | |
272 | lda slashn\r | |
273 | add a\r | |
274 | add a\r | |
275 | add a ; multiply by 8\r | |
276 | add e\r | |
277 | sta slashn\r | |
278 | lda slashc ; get the count\r | |
279 | inr a\r | |
280 | sta slashc ; plus one. If three then a number entered\r | |
281 | cpi 3\r | |
282 | lda slashn ; get the number in case...\r | |
283 | jz cmtx5\r | |
284 | jmp cmtxt1 ; else loop\r | |
285 | \r | |
286 | cmtxt4: lhld cmdptr ;[rtr] Get a pointer into the buffer\r | |
287 | inx h ;[rtr] Bump past '?'\r | |
288 | shld cmdptr ;[rtr]\r | |
289 | cmtx5: call cmtx5c\r | |
290 | jmp cmtxt1 ; put this into a subroutine\r | |
291 | \r | |
292 | cmtx5b:\r | |
293 | call cmtx5c ; here if we see \n\ or \nn\ rather than \nnn\\r | |
294 | mvi a,'\' ; so send slash number to buffer, \r | |
295 | sta slshsn ; re-store a slash seen\r | |
296 | jmp cmtxt1 ; try next one\r | |
297 | \r | |
298 | cmtx5c:\r | |
299 | inr b ;Increment the count.\r | |
300 | lhld cmptab ;Get the pointer.\r | |
301 | mov m,a ;Put the char in the array.\r | |
302 | inx h\r | |
303 | shld cmptab ;Save the updated pointer.\r | |
304 | xra a ; clear slash counters etc\r | |
305 | sta slashc\r | |
306 | sta slashn\r | |
307 | sta slshsn\r | |
308 | ret ; and exit\r | |
309 | \r | |
310 | cmtxt6: lxi d,cmer05 ; complain - not a valid \ parameter\r | |
311 | call prtstr\r | |
312 | jmp kermit ; and try another command\r | |
313 | ds 20h ; for debugging\r | |
314 | ;\f\r | |
315 | ; This routine gets a number from user input.\r | |
316 | ; Called by: comnd\r | |
317 | ;\r | |
318 | cmnumb: lxi h,0 ; make sure the number is zero to start with\r | |
319 | shld number\r | |
320 | cmnum0: call cmgtch ; get another character\r | |
321 | ora a ; if negative then its an action\r | |
322 | jp cmnum1 ; nope, so (possibly) valid input\r | |
323 | ani 7fh ; else lets see what it is...\r | |
324 | cpi esc ; do not know what to do with this one...\r | |
325 | cpi ' ' ; if it is a space then either a return or more\r | |
326 | jnz cmnum2 ; else\r | |
327 | jmp rskp ; space is a deliminter\r | |
328 | dw 0 ; set three bytes aside for a jump/call\r | |
329 | dw 0 ; and then another three just in case...\r | |
330 | dw 0 ; making 6 bytes\r | |
331 | cmnum2: cpi '?' ; user is curious\r | |
332 | jz gnum2\r | |
333 | cpi cr ; end of input?\r | |
334 | jz cmnumx\r | |
335 | gnum1: jmp prserr ; did not under stand this, so error\r | |
336 | cmnumx: dw 0\r | |
337 | dw 0\r | |
338 | jmp rskp ; return ok\r | |
339 | \r | |
340 | gnum2: lhld number ; get the number.. if at all entered\r | |
341 | mov a,l\r | |
342 | ora h ; if hl = 0 then possibly no number entered\r | |
343 | lxi d,cmin02 ; say confirm...or more on line\r | |
344 | jnz gnum21 ; else say enter a return\r | |
345 | lxi d,cmin01 ; say enter a number\r | |
346 | gnum21: call prtstr ; say it\r | |
347 | call prcrlf ; do a lf\r | |
348 | call prprmp ; another reprompt\r | |
349 | lhld cmdptr ; get pointer of string already entered\r | |
350 | mvi m,'$' ; dollar it to set end of line\r | |
351 | lhld cmcptr\r | |
352 | dcx h ; decrement and save the buffer pointer\r | |
353 | shld cmcptr\r | |
354 | lxi d,cmdbuf\r | |
355 | call prtstr ; print what has already been entered\r | |
356 | xra a\r | |
357 | sta cmaflg ; turn the action flag off\r | |
358 | jmp repars ; and try again\r | |
359 | \r | |
360 | mvi a,cmcfm ; parse a confirm\r | |
361 | dw 0\r | |
362 | dw 0\r | |
363 | dw 0\r | |
364 | dw 0\r | |
365 | dw 0 ; some space to patch...\r | |
366 | dw 0\r | |
367 | \r | |
368 | cmnum1: ani 7fh ; here for a (potentially) valid number\r | |
369 | sui '0' ; less ascii bias\r | |
370 | jc gnum3\r | |
371 | cpi 10 ; if 10 or more its still bad\r | |
372 | jnc gnum3\r | |
373 | cmc\r | |
374 | lhld number ; now multiply number by ten and add the new value\r | |
375 | push h\r | |
376 | pop d\r | |
377 | dad h ; hl = hl * 2\r | |
378 | dad h ; * 4\r | |
379 | dad d ; * 5\r | |
380 | dad h ; * 10\r | |
381 | mvi d,0\r | |
382 | mov e,a ; add de to hl...\r | |
383 | dad d\r | |
384 | shld number\r | |
385 | jmp cmnum0\r | |
386 | ;\r | |
387 | gnum3: lxi d,cmer04 ; invalid number...\r | |
388 | call prtstr\r | |
389 | jmp rskp\r | |
390 | ;\r | |
391 | \r | |
392 | ;\f\r | |
393 | ; This routine gets a confirm.\r | |
394 | ; called by: comnd\r | |
395 | \r | |
396 | cmcfrm: call cmgtch ;Get a char.\r | |
397 | ora a ;Is it negative (a terminator;a space or\r | |
398 | ;a tab will not be returned here as they\r | |
399 | ;will be seen as leading white space.)\r | |
400 | rp ;If not, return failure.\r | |
401 | ani 7FH ;Turn off the minus bit.\r | |
402 | cpi esc ;Is it an escape?\r | |
403 | jnz cmcfr2\r | |
404 | mvi c,conout\r | |
405 | mvi e,bell ;Get a bell.\r | |
406 | call bdos\r | |
407 | xra a\r | |
408 | sta cmaflg ;Turn off the action flag.\r | |
409 | lhld cmcptr ;Move the pointer to before the escape.\r | |
410 | dcx h\r | |
411 | shld cmcptr\r | |
412 | shld cmdptr\r | |
413 | lxi h,cmccnt ;Get the char count.\r | |
414 | dcr m ;Decrement it by one.\r | |
415 | jmp cmcfrm ;Try again.\r | |
416 | \r | |
417 | cmcfr2: cpi '?' ;Curious?\r | |
418 | jnz cmcfr3\r | |
419 | lxi d,cmin00 ;Print something useful.\r | |
420 | call prtstr\r | |
421 | call prcrlf ;Print a crlf. [Toad Hall]\r | |
422 | call prprmp ;Reprint the prompt [Toad Hall]\r | |
423 | lhld cmdptr ;Get the pointer into the buffer.\r | |
424 | mvi a,'$' ;Put a $ there for printing.\r | |
425 | mov m,a\r | |
426 | lhld cmcptr\r | |
427 | dcx h ;Decrement and save the buffer pointer.\r | |
428 | shld cmcptr\r | |
429 | lxi d,cmdbuf\r | |
430 | call prtstr\r | |
431 | xra a ;Turn off the action flag.\r | |
432 | sta cmaflg\r | |
433 | jmp repars ;Reparse everything.\r | |
434 | \r | |
435 | cmcfr3: cpi ff ;Is it a form feed?\r | |
436 | cz clrtop ;If so blank the screen.\r | |
437 | jmp rskp\r | |
438 | ;\f\r | |
439 | ; This routine parses a keyword from the table pointed\r | |
440 | ; to in DE. The format of the table is as follows:\r | |
441 | ;\r | |
442 | ; addr: db n ;Where n is the # of entries in the table.\r | |
443 | ; db m ;M is the size of the keyword.\r | |
444 | ; db 'string$' ;Where string is the keyword.\r | |
445 | ; db a,b ;Where a & b are pieces of data\r | |
446 | ; ;to be returned. (Must be two of them.)\r | |
447 | ;\r | |
448 | ; The keywords must be in alphabetical order.\r | |
449 | ;**** Note: The data value a is returned in registers A and E. The\r | |
450 | ;**** data value b is returned in register D. This allows the two data\r | |
451 | ; bytes to be stored as:\r | |
452 | ; dw xxx\r | |
453 | ; and result in a correctly formatted 16-bit value in register pair\r | |
454 | ; DE.\r | |
455 | ; called by: comnd\r | |
456 | \r | |
457 | cmkeyw: shld cmhlp ;Save the help.\r | |
458 | xchg ;Get the address of the table.\r | |
459 | shld cmptab ;Save the beginning of keyword tab for '?'.\r | |
460 | mov b,m ;Get the number of entries in the table.\r | |
461 | inx h\r | |
462 | shld cmkptr\r | |
463 | lhld cmdptr ;Save the command pointer.\r | |
464 | shld cmsptr\r | |
465 | cmkey2: mov a,b ;Get the number of entries left.\r | |
466 | ora a ;Any left?\r | |
467 | rz ;If not we failed.\r | |
468 | mvi a,0ffh ;[MF]Make sure we ignore leading spaces\r | |
469 | sta cmsflg ;[MF]...\r | |
470 | lhld cmkptr\r | |
471 | mov e,m ;Get the length of the keyword.\r | |
472 | inx h\r | |
473 | cmkey3: dcr e ;Decrement the number of chars left.\r | |
474 | mov a,e\r | |
475 | cpi 0FFH ;Have we passed the end?\r | |
476 | jm cmkey5 ;If so go to the next.\r | |
477 | call cmgtch ;Get a char.\r | |
478 | ora a ;Is it a terminator?\r | |
479 | jp cmkey4 ;If positive, it is not.\r | |
480 | ani 7FH ;Turn off the minus bit.\r | |
481 | cpi '?'\r | |
482 | jnz cmky31\r | |
483 | xra a\r | |
484 | sta cmaflg ;Turn off the action flag.\r | |
485 | lxi h,cmccnt ;Decrement the char count.\r | |
486 | dcr m\r | |
487 | ;* Must go through the keyword table and print them.\r | |
488 | lhld cmhlp ;For now print the help text.\r | |
489 | xchg\r | |
490 | call p20ln ;[8] print at most 20 lines then pause\r | |
491 | ; call prtstr\r | |
492 | call prcrlf ;Print a crlf [Toad Hall]\r | |
493 | call prprmp ;Reprint the prompt [Toad Hall]\r | |
494 | lhld cmdptr ;Get the pointer into the buffer.\r | |
495 | mvi a,'$' ;Put a $ there for printing.\r | |
496 | mov m,a\r | |
497 | lhld cmcptr\r | |
498 | dcx h ;Decrement and save the buffer pointer.\r | |
499 | shld cmcptr\r | |
500 | lxi d,cmdbuf\r | |
501 | call prtstr\r | |
502 | jmp repars ;Reparse everything.\r | |
503 | \r | |
504 | cmky31: cpi esc ;Is it an escape?\r | |
505 | jnz cmky35\r | |
506 | xra a\r | |
507 | sta cmaflg ;Turn off the action flag.\r | |
508 | push d\r | |
509 | push b\r | |
510 | push h\r | |
511 | call cmambg\r | |
512 | jmp cmky32 ;Not ambiguous.\r | |
513 | mvi c,conout\r | |
514 | mvi e,bell\r | |
515 | call bdos ;Ring the bell.\r | |
516 | lhld cmcptr ;Move the pointer to before the escape.\r | |
517 | dcx h\r | |
518 | shld cmcptr\r | |
519 | shld cmdptr\r | |
520 | lxi h,cmccnt ;Get the char count.\r | |
521 | dcr m ;Decrement it by one.\r | |
522 | pop h\r | |
523 | pop b\r | |
524 | pop d\r | |
525 | inr e ;Increment the left to parse char count.\r | |
526 | jmp cmkey3\r | |
527 | \r | |
528 | cmky32: lhld cmcptr ;Pointer into buffer.\r | |
529 | dcx h ;Backup to the escape.\r | |
530 | xchg\r | |
531 | pop h\r | |
532 | push h\r | |
533 | cmky33: mov a,m ;Get the next char.\r | |
534 | cpi '$' ;Finished?\r | |
535 | jz cmky34\r | |
536 | inx h\r | |
537 | xchg\r | |
538 | mov m,a ;Move it into the buffer.\r | |
539 | inx h\r | |
540 | xchg\r | |
541 | lda cmccnt ;Increment the char count.\r | |
542 | inr a\r | |
543 | sta cmccnt\r | |
544 | jmp cmky33\r | |
545 | \r | |
546 | cmky34: lda cmccnt ;Get the character count.\r | |
547 | inr a ;Increment and save it.\r | |
548 | sta cmccnt\r | |
549 | xchg ;Put the command buffer pointer in HL.\r | |
550 | mvi a,' ' ;Get a blank.\r | |
551 | mov m,a ;Put it in the command buffer.\r | |
552 | inx h ;Increment the pointer\r | |
553 | shld cmcptr ;Save the updated pointer.\r | |
554 | shld cmdptr\r | |
555 | pop h\r | |
556 | push h\r | |
557 | xchg\r | |
558 | call prtstr ;Print the rest of the keyword.\r | |
559 | mvi c,conout\r | |
560 | mvi e,' '\r | |
561 | call bdos ;Print a blank.\r | |
562 | pop h\r | |
563 | pop b\r | |
564 | pop d\r | |
565 | jmp cmky37\r | |
566 | \r | |
567 | cmky35: push h\r | |
568 | push d\r | |
569 | call cmambg\r | |
570 | jmp cmky36\r | |
571 | lxi d,cmer01\r | |
572 | call prtstr ;Say its ambiguous.\r | |
573 | jmp prserr ;Give up.\r | |
574 | \r | |
575 | cmky36: pop d\r | |
576 | pop h\r | |
577 | cmky37: inr e ;Add one incase it is negative.\r | |
578 | mvi d,0\r | |
579 | dad d ;Increment past the keyword.\r | |
580 | inx h ;Past the $.\r | |
581 | mov e,m ;Get the data.\r | |
582 | inx h\r | |
583 | mov d,m\r | |
584 | mov a,e\r | |
585 | jmp rskp\r | |
586 | \r | |
587 | cmkey4: cpi 'a' ;Is it less than a?\r | |
588 | jm cmky41 ;If so don't capitalize it.\r | |
589 | cpi 'z'+1 ;Is it more than z?\r | |
590 | jp cmky41 ;If so don't capitalize it.\r | |
591 | ani 137O ;Capitalize it.\r | |
592 | cmky41: mov d,m ;Get the next char of the keyword.\r | |
593 | inx h\r | |
594 | cmp d ;Match?\r | |
595 | jz cmkey3 ;If so get the next letter.\r | |
596 | \r | |
597 | cmkey5: mvi d,0\r | |
598 | mov a,e ;Get the number of chars left.\r | |
599 | ora a ;Is it negative?\r | |
600 | jp cmky51\r | |
601 | mvi d,0FFH ;If so, sign extend.\r | |
602 | cmky51: dad d ;Increment past the keyword.\r | |
603 | lxi d,0003H ;Plus the $ and data.\r | |
604 | dad d\r | |
605 | shld cmkptr\r | |
606 | dcr b ;Decrement the number of entries left.\r | |
607 | lhld cmsptr ;Get the old cmdptr.\r | |
608 | shld cmdptr ;Restore it.\r | |
609 | ;* check so we don't pass it.\r | |
610 | jmp cmkey2 ;Go check the next keyword.\r | |
611 | ;\f\r | |
612 | ; Test keyword for ambiguity.\r | |
613 | ; returns: nonskip if ambiguous, skip if OK.\r | |
614 | ; called by: cmkeyw\r | |
615 | \r | |
616 | cmambg: dcr b ;Decrement the number of entries left.\r | |
617 | rm ;If none left then it is not ambiguous.\r | |
618 | inr e ;This is off by one;adjust.\r | |
619 | mov c,e ;Save the char count.\r | |
620 | mov a,e\r | |
621 | ora a ;Any chars left?\r | |
622 | rz ;No, it can't be ambiguous.\r | |
623 | mvi d,0\r | |
624 | dad d ;Increment past the keyword.\r | |
625 | mvi e,3 ;Plus the $ and data.\r | |
626 | dad d\r | |
627 | mov b,m ;Get the length of the keyword.\r | |
628 | inx h\r | |
629 | xchg\r | |
630 | lhld cmkptr ;Get pointer to keyword entry.\r | |
631 | mov a,m ;Get the length of the keyword.\r | |
632 | sub c ;Subtract how many left.\r | |
633 | mov c,a ;Save the count.\r | |
634 | cmp b\r | |
635 | jz cmamb0\r | |
636 | rp ;If larger than the new word then not amb.\r | |
637 | cmamb0: lhld cmsptr ;Get the pointer to what parsed.\r | |
638 | cmamb1: dcr c ;Decrement the count.\r | |
639 | jm rskp ;If we are done then it is ambiguous.\r | |
640 | xchg ;Exchange the pointers.\r | |
641 | mov b,m ;Get the next char of the keyword\r | |
642 | inx h\r | |
643 | xchg ;Exchange the pointers.\r | |
644 | mov a,m ;Get the next parsed char.\r | |
645 | inx h\r | |
646 | cpi 'a' ;Is it less than a?\r | |
647 | jm cmamb2 ;If so don't capitalize it.\r | |
648 | cpi 'z'+1 ;Is it more than z?\r | |
649 | jp cmamb2 ;If so don't capitalize it.\r | |
650 | ani 137O\r | |
651 | cmamb2: cmp b ;Are they equal?\r | |
652 | rnz ;If not then its not ambiguous.\r | |
653 | jmp cmamb1 ;Check the next char.\r | |
654 | ;\f\r | |
655 | ; cmofil - parse output filespec\r | |
656 | ; cmifil - parse input filespec\r | |
657 | ; here from: comnd\r | |
658 | \r | |
659 | cmofil: mvi a,0 ;Don't allow wildcards.\r | |
660 | ; jmp cmifil ;For now, the same as CMIFI.\r | |
661 | cmifil: sta cmfwld ;Set wildcard flag\r | |
662 | xchg ;Get the fcb address.\r | |
663 | shld cmfcb ;Save it.\r | |
664 | mvi e,0 ;Initialize char count.\r | |
665 | mvi m,0 ;Set the drive to default to current.\r | |
666 | inx h\r | |
667 | shld cmfcb2\r | |
668 | xra a ;Initialize counter.\r | |
669 | cmifi0: mvi m,' ' ;Blank the FCB.\r | |
670 | inx h\r | |
671 | inr a\r | |
672 | ; cpi 0CH ;Twelve? [5a dont use this]\r | |
673 | cpi 0Bh ; [majoc 850585] Eleven?\r | |
674 | jm cmifi0\r | |
675 | cmif0a: ;[MF]Zero entire fcb, not just the extent\r | |
676 | mvi m,0 ; [majoc 850507] Specify extent 0\r | |
677 | inx h ;[MF]Increment fcb byte pointer\r | |
678 | inr a ;[MF]Increment fcb byte count\r | |
679 | cpi 32 ;[MF]Done with fcb?\r | |
680 | jm cmif0a ;[MF]No, zero until done\r | |
681 | cmifi1: call cmgtch ;Get another char.\r | |
682 | ora a ;Is it an action character?\r | |
683 | jp cmifi2\r | |
684 | ani 7FH ;Turn off the action bit.\r | |
685 | cpi '?' ;A question mark?\r | |
686 | jnz cmif12\r | |
687 | lda cmfwld ;[pcc006] Wildcards allowed?\r | |
688 | ora a ;[pcc006]\r | |
689 | jz cmif11 ;[pcc006] complain if not\r | |
690 | lhld cmdptr ;[jd] Increment buffer pointer\r | |
691 | inx h ;[jd] that was decremented in cmgtch\r | |
692 | shld cmdptr ;[jd] since we want this chr\r | |
693 | lda cmcptr ;[pcc006] get lsb of real input pointer\r | |
694 | cmp l ;[pcc006] is this the last chr input?\r | |
695 | jnz cmif1a ;[pcc006] no, don't reset action flag\r | |
696 | xra a ;[pcc006] yes, reset action flag\r | |
697 | sta cmaflg ;[pcc006] \r | |
698 | cmif1a: mvi a,'?' ;[pcc006] get it back in A\r | |
699 | jmp cmifi8 ;Treat like any other character\r | |
700 | \r | |
701 | cmif12: cpi esc ;An escape?\r | |
702 | jnz cmif13\r | |
703 | ;Try to recognize file-spec a'la TOPS-20\r | |
704 | xra a\r | |
705 | sta cmaflg ;Turn off the action flag.\r | |
706 | lhld cmcptr ;Move the pointer to before the escape.\r | |
707 | dcx h\r | |
708 | shld cmcptr\r | |
709 | shld cmdptr\r | |
710 | lxi h,cmccnt ;Get the char count.\r | |
711 | dcr m ;Decrement it by one.\r | |
712 | mov a,e ;Save character count up to now.\r | |
713 | sta temp1\r | |
714 | cpi 9 ;Past '.'?\r | |
715 | jm cmfrec ;No.\r | |
716 | dcr a ;Yes, don't count point.\r | |
717 | cmfrec: lhld cmfcb2 ;Fill the rest with CP/M wildcards.\r | |
718 | cmfrc1: cpi 11 ;Done?\r | |
719 | jp cmfrc2 ;Yes.\r | |
720 | mvi m,'?'\r | |
721 | inx h\r | |
722 | inr a\r | |
723 | jmp cmfrc1\r | |
724 | \r | |
725 | cmfrc2: mvi c,sfirst ;Find first matching file?\r | |
726 | lhld cmfcb\r | |
727 | xchg\r | |
728 | call bdos\r | |
729 | cpi 0FFH\r | |
730 | jz cmfrc9 ;No, lose.\r | |
731 | lxi h,fcbblk ;Copy first file spec.\r | |
732 | call fspcop\r | |
733 | lxi h,fcbblk+10H ;Get another copy (in case not ambiguous).\r | |
734 | call fspcop\r | |
735 | mvi c,snext ;More matching specs?\r | |
736 | lhld cmfcb\r | |
737 | xchg\r | |
738 | call bdos\r | |
739 | cpi 0FFH\r | |
740 | jz cmfrc3 ;Only one.\r | |
741 | lxi h,fcbblk+10H ;Copy second file spec.\r | |
742 | call fspcop\r | |
743 | cmfrc3: lxi d,fcbblk ;Start comparing file names.\r | |
744 | lxi h,fcbblk+10H\r | |
745 | lda temp1 ;Bypass characters typed.\r | |
746 | cpi 9 ;Past '.'?\r | |
747 | jm cmfrc4 ;No.\r | |
748 | dcr a ;Yes, don't count point.\r | |
749 | cmfrc4: mvi c,0\r | |
750 | cmfrl1: cmp c ;Bypassed?\r | |
751 | jz cmfrl2 ;Yes.\r | |
752 | inx d\r | |
753 | inx h\r | |
754 | inr c\r | |
755 | jmp cmfrl1 ;Repeat.\r | |
756 | \r | |
757 | cmfrl2: mov a,c ;Get file name characters processed.\r | |
758 | cpi 11 ;All done?\r | |
759 | jz cmfrc5 ;Yes.\r | |
760 | cpi 8 ;End of file name?\r | |
761 | jnz cmfrl3 ;No.\r | |
762 | lda temp1 ;Exactly at point?\r | |
763 | cpi 9\r | |
764 | jz cmfrl3 ;Yes, don't output a second point.\r | |
765 | mvi a,'.' ;Output separator.\r | |
766 | call cmfput\r | |
767 | cmfrl3: ldax d ;Get a character from first file spec.\r | |
768 | inx d\r | |
769 | mov b,m ;Get from second file spec.\r | |
770 | inx h\r | |
771 | cmp b ;Compare.\r | |
772 | jnz cmfrc5 ;Ambiguous.\r | |
773 | inr c ;Same, count.\r | |
774 | cpi ' ' ;Blank?\r | |
775 | jz cmfrl2 ;Yes, don't output.\r | |
776 | call cmfput ;Put character into buffer.\r | |
777 | jmp cmfrl2 ;Repeat.\r | |
778 | \r | |
779 | cmfrc5: mov a,c ;Get count of characters processed.\r | |
780 | sta temp1 ;Save it.\r | |
781 | mvi a,'$' ;Get terminator.\r | |
782 | call cmfput ;Put it into buffer.\r | |
783 | lhld cmdptr ;Output recognized characters.\r | |
784 | xchg\r | |
785 | mvi c,prstr\r | |
786 | call bdos\r | |
787 | lhld cmcptr ;Remove terminator from buffer.\r | |
788 | dcx h\r | |
789 | shld cmcptr\r | |
790 | lxi h,cmccnt\r | |
791 | dcr m\r | |
792 | lda temp1 ;Characters processed.\r | |
793 | cpi 11 ;Complete file name.\r | |
794 | jz repars ;Yes, don't beep.\r | |
795 | \r | |
796 | cmfrc9: mvi c,conout\r | |
797 | mvi e,bell\r | |
798 | call bdos ;Ring the bell.\r | |
799 | jmp repars\r | |
800 | ;\f\r | |
801 | ; Continue file spec parsing.\r | |
802 | \r | |
803 | cmif13: mov a,e ;It must be a terminator.\r | |
804 | ora a ;Test the length of the file name.\r | |
805 | jz cmifi9 ;If zero complain.\r | |
806 | cpi 0DH\r | |
807 | jp cmifi9 ;If too long complain.\r | |
808 | jmp rskp ;Otherwise we have succeeded.\r | |
809 | \r | |
810 | cmifi2: cpi '.'\r | |
811 | jnz cmifi3\r | |
812 | inr e\r | |
813 | mov a,e\r | |
814 | cpi 1H ;Any chars yet?\r | |
815 | jz cmifi9 ;No, give error.\r | |
816 | cpi 0AH ;Tenth char?\r | |
817 | jp cmifi9 ;Past it, give an error.\r | |
818 | mvi c,9H\r | |
819 | mvi b,0\r | |
820 | lhld cmfcb\r | |
821 | dad b ;Point to file type field.\r | |
822 | shld cmfcb2\r | |
823 | mvi e,9H ;Say we've gotten nine.\r | |
824 | jmp cmifi1 ;Get the next char.\r | |
825 | \r | |
826 | cmifi3: cpi ':'\r | |
827 | jnz cmifi4\r | |
828 | inr e\r | |
829 | mov a,e\r | |
830 | cpi 2H ;Is it in the right place for a drive?\r | |
831 | jnz cmifi9 ;If not, complain.\r | |
832 | lhld cmfcb2\r | |
833 | dcx h ;Point to previous character.\r | |
834 | mov a,m ;Get the drive name.\r | |
835 | sui '@' ;Get the drive number.\r | |
836 | shld cmfcb2 ;Save pointer to beginning of name field.\r | |
837 | mvi m,space ;[obs] restore a space in FCB\r | |
838 | dcx h ;Point to drive number.\r | |
839 | mov m,a ;Put it in the fcb.\r | |
840 | mvi e,0 ;Start character count over.\r | |
841 | jmp cmifi1\r | |
842 | \r | |
843 | cmifi4: cpi '*'\r | |
844 | jnz cmifi7\r | |
845 | lda cmfwld ;Wildcards allowed?\r | |
846 | cpi 0\r | |
847 | jz cmif11 ;No,complain\r | |
848 | mov a,e\r | |
849 | cpi 8H ;Is this in the name or type field?\r | |
850 | jz cmifi9 ;If its where the dot should be give up.\r | |
851 | jp cmifi5 ;Type.\r | |
852 | mvi b,8H ;Eight chars.\r | |
853 | jmp cmifi6\r | |
854 | \r | |
855 | cmifi5: mvi b,0CH ;Three chars.\r | |
856 | cmifi6: lhld cmfcb2 ;Get a pointer into the FCB.\r | |
857 | mvi a,'?'\r | |
858 | mov m,a ;Put a question mark in.\r | |
859 | inx h\r | |
860 | shld cmfcb2\r | |
861 | inr e\r | |
862 | mov a,e\r | |
863 | cmp b\r | |
864 | jm cmifi6 ;Go fill in another.\r | |
865 | jmp cmifi1 ;Get the next char.\r | |
866 | \r | |
867 | cmifi7: cpi '!' ;[pcc007] control chr or space?\r | |
868 | jm cmifi9 ;[pcc007] yes, illegal\r | |
869 | mov h,a ;[5] stash input char for a bit\r | |
870 | lda ffussy ;[5] while we check the fussy flag\r | |
871 | ora a ;[5] set the flags accordingly\r | |
872 | mov a,h ;[5] restore the input character\r | |
873 | jz cmif7a ;[5] if ffussy=0, allow <>.,;:?*[]\r | |
874 | ;[5] So far, we've eliminated "action characters" (including question),\r | |
875 | ;[5] period, colon, asterisk, control characters, and space.\r | |
876 | ;[5] That leaves us %(),/;<=>[\]_| to check for.\r | |
877 | cpi '%' ;[5]\r | |
878 | jz cmifi9 ;[5]\r | |
879 | cpi '(' ;[5]\r | |
880 | jz cmifi9 ;[5]\r | |
881 | cpi ')' ;[5]\r | |
882 | jz cmifi9 ;[5]\r | |
883 | cpi ',' ;[pcc007] weed out comma\r | |
884 | jz cmifi9 ;[pcc007]\r | |
885 | cpi '/' ;[5]\r | |
886 | jz cmifi9 ;[5]\r | |
887 | cpi '9'+1 ;[pcc007] anything else 21H-39H is ok\r | |
888 | jm cmifi8 ;[pcc007] except '*' never gets here\r | |
889 | cpi '@' ;[pcc007] all of 3AH-3FH is illegal\r | |
890 | jm cmifi9 ;[pcc007]\r | |
891 | cpi '[' ;[pcc007] [\] also illegal\r | |
892 | jm cmifi8 ;[pcc007]\r | |
893 | cpi ']'+1 ;[pcc007]\r | |
894 | jm cmifi9 ;[pcc007]\r | |
895 | cpi '_' ;[5]\r | |
896 | jz cmifi9 ;[5] (If I was doing CP/M, I would have\r | |
897 | cpi '|' ;[5] just eliminated all them funny chars\r | |
898 | jz cmifi9 ;[5] instead of a random selection)\r | |
899 | cmif7a: ;[5]\r | |
900 | cpi 'a' ;[pcc007] if not lower case its ok\r | |
901 | jm cmifi8 ;[pcc007] (DEL never gets here)\r | |
902 | cpi 'z'+1 ;[pcc007] only convert letters\r | |
903 | jp cmifi8 ;[pcc007]\r | |
904 | ani 137O ;Capitalize.\r | |
905 | cmifi8: lhld cmfcb2 ;Get the pointer into the FCB.\r | |
906 | mov m,a ;Put the char there.\r | |
907 | inx h\r | |
908 | shld cmfcb2\r | |
909 | inr e\r | |
910 | jmp cmifi1\r | |
911 | \r | |
912 | cmifi9: lda cmstat\r | |
913 | cpi cmifin ;"silent"?\r | |
914 | jz r ;Yes,let him go w/o check\r | |
915 | lxi d,cmer02\r | |
916 | cmif10: mvi c,prstr\r | |
917 | call bdos\r | |
918 | ret\r | |
919 | \r | |
920 | cmif11: lxi d,cmer03 ;Complain about wildcards.\r | |
921 | jmp cmif10\r | |
922 | \r | |
923 | ;\f\r | |
924 | \r | |
925 | ; copy filename from buffer\r | |
926 | ; called with HL = destination, A = position (0-3) in buffer\r | |
927 | ; called by: cmifil\r | |
928 | \r | |
929 | fspcop: push psw ;Save A.\r | |
930 | lxi d,buff ;Get the right offset in the buffer.\r | |
931 | rlc\r | |
932 | rlc\r | |
933 | rlc\r | |
934 | rlc\r | |
935 | rlc\r | |
936 | add e\r | |
937 | inr a ;Bypass drive spec.\r | |
938 | mov e,a\r | |
939 | mvi b,11 ;Copy file name.\r | |
940 | fspcp1: ldax d\r | |
941 | inx d\r | |
942 | mov m,a\r | |
943 | inx h\r | |
944 | dcr b\r | |
945 | jnz fspcp1\r | |
946 | pop psw ;Restore A.\r | |
947 | ret\r | |
948 | \r | |
949 | ; append character in A to command buffer\r | |
950 | ; called by: cmifil\r | |
951 | \r | |
952 | cmfput: push h ;Save H.\r | |
953 | lhld cmcptr ;Get buffer pointer.\r | |
954 | mov m,a ;Store in buffer.\r | |
955 | inx h\r | |
956 | shld cmcptr\r | |
957 | lxi h,cmccnt ;Count it.\r | |
958 | inr m\r | |
959 | pop h ;Restore H.\r | |
960 | ret\r | |
961 | ;\f\r | |
962 | ; Read characters from the command buffer.\r | |
963 | ; called by: cmtext, cmcfrm, cmkeyw, cmifil\r | |
964 | \r | |
965 | cmgtch: push h\r | |
966 | push b\r | |
967 | cmgtc1: lda cmaflg\r | |
968 | ora a ;Is it set.\r | |
969 | cz cminbf ;If the action char flag is not set get more.\r | |
970 | lhld cmdptr ;Get a pointer into the buffer.\r | |
971 | mov a,m ;Get the next char.\r | |
972 | inx h\r | |
973 | shld cmdptr\r | |
974 | cpi ' ' ;Is it a space?\r | |
975 | jz cmgtc2\r | |
976 | cpi tab ;Or a tab?\r | |
977 | jnz cmgtc3\r | |
978 | cmgtc2: lda cmsflg ;Get the space flag.\r | |
979 | ora a ;Was the last char a space?\r | |
980 | jnz cmgtc1 ;Yes, get another char.\r | |
981 | mvi a,0FFH ;Set the space flag.\r | |
982 | sta cmsflg\r | |
983 | mvi a,' '\r | |
984 | pop b\r | |
985 | pop h\r | |
986 | jmp cmgtc5\r | |
987 | \r | |
988 | cmgtc3: push psw\r | |
989 | xra a\r | |
990 | sta cmsflg ;Zero the space flag.\r | |
991 | pop psw\r | |
992 | pop b\r | |
993 | pop h\r | |
994 | cpi esc\r | |
995 | jz cmgtc5\r | |
996 | cpi '?' ;Is the user curious?\r | |
997 | jz cmgtc4\r | |
998 | cpi cr\r | |
999 | jz cmgtc4\r | |
1000 | cpi lf\r | |
1001 | jz cmgtc4\r | |
1002 | cpi ff\r | |
1003 | rnz ;Not an action char, just return.\r | |
1004 | cmgtc4: push h\r | |
1005 | lhld cmdptr\r | |
1006 | dcx h\r | |
1007 | shld cmdptr\r | |
1008 | pop h\r | |
1009 | cmgtc5: ori 80H ;Make the char negative to indicate it is\r | |
1010 | ret ;a terminator.\r | |
1011 | ;\f\r | |
1012 | ; Read characters from console into command buffer, processing\r | |
1013 | ; editing characters (^H, ^M, ^J, ^L, ^U, ^X, ?, del).\r | |
1014 | ; called by: comnd, cmgtch\r | |
1015 | \r | |
1016 | cminbf: push psw\r | |
1017 | push d\r | |
1018 | push h\r | |
1019 | lda cmaflg ;Is the action char flag set?\r | |
1020 | ora a\r | |
1021 | jnz cminb9 ;If so get no more chars.\r | |
1022 | cminb1: lxi h,cmccnt ;Increment the char count.\r | |
1023 | inr m\r | |
1024 | mvi c,conin ;Get a char.\r | |
1025 | lda cmqflg ;[MF]but do we want it echoed?\r | |
1026 | ora a ;[MF]...\r | |
1027 | jz cmin1b ;[MF]Yup, proceed normally\r | |
1028 | cmin1c: mvi e,0ffH ;[MF]Nope, do it with Direct\r | |
1029 | mvi c,dconio ;[MF]Console I/O\r | |
1030 | call bdos ;[MF]...\r | |
1031 | ora a ;[MF]Did the user type anything?\r | |
1032 | jz cmin1c ;[MF]No, don't go on until he/she does.\r | |
1033 | jmp cmin1a ;[MF]We got a character\r | |
1034 | cmin1b: call bdos\r | |
1035 | cmin1a: lhld cmcptr ;Get the pointer into the buffer.\r | |
1036 | mov m,a ;Put it in the buffer.\r | |
1037 | inx h\r | |
1038 | shld cmcptr\r | |
1039 | cpi 25O ;Is it a ^U?\r | |
1040 | jz cmnb12 ;Yes.\r | |
1041 | cpi 30O ;Is it a ^X?\r | |
1042 | jnz cminb2\r | |
1043 | cmnb12: call clrlin ;Clear the line.\r | |
1044 | call prprmp ;Print the prompt [Toad Hall]\r | |
1045 | lxi h,cmdbuf\r | |
1046 | shld cmcptr ;Reset the point to the start.\r | |
1047 | lxi h,cmccnt ;Zero the count.\r | |
1048 | mvi m,0\r | |
1049 | jmp repars ;Go start over.\r | |
1050 | \r | |
1051 | cminb2: cpi 10O ;Backspace?\r | |
1052 | jz cminb3\r | |
1053 | cpi del ;or Delete?\r | |
1054 | jnz cminb4\r | |
1055 | lda cmqflg ;[MF]If we are echoing characters,\r | |
1056 | ora a ;[MF]...\r | |
1057 | cz delchr ;Print the delete string. [MF]\r | |
1058 | cminb3: lda cmccnt ;Decrement the char count by two.\r | |
1059 | dcr a\r | |
1060 | dcr a\r | |
1061 | ora a ;Have we gone too far?\r | |
1062 | jp cmnb32 ;If not proceed.\r | |
1063 | mvi c,conout ;Ring the bell.\r | |
1064 | mvi e,bell\r | |
1065 | call bdos\r | |
1066 | jmp cmnb12 ;Go reprint prompt and reparse.\r | |
1067 | \r | |
1068 | cmnb32: sta cmccnt ;Save the new char count.\r | |
1069 | lda cmqflg ;[MF]Echoing characters?\r | |
1070 | ora a ;[MF]If we are, then\r | |
1071 | cz clrspc ;Erase the character. [MF]\r | |
1072 | lhld cmcptr ;Get the pointer into the buffer.\r | |
1073 | dcx h ;Back up in the buffer.\r | |
1074 | dcx h\r | |
1075 | shld cmcptr\r | |
1076 | jmp repars ;Go reparse everything.\r | |
1077 | \r | |
1078 | cminb4: cpi '?' ;Is it a question mark.\r | |
1079 | jz cminb6\r | |
1080 | cpi esc ;Is it an escape?\r | |
1081 | jz cminb6\r | |
1082 | cpi cr ;Is it a carriage return?\r | |
1083 | jz cminb5\r | |
1084 | cpi lf ;Is it a line feed?\r | |
1085 | jz cminb5\r | |
1086 | cpi ff ;Is it a formfeed?\r | |
1087 | jnz cminb8 ;no - just store it and \r | |
1088 | ;test if buffer overflowing, else get another character.\r | |
1089 | call clrtop\r | |
1090 | cminb5: lda cmbflg ;[MF]Allowing initial blank word (<cr>)?\r | |
1091 | ora a ;[MF]...\r | |
1092 | jnz cminb6 ;[MF]Yes\r | |
1093 | lda cmccnt ;Have we parsed any chars yet?\r | |
1094 | cpi 1\r | |
1095 | jz prserr ;If not, just start over.\r | |
1096 | cminb6: mvi a,0FFH ;Set the action flag.\r | |
1097 | sta cmaflg\r | |
1098 | jmp cminb9\r | |
1099 | \r | |
1100 | cminb8:\r | |
1101 | lda cmccnt ; get the command character count\r | |
1102 | cpi cmbufl ; check for comand buffer length\r | |
1103 | jm cminb1 ; if less, then all ok\r | |
1104 | mvi e,bell ; else beep at user\r | |
1105 | call outcon ; send it to the console\r | |
1106 | lda cmccnt ; back up one character\r | |
1107 | dcr a\r | |
1108 | sta cmccnt\r | |
1109 | lhld cmcptr ; ditto pointer\r | |
1110 | dcx h\r | |
1111 | shld cmcptr ; save it again\r | |
1112 | jmp cminb1 ; and try again\r | |
1113 | \r | |
1114 | cminb9: pop h\r | |
1115 | pop d\r | |
1116 | pop psw\r | |
1117 | ret\r | |
1118 | ;\f\r | |
1119 | ;Little utility to print the prompt. (We do a LOT of these.) [Toad Hall]\r | |
1120 | ;Enters with nothing.\r | |
1121 | ;Destroys HL (and I suppose B and DE and A).\r | |
1122 | \r | |
1123 | prprmp: mvi e,cr ; do a cr first\r | |
1124 | mvi c,dconio\r | |
1125 | call bdos\r | |
1126 | lhld cmprmp ;Get the prompt.\r | |
1127 | xchg\r | |
1128 | call prtstr\r | |
1129 | ret\r | |
1130 | \r | |
1131 | ; Little code to allow some expansion of code without changing\r | |
1132 | ; every futher address, only up to the end of this file.\r | |
1133 | ; TO BE REMOVED FOR RELEASE!\r | |
1134 | \r | |
1135 | ; org ($+100h) AND 0FF00H\r | |
1136 | \r | |
1137 | \r | |
1138 | IF lasm\r | |
1139 | LINK CPSUTL\r | |
1140 | ENDIF ;lasm [Toad Hall]\r |