2 ; SCCSID = @(#)tenv.asm 4.2 85/08/16
3 ; SCCSID = @(#)tenv.asm 4.2 85/08/16
4 TITLE Part6 COMMAND Transient routines
.
6 ; Environment utilities and misc. routines
15 INCLUDE DOSCNTRY
.INC ;AN000;
20 DATARES
SEGMENT PUBLIC BYTE ;AC000;
22 EXTRN comspec_end
:word
23 EXTRN comspec_print
:word
25 EXTRN dbcs_vector_addr
:dword ;AN000;
27 EXTRN fucase_addr
:word ;AC000;
31 TRANDATA
SEGMENT PUBLIC BYTE ;AC000;
32 EXTRN arg_buf_ptr
:word
34 EXTRN comspec_flag
:byte
38 EXTRN PROMPT_TEXT
:byte
39 EXTRN SYNTMES_PTR
:WORD
42 TRANSPACE
SEGMENT PUBLIC BYTE ;AC000;
48 TRANCODE
SEGMENT PUBLIC byte
50 ASSUME
CS:TRANGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
54 PUBLIC add_name_to_environment
57 PUBLIC find_name_in_environment
63 PUBLIC scan_double_null
66 PUBLIC Testkanj
;AN000; 3/3/KK
69 BREAK <Environment utilities
>
73 assume
ds:trangroup
,es:trangroup
76 CALL DELETE_PROMPT
; DELETE ANY EXISTING PROMPT
83 retz
; PRE SCAN FOR ARGUMENTS
84 CALL MOVE_NAME
; MOVE IN NAME
91 assume
ds:trangroup
,es:trangroup
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
102 ADD_NAME_TO_ENVIRONMENT:
106 ; check if line contains exactly one equals sign
108 XOR BX,BX ;= COUNT IS 0
109 PUSH SI ;SAVE POINTER TO BEGINNING OF LINE
113 CMP AL,13 ;IF CR WE'RE ALL DONE
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
120 INC BH ;SET BH=1 MEANS NO PARAMETERS
121 JMP EQLP
;AND LOOK FOR MORE
124 POP SI ;RESTORE BEGINNING OF LINE
125 DEC BL ;ZERO FLAG MEANS ONLY ONE EQ
127 MOV DX,OFFSET TRANGROUP
:SYNTMES_ptr
132 CALL DELETE_NAME_IN_ENVIRONMENT
137 CALL SCAN_DOUBLE_NULL
138 mov bx,di ; Save ptr to beginning of env var name
141 xchg bx,di ; Switch ptrs to beginning and end of
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
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
152 ; Zero set => exact match
158 mov di,bx ; Load ptr to end of env var name
160 ADD_NAME: ; Add the value of the new env var
161 pop si ; to the environment.
173 cmp comspec_flag
,0 ; If the new env var is comspec,
174 retz
; copy the value into the
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
180 mov es,[resseg
] ; comspec var in the resident
183 ; Make sure that the printer knows where the beginning of the string is
185 mov di,offset resgroup
:comspec
188 ; Generate drive letter for display
190 xor ax,ax ;g assume no drive first
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
197 cmp byte ptr [si+1],':' ; drive specified?
199 mov al,[si] ; get his specified drive
200 call UpConv
; convert to uppercase
201 sub al,'A' ; convert to 0-based
203 inc al ; convert to 1-based number
206 ; Stick the drive letter in the prompt message. Nothing special needs to be
213 mov comspec_print
,di ;g point to beginning of name after drive
216 ; Copy chars until delim
228 jmp short copy_comspec
231 xor al,al ; Null terminate the string and quit
249 mov di,offset trangroup
:arg_buf
256 mov dx,offset trangroup
:arg_buf_ptr
267 MOV SI,OFFSET TRANGROUP
:PATH_TEXT
268 JMP SHORT DELETE_NAME_IN_environment
271 MOV SI,OFFSET TRANGROUP
:PROMPT_TEXT
273 DELETE_NAME_IN_environment:
275 ; Input: DS:SI points to a "=" terminated string
276 ; Output: carry flag is set if name not found
277 ; otherwise name is deleted
281 CALL FIND
; ES:DI POINTS TO NAME
284 CALL SCASB2
; SCAN FOR THE NUL
289 POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
290 REP MOVSB ; DELETE THE NAME
298 MOV SI,OFFSET TRANGROUP
:PATH_TEXT
299 JMP SHORT FIND_NAME_IN_environment
302 MOV SI,OFFSET TRANGROUP
:PROMPT_TEXT
304 FIND_NAME_IN_environment:
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
311 CALL FIND
; FIND THE NAME
312 retc
; CARRY MEANS NOT FOUND
313 JMP SCASB1
; SCAN FOR = SIGN
315 ; On return of FIND1, ES:DI points to beginning of name
319 CALL COUNT0
; CX = LENGTH OF NAME
358 CALL SCASB2
; SCAN FOR A NUL
360 CMP BYTE PTR ES:[DI],0
362 STC ; INDICATE NOT FOUND
371 PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
376 PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
386 CMP BYTE PTR DS:[SI],13
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.
427 ; Top cycle-point. If the string here is empty, then we are done
430 cmp byte ptr es:[di],0 ; nul string?
436 MOV AL,'=' ; SCAN FOR AN =
439 XOR AL,AL ; SCAN FOR A NUL
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
452 ktlop: ;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
464 Notlead: ;AN000; 3/3/KK
465 xor ax,ax ;AN000; set zero 3/3/KK
466 jmp short ktret
;AN000; 3/3/KK
467 Islead: ;AN000; 3/3/KK
468 xor ax,ax ;AN000; reset zero 3/3/KK
469 inc ax ;AN000; 3/3/KK
470 ktret: ;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
478 ; ****************************************************************
480 ; * ROUTINE: UPCONV (ADDED BY EMG 4.00)
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".
487 ; * INPUT: AL char to be upper cased
488 ; * FUCASE_ADDR set to the file upper case table
490 ; * OUTPUT: AL upper cased character
492 ; ****************************************************************
494 assume
ds:trangroup
;AN000;
496 upconv proc
near ;AN000;
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
503 mov ds,[resseg
] ;AN000; get resident data segment
504 assume
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
510 assume
ds:trangroup
;AN000;
511 jmp short upconv_end
;AN000; we finished - exit
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
527 ; STORE A CHAR IN environment, GROWING IT IF NECESSARY
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;
542 SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL
548 PUSH BX ; Save Size of environment
551 ADD BX,2 ; Recover true environment size
553 CMP BX, 8000H
; Don't let environment grow > 32K
555 BAD_ENV_SIZE: ;AN056;
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!!!
582 MOV DX,OFFSET TRANGROUP
:ENVERR_ptr
586 MOV WORD PTR ES:[DI],0 ; NULL IS AT END
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
600 DEC AX ;Point at arena
602 MOV AX,ES:[arena_size
]
604 SHL AX,CL ;Convert to bytes
624 MOV DX,OFFSET TRANGROUP
:USERDIR1
626 INT int_command
; Restore users DIR