summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/TENV.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/COMMAND/TENV.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/COMMAND/TENV.ASM')
-rw-r--r--v4.0/src/CMD/COMMAND/TENV.ASM633
1 files changed, 633 insertions, 0 deletions
diff --git a/v4.0/src/CMD/COMMAND/TENV.ASM b/v4.0/src/CMD/COMMAND/TENV.ASM
new file mode 100644
index 0000000..e1d43f6
--- /dev/null
+++ b/v4.0/src/CMD/COMMAND/TENV.ASM
@@ -0,0 +1,633 @@
1 page 80,132
2; SCCSID = @(#)tenv.asm 4.2 85/08/16
3; SCCSID = @(#)tenv.asm 4.2 85/08/16
4TITLE Part6 COMMAND Transient routines.
5
6; Environment utilities and misc. routines
7
8 INCLUDE comsw.asm
9
10.xlist
11.xcref
12 INCLUDE DOSSYM.INC
13 INCLUDE comseg.asm
14 INCLUDE comequ.asm
15 INCLUDE DOSCNTRY.INC ;AN000;
16.list
17.cref
18
19
20DATARES SEGMENT PUBLIC BYTE ;AC000;
21 EXTRN comdrv:byte
22 EXTRN comspec_end:word
23 EXTRN comspec_print:word
24 EXTRN cpdrv:byte
25 EXTRN dbcs_vector_addr:dword ;AN000;
26 EXTRN ENVIRSEG:WORD
27 EXTRN fucase_addr:word ;AC000;
28 EXTRN RESTDIR:BYTE
29DATARES ENDS
30
31TRANDATA SEGMENT PUBLIC BYTE ;AC000;
32 EXTRN arg_buf_ptr:word
33 EXTRN comspec:byte
34 EXTRN comspec_flag:byte
35 EXTRN comspecstr:byte
36 EXTRN ENVERR_PTR:WORD
37 EXTRN PATH_TEXT:byte
38 EXTRN PROMPT_TEXT:byte
39 EXTRN SYNTMES_PTR:WORD
40TRANDATA ENDS
41
42TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
43 EXTRN Arg_Buf:BYTE
44 EXTRN RESSEG:WORD
45 EXTRN USERDIR1:BYTE
46TRANSPACE ENDS
47
48TRANCODE SEGMENT PUBLIC byte
49
50ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
51
52 EXTRN cerror:near
53
54 PUBLIC add_name_to_environment
55 PUBLIC add_prompt
56 PUBLIC delete_path
57 PUBLIC find_name_in_environment
58 PUBLIC find_path
59 PUBLIC find_prompt
60 PUBLIC move_name
61 PUBLIC restudir
62 PUBLIC restudir1
63 PUBLIC scan_double_null
64 PUBLIC scasb2
65 PUBLIC store_char
66 PUBLIC Testkanj ;AN000; 3/3/KK
67 PUBLIC upconv
68
69BREAK <Environment utilities>
70ASSUME DS:TRANGROUP
71
72 break Prompt command
73assume ds:trangroup,es:trangroup
74
75ADD_PROMPT:
76 CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT
77 CALL SCAN_DOUBLE_NULL
78
79ADD_PROMPT2:
80 PUSH SI
81 CALL GETARG
82 POP SI
83 retz ; PRE SCAN FOR ARGUMENTS
84 CALL MOVE_NAME ; MOVE IN NAME
85 CALL GETARG
86 PUSH SI
87 JMP SHORT ADD_NAME
88
89
90 break The SET command
91assume ds:trangroup,es:trangroup
92
93;
94; Input: DS:SI points to a CR terminated string
95; Output: carry flag is set if no room
96; otherwise name is added to environment
97;
98
99DISP_ENVj:
100 jmp DISP_ENV
101
102ADD_NAME_TO_ENVIRONMENT:
103 CALL GETARG
104 JZ DISP_ENVj
105;
106; check if line contains exactly one equals sign
107;
108 XOR BX,BX ;= COUNT IS 0
109 PUSH SI ;SAVE POINTER TO BEGINNING OF LINE
110
111EQLP:
112 LODSB ;GET A CHAR
113 CMP AL,13 ;IF CR WE'RE ALL DONE
114 JZ QUEQ
115 CMP AL,'=' ;LOOK FOR = SIGN
116 JNZ EQLP ;NOT THERE, GET NEXT CHAR
117 INC BL ;OTHERWISE INCREMENT EQ COUNT
118 CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN
119 JNZ EQLP
120 INC BH ;SET BH=1 MEANS NO PARAMETERS
121 JMP EQLP ;AND LOOK FOR MORE
122
123QUEQ:
124 POP SI ;RESTORE BEGINNING OF LINE
125 DEC BL ;ZERO FLAG MEANS ONLY ONE EQ
126 JZ ONEQ ;GOOD LINE
127 MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
128 JMP CERROR
129
130ONEQ:
131 PUSH BX
132 CALL DELETE_NAME_IN_ENVIRONMENT
133 POP BX
134 DEC BH
135 retz
136
137 CALL SCAN_DOUBLE_NULL
138 mov bx,di ; Save ptr to beginning of env var name
139 CALL MOVE_NAME
140 push si
141 xchg bx,di ; Switch ptrs to beginning and end of
142 ; env var name
143;
144; We want to special-case COMSPEC. This is to reduce the amount of code
145; necessary in the resident for re-reading the transient. Let's look for
146; COMSPEC=
147;
148 mov si,offset trangroup:comspecstr ; Load ptr to string "COMSPEC"
149 mov cx,4 ; If the new env var is comspec, set
150 repz cmpsw ; the comspec_flag
151;
152; Zero set => exact match
153;
154 jnz not_comspec
155 mov comspec_flag,1
156
157not_comspec:
158 mov di,bx ; Load ptr to end of env var name
159
160ADD_NAME: ; Add the value of the new env var
161 pop si ; to the environment.
162 push si
163
164add_name1:
165 LODSB
166 CMP AL,13
167 jz add_name_ret
168 CALL STORE_CHAR
169 JMP ADD_NAME1
170
171add_name_ret:
172 pop si
173 cmp comspec_flag,0 ; If the new env var is comspec,
174 retz ; copy the value into the
175;
176; We have changed the COMSPEC variable. We need to update the resident
177; pieces necessary to reread in the info. First, skip all delimiters
178;
179 invoke ScanOff
180 mov es,[resseg] ; comspec var in the resident
181 assume es:resgroup
182;
183; Make sure that the printer knows where the beginning of the string is
184;
185 mov di,offset resgroup:comspec
186 mov bx,di
187;
188; Generate drive letter for display
189;
190 xor ax,ax ;g assume no drive first
191 mov comdrv,al ;g
192 push ax ;AN000; 3/3/KK
193 mov al,[si] ;AN000; 3/3/KK
194 call testkanj ;AN000; 3/3/KK
195 pop ax ;AN000; 3/3/KK
196 jnz GotDrive
197 cmp byte ptr [si+1],':' ; drive specified?
198 jnz GotDrive
199 mov al,[si] ; get his specified drive
200 call UpConv ; convert to uppercase
201 sub al,'A' ; convert to 0-based
202 add di,2
203 inc al ; convert to 1-based number
204 mov comdrv,al
205;
206; Stick the drive letter in the prompt message. Nothing special needs to be
207; done here..
208;
209
210 add al,'A'-1
211
212GotDrive: ;g
213 mov comspec_print,di ;g point to beginning of name after drive
214 mov es:cpdrv,al
215;
216; Copy chars until delim
217;
218
219 mov di,bx
220
221copy_comspec:
222 lodsb
223 invoke Delim
224 jz CopyDone
225 cmp al,13
226 jz CopyDone
227 stosb
228 jmp short copy_comspec
229
230CopyDone:
231 xor al,al ; Null terminate the string and quit
232 stosb
233 mov comspec_flag,0
234 dec di
235 mov comspec_end,di
236
237 ret
238
239DISP_ENV:
240 MOV DS,[RESSEG]
241ASSUME DS:RESGROUP
242 MOV DS,[ENVIRSEG]
243ASSUME DS:NOTHING
244 XOR SI,SI
245
246PENVLP:
247 CMP BYTE PTR [SI],0
248 retz
249 mov di,offset trangroup:arg_buf
250
251PENVLP2:
252 LODSB
253 stosb
254 OR AL,AL
255 JNZ PENVLP2
256 mov dx,offset trangroup:arg_buf_ptr
257 push ds
258 push es
259 pop ds
260 invoke printf_crlf
261 pop ds
262 JMP PENVLP
263
264ASSUME DS:TRANGROUP
265
266DELETE_PATH:
267 MOV SI,OFFSET TRANGROUP:PATH_TEXT
268 JMP SHORT DELETE_NAME_IN_environment
269
270DELETE_PROMPT:
271 MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
272
273DELETE_NAME_IN_environment:
274;
275; Input: DS:SI points to a "=" terminated string
276; Output: carry flag is set if name not found
277; otherwise name is deleted
278;
279 PUSH SI
280 PUSH DS
281 CALL FIND ; ES:DI POINTS TO NAME
282 JC DEL1
283 MOV SI,DI ; SAVE IT
284 CALL SCASB2 ; SCAN FOR THE NUL
285 XCHG SI,DI
286 CALL GETENVSIZ
287 SUB CX,SI
288 PUSH ES
289 POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
290 REP MOVSB ; DELETE THE NAME
291
292DEL1:
293 POP DS
294 POP SI
295 return
296
297FIND_PATH:
298 MOV SI,OFFSET TRANGROUP:PATH_TEXT
299 JMP SHORT FIND_NAME_IN_environment
300
301FIND_PROMPT:
302 MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
303
304FIND_NAME_IN_environment:
305;
306; Input: DS:SI points to a "=" terminated string
307; Output: ES:DI points to the arguments in the environment
308; zero is set if name not found
309; carry flag is set if name not valid format
310;
311 CALL FIND ; FIND THE NAME
312 retc ; CARRY MEANS NOT FOUND
313 JMP SCASB1 ; SCAN FOR = SIGN
314;
315; On return of FIND1, ES:DI points to beginning of name
316;
317FIND:
318 CLD
319 CALL COUNT0 ; CX = LENGTH OF NAME
320 MOV ES,[RESSEG]
321ASSUME ES:RESGROUP
322 MOV ES,[ENVIRSEG]
323ASSUME ES:NOTHING
324 XOR DI,DI
325
326FIND1:
327 PUSH CX
328 PUSH SI
329 PUSH DI
330
331FIND11:
332 LODSB
333 CALL TESTKANJ
334 JZ NOTKANJ3
335 DEC SI
336 LODSW
337 INC DI
338 INC DI
339 CMP AX,ES:[DI-2]
340 JNZ FIND12
341 DEC CX
342 LOOP FIND11
343 JMP SHORT FIND12
344
345NOTKANJ3:
346 CALL UPCONV
347 INC DI
348 CMP AL,ES:[DI-1]
349 JNZ FIND12
350 LOOP FIND11
351
352FIND12:
353 POP DI
354 POP SI
355 POP CX
356 retz
357 PUSH CX
358 CALL SCASB2 ; SCAN FOR A NUL
359 POP CX
360 CMP BYTE PTR ES:[DI],0
361 JNZ FIND1
362 STC ; INDICATE NOT FOUND
363 return
364
365COUNT0:
366 PUSH DS
367 POP ES
368 MOV DI,SI
369
370COUNT1:
371 PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
372 CALL SCASB1
373 JMP SHORT COUNTX
374
375COUNT2:
376 PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
377 CALL SCASB2
378
379COUNTX:
380 POP CX
381 SUB DI,CX
382 XCHG DI,CX
383 return
384
385MOVE_NAME:
386 CMP BYTE PTR DS:[SI],13
387 retz
388 LODSB
389
390;;;; IF KANJI 3/3/KK
391 CALL TESTKANJ
392 JZ NOTKANJ1
393 CALL STORE_CHAR
394 LODSB
395 CALL STORE_CHAR
396 JMP SHORT MOVE_NAME
397
398NOTKANJ1:
399;;;; ENDIF 3/3/KK
400
401 CALL UPCONV
402 CALL STORE_CHAR
403 CMP AL,'='
404 JNZ MOVE_NAME
405 return
406
407GETARG:
408 MOV SI,80H
409 LODSB
410 OR AL,AL
411 retz
412 invoke SCANOFF
413 CMP AL,13
414 return
415
416;
417; Point ES:DI to the final NULL string. Note that in an empty environment,
418; there is NO double NULL, merely a string that is empty.
419;
420SCAN_DOUBLE_NULL:
421 MOV ES,[RESSEG]
422ASSUME ES:RESGROUP
423 MOV ES,[ENVIRSEG]
424ASSUME ES:NOTHING
425 XOR DI,DI
426;
427; Top cycle-point. If the string here is empty, then we are done
428;
429SDN1:
430 cmp byte ptr es:[di],0 ; nul string?
431 retz ; yep, all done
432 CALL SCASB2
433 JMP SDN1
434
435SCASB1:
436 MOV AL,'=' ; SCAN FOR AN =
437 JMP SHORT SCASBX
438SCASB2:
439 XOR AL,AL ; SCAN FOR A NUL
440SCASBX:
441 MOV CX,100H
442 REPNZ SCASB
443 return
444
445TESTKANJ:
446 push ds ;AN000; 3/3/KK
447 push si ;AN000; 3/3/KK
448 push ax ;AN000; 3/3/KK
449 mov ds,cs:[resseg] ;AN000; Get resident segment
450 assume ds:resgroup ;AN000;
451 lds si,dbcs_vector_addr ;AN000; get DBCS vector
452ktlop: ;AN000; 3/3/KK
453 cmp word ptr ds:[si],0 ;AN000; end of Table 3/3/KK
454 je notlead ;AN000; 3/3/KK
455 pop ax ;AN000; 3/3/KK
456 push ax ;AN000; 3/3/KK
457 cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
458 jb notlead ;AN000; 3/3/KK
459 inc si ;AN000; 3/3/KK
460 cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
461 jbe islead ;AN000; 3/3/KK
462 inc si ;AN000; 3/3/KK
463 jmp short ktlop ;AN000; try another range ; 3/3/KK
464Notlead: ;AN000; 3/3/KK
465 xor ax,ax ;AN000; set zero 3/3/KK
466 jmp short ktret ;AN000; 3/3/KK
467Islead: ;AN000; 3/3/KK
468 xor ax,ax ;AN000; reset zero 3/3/KK
469 inc ax ;AN000; 3/3/KK
470ktret: ;AN000; 3/3/KK
471 pop ax ;AN000; 3/3/KK
472 pop si ;AN000; 3/3/KK
473 pop ds ;AN000; 3/3/KK
474 return ;AN000; 3/3/KK
475;------------------------------------- ;3/3/KK
476
477
478; ****************************************************************
479; *
480; * ROUTINE: UPCONV (ADDED BY EMG 4.00)
481; *
482; * FUNCTION: This routine returns the upper case equivalent of
483; * the character in AL from the file upper case table
484; * in DOS if character if above ascii 128, else
485; * subtracts 20H if between "a" and "z".
486; *
487; * INPUT: AL char to be upper cased
488; * FUCASE_ADDR set to the file upper case table
489; *
490; * OUTPUT: AL upper cased character
491; *
492; ****************************************************************
493
494assume ds:trangroup ;AN000;
495
496upconv proc near ;AN000;
497
498 cmp al,80h ;AN000; see if char is > ascii 128
499 jb oth_fucase ;AN000; no - upper case math
500 sub al,80h ;AN000; only upper 128 chars in table
501 push ds ;AN000;
502 push bx ;AN000;
503 mov ds,[resseg] ;AN000; get resident data segment
504assume ds:resgroup ;AN000;
505 lds bx,dword ptr fucase_addr+1 ;AN000; get table address
506 add bx,2 ;AN000; skip over first word
507 xlat ds:byte ptr [bx] ;AN000; convert to upper case
508 pop bx ;AN000;
509 pop ds ;AN000;
510assume ds:trangroup ;AN000;
511 jmp short upconv_end ;AN000; we finished - exit
512
513oth_fucase: ;AN000;
514 cmp al,small_a ;AC000; if between "a" and "z",
515 jb upconv_end ;AC000; subtract 20h to get
516 cmp al,small_z ;AC000; upper case equivalent.
517 ja upconv_end ;AC000;
518 sub al,20h ;AC000; Change lower-case to upper
519
520upconv_end: ;AN000;
521 ret
522
523upconv endp ;AN000;
524
525
526;
527; STORE A CHAR IN environment, GROWING IT IF NECESSARY
528;
529STORE_CHAR:
530 PUSH CX
531 PUSH BX
532 PUSH ES ;AN056;
533 PUSH DS ;AN056; Save local DS
534 MOV DS,[RESSEG] ;AN056; Get resident segment
535 ASSUME DS:RESGROUP ;AN056;
536 MOV ES,[ENVIRSEG] ;AN056; Get environment segment
537 ASSUME ES:NOTHING ;AN056;
538 POP DS ;AN056; Get local segment back
539 ASSUME DS:TRANGROUP ;AN056;
540 CALL GETENVSIZ
541 MOV BX,CX
542 SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL
543 CMP DI,BX
544 JB STORE1
545
546 PUSH AX
547 PUSH CX
548 PUSH BX ; Save Size of environment
549 invoke FREE_TPA
550 POP BX
551 ADD BX,2 ; Recover true environment size
552
553 CMP BX, 8000H ; Don't let environment grow > 32K
554 JB ENVSIZ_OK
555BAD_ENV_SIZE: ;AN056;
556 STC
557 JMP ENVNOSET
558ENVSIZ_OK:
559
560 MOV CL,4
561 SHR BX,CL ; Convert back to paragraphs
562 INC BX ; Try to grow environment by one para
563 MOV CX,ES ;AN056; Get environment segment
564 ADD CX,BX ;AN056; Add in size of environment
565 ADD CX,020H ;AN056; Add in some TPA
566 MOV AX,CS ;AN056; Get the transient segment
567 CMP CX,AX ;AN056; Are we hitting the transient?
568 JNB BAD_ENV_SIZE ;AN056; Yes - don't do it!!!
569 MOV AH,SETBLOCK
570 INT int_command
571ENVNOSET:
572 PUSHF
573 PUSH ES
574 MOV ES,[RESSEG]
575 invoke ALLOC_TPA
576 POP ES
577 POPF
578 POP CX
579 POP AX
580 JNC STORE1
581 POP ES ;AN056;
582 MOV DX,OFFSET TRANGROUP:ENVERR_ptr
583 JMP CERROR
584STORE1:
585 STOSB
586 MOV WORD PTR ES:[DI],0 ; NULL IS AT END
587 POP ES ;AN056;
588 POP BX
589 POP CX
590 return
591
592GETENVSIZ:
593;Get size of environment in bytes, rounded up to paragraph boundry
594;ES has environment segment
595;Size returned in CX, all other registers preserved
596
597 PUSH ES
598 PUSH AX
599 MOV AX,ES
600 DEC AX ;Point at arena
601 MOV ES,AX
602 MOV AX,ES:[arena_size]
603 MOV CL,4
604 SHL AX,CL ;Convert to bytes
605 MOV CX,AX
606 POP AX
607 POP ES
608 return
609
610
611ASSUME DS:TRANGROUP
612
613
614RESTUDIR1:
615 PUSH DS
616 MOV DS,[RESSEG]
617ASSUME DS:RESGROUP
618 CMP [RESTDIR],0
619 POP DS
620ASSUME DS:TRANGROUP
621 retz
622
623RESTUDIR:
624 MOV DX,OFFSET TRANGROUP:USERDIR1
625 MOV AH,CHDIR
626 INT int_command ; Restore users DIR
627 XOR AL,AL
628 invoke SETREST
629RET56:
630 return
631
632trancode ends
633 end