summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/TENV.ASM
blob: e1d43f6f034e1a08326e22da329c40f1ebfb2874 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
 page 80,132
;	SCCSID = @(#)tenv.asm	4.2 85/08/16
;	SCCSID = @(#)tenv.asm	4.2 85/08/16
TITLE	Part6 COMMAND Transient routines.

;	Environment utilities and misc. routines

	INCLUDE comsw.asm

.xlist
.xcref
	INCLUDE DOSSYM.INC
	INCLUDE comseg.asm
	INCLUDE comequ.asm
	INCLUDE DOSCNTRY.INC		;AN000;
.list
.cref


DATARES 	SEGMENT PUBLIC BYTE	;AC000;
	EXTRN	comdrv:byte
	EXTRN	comspec_end:word
	EXTRN	comspec_print:word
	EXTRN	cpdrv:byte
	EXTRN	dbcs_vector_addr:dword	;AN000;
	EXTRN	ENVIRSEG:WORD
	EXTRN	fucase_addr:word	;AC000;
	EXTRN	RESTDIR:BYTE
DATARES ENDS

TRANDATA	SEGMENT PUBLIC BYTE	;AC000;
	EXTRN	arg_buf_ptr:word
	EXTRN	comspec:byte
	EXTRN	comspec_flag:byte
	EXTRN	comspecstr:byte
	EXTRN	ENVERR_PTR:WORD
	EXTRN	PATH_TEXT:byte
	EXTRN	PROMPT_TEXT:byte
	EXTRN	SYNTMES_PTR:WORD
TRANDATA	ENDS

TRANSPACE	SEGMENT PUBLIC BYTE	;AC000;
	EXTRN	Arg_Buf:BYTE
	EXTRN	RESSEG:WORD
	EXTRN	USERDIR1:BYTE
TRANSPACE	ENDS

TRANCODE	SEGMENT PUBLIC byte

ASSUME	CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING

	EXTRN	cerror:near

	PUBLIC	add_name_to_environment
	PUBLIC	add_prompt
	PUBLIC	delete_path
	PUBLIC	find_name_in_environment
	PUBLIC	find_path
	PUBLIC	find_prompt
	PUBLIC	move_name
	PUBLIC	restudir
	PUBLIC	restudir1
	PUBLIC	scan_double_null
	PUBLIC	scasb2
	PUBLIC	store_char
	PUBLIC	Testkanj		;AN000;  3/3/KK
	PUBLIC	upconv

BREAK	<Environment utilities>
ASSUME DS:TRANGROUP

	break	Prompt command
assume	ds:trangroup,es:trangroup

ADD_PROMPT:
	CALL	DELETE_PROMPT			; DELETE ANY EXISTING PROMPT
	CALL	SCAN_DOUBLE_NULL

ADD_PROMPT2:
	PUSH	SI
	CALL	GETARG
	POP	SI
	retz					; PRE SCAN FOR ARGUMENTS
	CALL	MOVE_NAME			; MOVE IN NAME
	CALL	GETARG
	PUSH	SI
	JMP	SHORT ADD_NAME


	break	The SET command
assume	ds:trangroup,es:trangroup

;
; Input: DS:SI points to a CR terminated string
; Output: carry flag is set if no room
;	  otherwise name is added to environment
;

DISP_ENVj:
	jmp	DISP_ENV

ADD_NAME_TO_ENVIRONMENT:
	CALL	GETARG
	JZ	DISP_ENVj
;
; check if line contains exactly one equals sign
;
	XOR	BX,BX				;= COUNT IS 0
	PUSH	SI				;SAVE POINTER TO BEGINNING OF LINE

EQLP:
	LODSB					;GET A CHAR
	CMP	AL,13				;IF CR WE'RE ALL DONE
	JZ	QUEQ
	CMP	AL,'='                          ;LOOK FOR = SIGN
	JNZ	EQLP				;NOT THERE, GET NEXT CHAR
	INC	BL				;OTHERWISE INCREMENT EQ COUNT
	CMP	BYTE PTR [SI],13		;LOOK FOR CR FOLLOWING = SIGN
	JNZ	EQLP
	INC	BH				;SET BH=1 MEANS NO PARAMETERS
	JMP	EQLP				;AND LOOK FOR MORE

QUEQ:
	POP	SI				;RESTORE BEGINNING OF LINE
	DEC	BL				;ZERO FLAG MEANS ONLY ONE EQ
	JZ	ONEQ				;GOOD LINE
	MOV	DX,OFFSET TRANGROUP:SYNTMES_ptr
	JMP	CERROR

ONEQ:
	PUSH	BX
	CALL	DELETE_NAME_IN_ENVIRONMENT
	POP	BX
	DEC	BH
	retz

	CALL	SCAN_DOUBLE_NULL
	mov	bx,di				; Save ptr to beginning of env var name
	CALL	MOVE_NAME
	push	si
	xchg	bx,di				; Switch ptrs to beginning and end of
						;  env var name
;
; We want to special-case COMSPEC.  This is to reduce the amount of code
; necessary in the resident for re-reading the transient.  Let's look for
; COMSPEC=
;
	mov	si,offset trangroup:comspecstr	; Load ptr to string "COMSPEC"
	mov	cx,4				; If the new env var is comspec, set
	repz	cmpsw				;  the comspec_flag
;
; Zero set => exact match
;
	jnz	not_comspec
	mov	comspec_flag,1

not_comspec:
	mov	di,bx				; Load ptr to end of env var name

ADD_NAME:					; Add the value of the new env var
	pop	si				;  to the environment.
	push	si

add_name1:
	LODSB
	CMP	AL,13
	jz	add_name_ret
	CALL	STORE_CHAR
	JMP	ADD_NAME1

add_name_ret:
	pop	si
	cmp	comspec_flag,0			; If the new env var is comspec,
	retz					;  copy the value into the
;
; We have changed the COMSPEC variable.  We need to update the resident
; pieces necessary to reread in the info.  First, skip all delimiters
;
	invoke	ScanOff
	mov	es,[resseg]			;  comspec var in the resident
	assume	es:resgroup
;
; Make sure that the printer knows where the beginning of the string is
;
	mov	di,offset resgroup:comspec
	mov	bx,di
;
; Generate drive letter for display
;
	xor	ax,ax				;g assume no drive first
	mov	comdrv,al			;g
	push	ax				;AN000;  3/3/KK
	mov	al,[si] 			;AN000;  3/3/KK
	call	testkanj			;AN000;  3/3/KK
	pop	ax				;AN000;  3/3/KK
	jnz	GotDrive
	cmp	byte ptr [si+1],':'             ; drive specified?
	jnz	GotDrive
	mov	al,[si] 			; get his specified drive
	call	UpConv				; convert to uppercase
	sub	al,'A'                          ; convert to 0-based
	add	di,2
	inc	al				; convert to 1-based number
	mov	comdrv,al
;
; Stick the drive letter in the prompt message.  Nothing special needs to be
; done here..
;

	add	al,'A'-1

GotDrive:					;g
	mov	comspec_print,di		;g point to beginning of name after drive
	mov	es:cpdrv,al
;
; Copy chars until delim
;

	mov	di,bx

copy_comspec:
	lodsb
	invoke	Delim
	jz	CopyDone
	cmp	al,13
	jz	CopyDone
	stosb
	jmp	short copy_comspec

CopyDone:
	xor	al,al				; Null terminate the string and quit
	stosb
	mov	comspec_flag,0
	dec	di
	mov	comspec_end,di

	ret

DISP_ENV:
	MOV	DS,[RESSEG]
ASSUME	DS:RESGROUP
	MOV	DS,[ENVIRSEG]
ASSUME	DS:NOTHING
	XOR	SI,SI

PENVLP:
	CMP	BYTE PTR [SI],0
	retz
	mov	di,offset trangroup:arg_buf

PENVLP2:
	LODSB
	stosb
	OR	AL,AL
	JNZ	PENVLP2
	mov	dx,offset trangroup:arg_buf_ptr
	push	ds
	push	es
	pop	ds
	invoke	printf_crlf
	pop	ds
	JMP	PENVLP

ASSUME	DS:TRANGROUP

DELETE_PATH:
	MOV	SI,OFFSET TRANGROUP:PATH_TEXT
	JMP	SHORT DELETE_NAME_IN_environment

DELETE_PROMPT:
	MOV	SI,OFFSET TRANGROUP:PROMPT_TEXT

DELETE_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: carry flag is set if name not found
;	  otherwise name is deleted
;
	PUSH	SI
	PUSH	DS
	CALL	FIND				; ES:DI POINTS TO NAME
	JC	DEL1
	MOV	SI,DI				; SAVE IT
	CALL	SCASB2				; SCAN FOR THE NUL
	XCHG	SI,DI
	CALL	GETENVSIZ
	SUB	CX,SI
	PUSH	ES
	POP	DS				; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
	REP	MOVSB				; DELETE THE NAME

DEL1:
	POP	DS
	POP	SI
	return

FIND_PATH:
	MOV	SI,OFFSET TRANGROUP:PATH_TEXT
	JMP	SHORT FIND_NAME_IN_environment

FIND_PROMPT:
	MOV	SI,OFFSET TRANGROUP:PROMPT_TEXT

FIND_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: ES:DI points to the arguments in the environment
;	  zero is set if name not found
;	  carry flag is set if name not valid format
;
	CALL	FIND				; FIND THE NAME
	retc					; CARRY MEANS NOT FOUND
	JMP	SCASB1				; SCAN FOR = SIGN
;
; On return of FIND1, ES:DI points to beginning of name
;
FIND:
	CLD
	CALL	COUNT0				; CX = LENGTH OF NAME
	MOV	ES,[RESSEG]
ASSUME	ES:RESGROUP
	MOV	ES,[ENVIRSEG]
ASSUME	ES:NOTHING
	XOR	DI,DI

FIND1:
	PUSH	CX
	PUSH	SI
	PUSH	DI

FIND11:
	LODSB
	CALL	TESTKANJ
	JZ	NOTKANJ3
	DEC	SI
	LODSW
	INC	DI
	INC	DI
	CMP	AX,ES:[DI-2]
	JNZ	FIND12
	DEC	CX
	LOOP	FIND11
	JMP	SHORT FIND12

NOTKANJ3:
	CALL	UPCONV
	INC	DI
	CMP	AL,ES:[DI-1]
	JNZ	FIND12
	LOOP	FIND11

FIND12:
	POP	DI
	POP	SI
	POP	CX
	retz
	PUSH	CX
	CALL	SCASB2				; SCAN FOR A NUL
	POP	CX
	CMP	BYTE PTR ES:[DI],0
	JNZ	FIND1
	STC					; INDICATE NOT FOUND
	return

COUNT0:
	PUSH	DS
	POP	ES
	MOV	DI,SI

COUNT1:
	PUSH	DI				; COUNT NUMBER OF CHARS UNTIL "="
	CALL	SCASB1
	JMP	SHORT COUNTX

COUNT2:
	PUSH	DI				; COUNT NUMBER OF CHARS UNTIL NUL
	CALL	SCASB2

COUNTX:
	POP	CX
	SUB	DI,CX
	XCHG	DI,CX
	return

MOVE_NAME:
	CMP	BYTE PTR DS:[SI],13
	retz
	LODSB

;;;;	IF	KANJI			3/3/KK
	CALL	TESTKANJ
	JZ	NOTKANJ1
	CALL	STORE_CHAR
	LODSB
	CALL	STORE_CHAR
	JMP	SHORT MOVE_NAME

NOTKANJ1:
;;;;	ENDIF				3/3/KK

	CALL	UPCONV
	CALL	STORE_CHAR
	CMP	AL,'='
	JNZ	MOVE_NAME
	return

GETARG:
	MOV	SI,80H
	LODSB
	OR	AL,AL
	retz
	invoke	SCANOFF
	CMP	AL,13
	return

;
; Point ES:DI to the final NULL string.  Note that in an empty environment,
; there is NO double NULL, merely a string that is empty.
;
SCAN_DOUBLE_NULL:
	MOV	ES,[RESSEG]
ASSUME	ES:RESGROUP
	MOV	ES,[ENVIRSEG]
ASSUME	ES:NOTHING
	XOR	DI,DI
;
; Top cycle-point.  If the string here is empty, then we are done
;
SDN1:
	cmp	byte ptr es:[di],0		; nul string?
	retz					; yep, all done
	CALL	SCASB2
	JMP	SDN1

SCASB1:
	MOV	AL,'='                          ; SCAN FOR AN =
	JMP	SHORT SCASBX
SCASB2:
	XOR	AL,AL				; SCAN FOR A NUL
SCASBX:
	MOV	CX,100H
	REPNZ	SCASB
	return

TESTKANJ:
	push	ds				;AN000;  3/3/KK
	push	si				;AN000;  3/3/KK
	push	ax				;AN000;  3/3/KK
	mov	ds,cs:[resseg]			;AN000;  Get resident segment
	assume	ds:resgroup			;AN000;
	lds	si,dbcs_vector_addr		;AN000;  get DBCS vector
ktlop:						;AN000;  3/3/KK
	cmp	word ptr ds:[si],0		;AN000;  end of Table	3/3/KK
	je	notlead 			;AN000;  3/3/KK
	pop	ax				;AN000;  3/3/KK
	push	ax				;AN000;  3/3/KK
	cmp	al, byte ptr ds:[si]		;AN000;  3/3/KK
	jb	notlead 			;AN000;  3/3/KK
	inc	si				;AN000;  3/3/KK
	cmp	al, byte ptr ds:[si]		;AN000;  3/3/KK
	jbe	islead				;AN000;  3/3/KK
	inc	si				;AN000;  3/3/KK
	jmp	short ktlop			;AN000;  try another range ; 3/3/KK
Notlead:					;AN000;  3/3/KK
	xor	ax,ax				;AN000;  set zero 3/3/KK
	jmp	short ktret			;AN000;  3/3/KK
Islead: 					;AN000;  3/3/KK
	xor	ax,ax				;AN000;  reset zero  3/3/KK
	inc	ax				;AN000;  3/3/KK
ktret:						;AN000;  3/3/KK
	pop	ax				;AN000;  3/3/KK
	pop	si				;AN000;  3/3/KK
	pop	ds				;AN000;  3/3/KK
	return					;AN000;  3/3/KK
;-------------------------------------		;3/3/KK


; ****************************************************************
; *
; * ROUTINE:	 UPCONV     (ADDED BY EMG 4.00)
; *
; * FUNCTION:	 This routine returns the upper case equivalent of
; *		 the character in AL from the file upper case table
; *		 in DOS if character if above  ascii 128, else
; *		 subtracts 20H if between "a" and "z".
; *
; * INPUT:	 AL	      char to be upper cased
; *		 FUCASE_ADDR  set to the file upper case table
; *
; * OUTPUT:	 AL	      upper cased character
; *
; ****************************************************************

assume	ds:trangroup				;AN000;

upconv	proc	near				;AN000;

	cmp	al,80h				;AN000;  see if char is > ascii 128
	jb	oth_fucase			;AN000;  no - upper case math
	sub	al,80h				;AN000;  only upper 128 chars in table
	push	ds				;AN000;
	push	bx				;AN000;
	mov	ds,[resseg]			;AN000;  get resident data segment
assume	ds:resgroup				;AN000;
	lds	bx,dword ptr fucase_addr+1	;AN000;  get table address
	add	bx,2				;AN000;  skip over first word
	xlat	ds:byte ptr [bx]		;AN000;  convert to upper case
	pop	bx				;AN000;
	pop	ds				;AN000;
assume	ds:trangroup				;AN000;
	jmp	short upconv_end		;AN000;  we finished - exit

oth_fucase:					;AN000;
	cmp	al,small_a			;AC000; if between "a" and "z",
	jb	upconv_end			;AC000;     subtract 20h to get
	cmp	al,small_z			;AC000;    upper case equivalent.
	ja	upconv_end			;AC000;
	sub	al,20h				;AC000; Change lower-case to upper

upconv_end:					;AN000;
	ret

upconv	endp					;AN000;


;
; STORE A CHAR IN environment, GROWING IT IF NECESSARY
;
STORE_CHAR:
	PUSH	CX
	PUSH	BX
	PUSH	ES				;AN056;
	PUSH	DS				;AN056; Save local DS
	MOV	DS,[RESSEG]			;AN056; Get resident segment
	ASSUME	DS:RESGROUP			;AN056;
	MOV	ES,[ENVIRSEG]			;AN056; Get environment segment
	ASSUME	ES:NOTHING			;AN056;
	POP	DS				;AN056; Get local segment back
	ASSUME	DS:TRANGROUP			;AN056;
	CALL	GETENVSIZ
	MOV	BX,CX
	SUB	BX,2				; SAVE ROOM FOR DOUBLE NULL
	CMP	DI,BX
	JB	STORE1

	PUSH	AX
	PUSH	CX
	PUSH	BX				; Save Size of environment
	invoke	FREE_TPA
	POP	BX
	ADD	BX,2				; Recover true environment size

	CMP	BX, 8000H			; Don't let environment grow > 32K
	JB	ENVSIZ_OK
BAD_ENV_SIZE:					;AN056;
	STC
	JMP	ENVNOSET
ENVSIZ_OK:

	MOV	CL,4
	SHR	BX,CL				; Convert back to paragraphs
	INC	BX				; Try to grow environment by one para
	MOV	CX,ES				;AN056; Get environment segment
	ADD	CX,BX				;AN056; Add in size of environment
	ADD	CX,020H 			;AN056; Add in some TPA
	MOV	AX,CS				;AN056; Get the transient segment
	CMP	CX,AX				;AN056; Are we hitting the transient?
	JNB	BAD_ENV_SIZE			;AN056; Yes - don't do it!!!
	MOV	AH,SETBLOCK
	INT	int_command
ENVNOSET:
	PUSHF
	PUSH	ES
	MOV	ES,[RESSEG]
	invoke	ALLOC_TPA
	POP	ES
	POPF
	POP	CX
	POP	AX
	JNC	STORE1
	POP	ES				;AN056;
	MOV	DX,OFFSET TRANGROUP:ENVERR_ptr
	JMP	CERROR
STORE1:
	STOSB
	MOV	WORD PTR ES:[DI],0		; NULL IS AT END
	POP	ES				;AN056;
	POP	BX
	POP	CX
	return

GETENVSIZ:
;Get size of environment in bytes, rounded up to paragraph boundry
;ES has environment segment
;Size returned in CX, all other registers preserved

	PUSH	ES
	PUSH	AX
	MOV	AX,ES
	DEC	AX				;Point at arena
	MOV	ES,AX
	MOV	AX,ES:[arena_size]
	MOV	CL,4
	SHL	AX,CL				;Convert to bytes
	MOV	CX,AX
	POP	AX
	POP	ES
	return


ASSUME	DS:TRANGROUP


RESTUDIR1:
	PUSH	DS
	MOV	DS,[RESSEG]
ASSUME	DS:RESGROUP
	CMP	[RESTDIR],0
	POP	DS
ASSUME	DS:TRANGROUP
	retz

RESTUDIR:
	MOV	DX,OFFSET TRANGROUP:USERDIR1
	MOV	AH,CHDIR
	INT	int_command			; Restore users DIR
	XOR	AL,AL
	invoke	SETREST
RET56:
	return

trancode    ends
	    end