summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/COMMAND/TBATCH2.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/TBATCH2.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/TBATCH2.ASM')
-rw-r--r--v4.0/src/CMD/COMMAND/TBATCH2.ASM753
1 files changed, 753 insertions, 0 deletions
diff --git a/v4.0/src/CMD/COMMAND/TBATCH2.ASM b/v4.0/src/CMD/COMMAND/TBATCH2.ASM
new file mode 100644
index 0000000..501c637
--- /dev/null
+++ b/v4.0/src/CMD/COMMAND/TBATCH2.ASM
@@ -0,0 +1,753 @@
1 page 80,132
2; SCCSID = @(#)tbatch2.asm 4.2 85/07/22
3; SCCSID = @(#)tbatch2.asm 4.2 85/07/22
4TITLE Batch processing routines part II
5
6 INCLUDE comsw.asm
7
8.xlist
9.xcref
10 INCLUDE DOSSYM.INC
11 INCLUDE comseg.asm
12 INCLUDE comequ.asm
13.list
14.cref
15
16
17DATARES SEGMENT PUBLIC BYTE ;AC000;
18 EXTRN BATCH:WORD
19 EXTRN Batch_Abort:byte
20 EXTRN call_batch_flag:byte
21 EXTRN call_flag:byte
22 EXTRN IFFlag:BYTE
23 EXTRN In_Batch:byte
24 EXTRN Nest:word
25 EXTRN PIPEFILES:BYTE
26 EXTRN RETCODE:WORD
27 EXTRN SINGLECOM:WORD
28DATARES ENDS
29
30TRANDATA SEGMENT PUBLIC BYTE ;AC000;
31 EXTRN BADLAB_PTR:WORD
32 EXTRN BatBufLen:WORD
33 EXTRN IFTAB:BYTE
34 EXTRN SYNTMES_PTR:WORD
35TRANDATA ENDS
36
37TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
38 EXTRN arg:byte ; the arg structure!
39 EXTRN BatBuf:BYTE
40 EXTRN BatBufEnd:WORD
41 EXTRN BatBufPos:WORD
42 EXTRN BATHAND:WORD
43 EXTRN COMBUF:BYTE
44 EXTRN DIRBUF:BYTE
45 EXTRN GOTOLEN:WORD
46 EXTRN if_not_count:word
47 EXTRN IFNOTFLAG:BYTE
48 EXTRN RESSEG:WORD
49TRANSPACE ENDS
50
51TRANCODE SEGMENT PUBLIC BYTE
52
53ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
54
55 EXTRN cerror:near
56 EXTRN docom1:near
57 EXTRN tcommand:near
58
59 public $if,iferlev,goto,shift,ifexists,ifnot,forerror,$call
60
61
62Break <GetBatByt - retrieve a byte from the batch file>
63
64; Get one byte from the batch file and return it in AL. End-of-file returns
65; <CR> and ends batch mode. DS must be set to resident segment.
66; AH, DX destroyed.
67
68Procedure GETBATBYT,NEAR
69
70ASSUME DS:RESGROUP
71
72 SaveReg <BX,CX,DS>
73 test byte ptr [Batch_Abort],-1
74 jnz BatEOF
75 TEST Batch,-1
76 JZ BatEOF
77 PUSH ES
78 MOV ES,Batch
79 ASSUME ES:NOTHING
80 ADD WORD PTR ES:[BatSeek],1
81 ADC WORD PTR ES:[BatSeek+2],0
82 POP ES
83;
84; See if we have bytes buffered...
85;
86 MOV AX,CS
87 MOV DS,AX
88 ASSUME DS:TranGroup
89 MOV BX,BatBufPos
90 CMP BX,-1
91 JNZ UnBuf
92;
93; There are no bytes in the buffer. Let's try to fill it up.
94;
95 MOV DX,OFFSET TranGROUP:BatBuf
96 MOV CX,BatBufLen ; max to read.
97 MOV BX,BatHand
98 MOV AH,READ
99 INT int_command ; Get one more byte from batch file
100 jnc bat_read_ok ;AN022; if no error - continue
101 invoke get_ext_error_number ;AN022; get the error
102 push ds ;AN022; save local segment
103 mov ds,[resseg] ;AN022; get resident segment
104assume ds:resgroup ;AN022;
105 mov dx,ax ;AN022; put error in DX
106 invoke output_batch_name ;AN022; set up to print the error
107 pop ds ;AN022;
108assume ds:trangroup ;AN022;
109 invoke std_eprintf ;AN022; print out the error
110 mov byte ptr combuf+2,end_of_line_in;AN022; terminate the batch line for parsing
111 mov byte ptr combuf+3,end_of_line_out ;AN022; terminate the batch line for output
112 jmp bateof ;AN022; terminate the batch file
113
114bat_read_ok: ;AN022;
115 MOV CX,AX
116 JCXZ BATEOFDS
117 MOV BatBufEnd,CX
118 XOR BX,BX
119 MOV BatBufPos,BX
120;
121; Buffered bytes!
122;
123UnBuf:
124 MOV AL,BatBuf[BX] ; get next byte
125 INC BX
126 CMP BX,BatBufEnd ; beyond end of buffer?
127 JB SetBufPos
128 MOV BX,-1
129
130SetBufPos:
131 MOV BatBufPos,BX
132 CMP AL,1AH ; ^Z for termination?
133 jnz GetByteDone
134
135BatEOFDS:
136 ASSUME DS:TranGroup
137 MOV DS,ResSeg
138 ASSUME DS:ResGroup
139
140BATEOF:
141 invoke BatchOff
142 CALL BATCLOSE
143 MOV AL,0DH ; If end-of-file, then end of line
144 test byte ptr [Batch_Abort],-1
145 mov byte ptr [Batch_Abort],0
146 jz Cont_Get_Byt
147 mov di,offset TRANGROUP:COMBUF+2 ; reset pointer to beginning of buffer
148 xor cx,cx ; zero line length
149 jmp short GetByteDone
150
151Cont_Get_Byt:
152 CMP [SINGLECOM],0FFF0H ; See if we need to set SINGLECOM
153 JNZ GetByteDone
154 CMP NEST,0 ;G See if we have nested batch files
155 JNZ GETBYTEDONE ;G Yes - don't exit just yet
156 MOV [SINGLECOM],-1 ; Cause termination
157
158GetByteDone:
159 RestoreReg <DS,CX,BX>
160
161 return
162
163EndProc GetBatByt
164
165 break <$If - conditional execution>
166assume ds:trangroup,es:trangroup
167
168IFERRORP:
169 POP AX
170IFERROR:
171FORERROR:
172 MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
173 JMP CERROR
174
175$IF:
176;
177; Turn off any pipes in progress.
178;
179 push ds ;AN004; save local DS
180 mov ds,[resseg] ;AN004; get resident segment
181 assume ds:resgroup ;AN004;
182 cmp [PIPEFILES],0 ;AN004; Only turn off if present.
183 jz IFNoPipe ;AN004; no pipe - continue
184 invoke PipeDel ;AN004; turn off piping
185
186IFNoPipe: ;AN004;
187 pop ds ;AN004; get local DS back
188 assume ds:trangroup ;AN004;
189 MOV [IFNOTFLAG],0
190 mov [if_not_count], 0
191 MOV SI,81H
192
193IFREENT:
194 invoke SCANOFF
195 CMP AL,0DH
196 JZ IFERROR
197 MOV BP,SI
198 MOV DI,OFFSET TRANGROUP:IFTAB ; Prepare to search if table
199 MOV CH,0
200
201IFINDCOM:
202 MOV SI,BP
203 MOV CL,[DI]
204 INC DI
205 JCXZ IFSTRING
206 JMP SHORT FIRSTCOMP
207
208IFCOMP:
209 JNZ IF_DIF ;AC000;
210
211FIRSTCOMP:
212 LODSB
213 MOV AH,ES:[DI]
214 INC DI
215 CMP AL,AH
216 JZ IFLP
217 OR AH,20H ; Try lower case
218 CMP AL,AH
219
220IFLP:
221 LOOP IFCOMP
222
223IF_DIF: ;AC000;
224 LAHF
225 ADD DI,CX ; Bump to next position without affecting flags
226 MOV BX,[DI] ; Get handler address
227 INC DI
228 INC DI
229 SAHF
230 JNZ IFINDCOM
231 LODSB
232 CMP AL,0DH
233
234IFERRORJ:
235 JZ IFERROR
236 invoke DELIM
237 JNZ IFINDCOM
238 invoke SCANOFF
239 JMP BX
240
241IFNOT:
242 NOT [IFNOTFLAG]
243 inc [if_not_count]
244 JMP IFREENT
245
246;
247; We are comparing two strings for equality. First, find the end of the
248; first string.
249;
250
251IFSTRING:
252 PUSH SI ; save away pointer for later compare
253 XOR CX,CX ; count of chars in first string
254
255FIRST_STRING:
256 LODSB ; get character
257 CMP AL,0DH ; end of line?
258 JZ IFERRORP ; yes => error
259 invoke DELIM ; is it a delimiter?
260 JZ EQUAL_CHECK ; yes, go find equal sign
261 INC CX ; remember 1 byte for the length
262 JMP FIRST_STRING ; go back for more
263;
264; We have found the end of the first string. Unfortunately, we CANNOT use
265; scanoff to find the next token; = is a valid separator and will be skipped
266; over.
267;
268
269EQUAL_CHECK:
270 CMP AL,'=' ; is char we have an = sign?
271 JZ EQUAL_CHECK2 ; yes, go find second one.
272 CMP AL,0DH ; end of line?
273 JZ IFERRORPj ;AC004; yes, syntax error
274 LODSB ; get next char
275 JMP EQUAL_CHECK
276;
277; The first = has been found. The next char had better be an = too.
278;
279
280EQUAL_CHECK2:
281 LODSB ; get potential = char
282 CMP AL,'=' ; is it good?
283 jnz iferrorpj ; no, error
284;
285; Find beginning of second string.
286;
287 invoke SCANOFF
288 CMP AL,0DH
289 jz iferrorpj
290 POP DI
291;
292; DS:SI points to second string
293; CX has number of chars in first string
294; ES:DI points to first string
295;
296; Perform compare to elicit match
297;
298 REPE CMPSB
299 JZ MATCH ; match found!
300;
301; No match. Let's find out what was wrong. The character that did not match
302; has been advanced over. Let's back up to it.
303;
304 DEC SI
305;
306; If it is EOL, then syntax error
307;
308 CMP BYTE PTR [SI],0DH
309 JZ IFERRORJ
310;
311; Advance pointer over remainder of unmatched text to next delimiter
312;
313
314SKIPSTRINGEND:
315 LODSB
316
317NOTMATCH:
318 CMP AL,0DH
319
320IFERRORJ2:
321 JZ IFERRORJ
322 invoke DELIM
323 JNZ SKIPSTRINGEND
324;
325; Signal that we did NOT have a match
326;
327 MOV AL,-1
328 JMP SHORT IFRET
329
330iferrorpj:
331 jmp iferrorp
332;
333; The compare succeeded. Was the second string longer than the first? We
334; do this by seeing if the next char is a delimiter.
335;
336
337MATCH:
338 LODSB
339 invoke DELIM
340 JNZ NOTMATCH ; not same.
341 XOR AL,AL
342 JMP SHORT IFRET
343
344IFEXISTS:
345ifexist_attr EQU attr_hidden+attr_system
346
347moredelim:
348 lodsb ; move command line pointer over
349 invoke delim ; pathname -- have to do it ourselves
350 jnz moredelim ; 'cause parse_file_descriptor is dumb
351 mov DX, OFFSET TRANGROUP:dirbuf
352 trap set_dma
353 mov BX, 2 ; if(0) [|not](|1) exist[1|2] file(2|3)
354 add BX, [if_not_count]
355 mov AX, OFFSET TRANGROUP:arg.argv
356 invoke argv_calc ; convert arg index to pointer
357 mov DX, [BX].argpointer ; get pointer to supposed filename
358 mov CX, ifexist_attr ; filetypes to search for
359 trap Find_First ; request first match, if any
360 jc if_ex_c ; carry is how to determine error
361 xor AL, AL
362 jmp ifret
363
364if_ex_c:
365 mov AL, -1 ; false 'n' fall through...
366
367IFRET:
368 TEST [IFNOTFLAG],-1
369 JZ REALTEST
370 NOT AL
371
372REALTEST:
373 OR AL,AL
374 JZ IFTRUE
375 JMP TCOMMAND
376
377IFTRUE:
378 invoke SCANOFF
379 MOV CX,SI
380 SUB CX,81H
381 SUB DS:[80H],CL
382 MOV CL,DS:[80H]
383 MOV [COMBUF+1],CL
384 MOV DI,OFFSET TRANGROUP:COMBUF+2
385 CLD
386 REP MOVSB
387 MOV AL,0DH
388 STOSB
389;
390; Signal that an IF was done. This prevents the redirections from getting
391; lost.
392;
393 PUSH DS
394 MOV DS,ResSeg
395 ASSUME DS:RESGROUP
396 MOV IFFlag,-1
397 POP DS
398 ASSUME DS:TRANGROUP
399;
400; Go do the command
401;
402 JMP DOCOM1
403
404iferrorj3:
405 jmp iferrorj2
406
407IFERLEV:
408 MOV BH,10
409 XOR BL,BL
410
411GETNUMLP:
412 LODSB
413 CMP AL,0DH
414 jz iferrorj3
415 invoke DELIM
416 JZ GOTNUM
417 SUB AL,'0'
418 XCHG AL,BL
419 MUL BH
420 ADD AL,BL
421 XCHG AL,BL
422 JMP SHORT GETNUMLP
423
424GOTNUM:
425 PUSH DS
426 MOV DS,[RESSEG]
427ASSUME DS:RESGROUP
428 MOV AH,BYTE PTR [RETCODE]
429 POP DS
430ASSUME DS:TRANGROUP
431 XOR AL,AL
432 CMP AH,BL
433 JAE IFRET
434 DEC AL
435 JMP SHORT IFRET
436
437
438 break <Shift - advance arguments>
439assume ds:trangroup,es:trangroup
440
441;
442; Shift the parameters in the batch structure by 1 and set up the new argument.
443; This is a NOP if no batch in progress.
444;
445
446Procedure Shift,NEAR
447
448 MOV DS,[RESSEG]
449ASSUME DS:RESGROUP
450 MOV AX,[BATCH] ; get batch pointer
451 OR AX,AX ; in batch mode?
452 retz ; no, done.
453 MOV ES,AX ; operate in batch segment
454 MOV DS,AX
455
456ASSUME DS:NOTHING,ES:NOTHING
457
458;
459; Now move the batch args down by 1 word
460;
461 MOV DI,BatParm ; point to parm table
462 LEA SI,[DI+2] ; make source = dest + 2
463 MOV CX,9 ; move 9 parameters
464 REP MOVSW ; SHIFT down
465;
466; If the last parameter (the one not moved) is empty (= -1) then we are done.
467; We have copied it into the previous position
468;
469 CMP WORD PTR [DI],-1 ; if last one was not in use then
470 retz ; No new parm
471;
472; This last pointer is NOT nul. Get it and scan to find the next argument.
473; Assume, first, that there is no next argument
474;
475 MOV SI,[DI]
476 MOV WORD PTR [DI],-1 ; Assume no parm
477;
478; The parameters are CR separated. Scan for end of this parm
479;
480SKIPCRLP:
481 LODSB
482 CMP AL,0DH
483 JNZ SKIPCRLP
484;
485; We are now pointing at next arg. If it is 0 (end of original line) then we
486; are finished. There ARE no more parms and the pointer has been previously
487; initialized to indicate it.
488;
489 CMP BYTE PTR [SI],0
490 retz ; End of parms
491 MOV [DI],SI ; Pointer to next parm as %9
492
493 return
494
495EndProc Shift
496
497;
498; Skip delim reads bytes from the batch file until a non-delimiter is seen.
499; returns char in AL, carry set -> eof
500;
501
502Procedure SkipDelim,NEAR
503
504 ASSUME DS:ResGroup,ES:NOTHING
505 TEST Batch,-1
506 JZ SkipErr ; batch file empty. OOPS!
507 CALL GetBatByt ; get a char
508 invoke Delim ; check for ignoreable chars
509 JZ SkipDelim ; ignore this char.
510 clc
511 return
512
513SkipErr:
514 stc
515 return
516
517EndProc SkipDelim
518
519 break $Call
520
521; CALL is an internal command that transfers control to a .bat, .exe, or
522; .com file. This routine strips the CALL off the command line, sets
523; the CALL_FLAG to indicate a call in progress, and returns control to
524; DOCOM1 in TCODE to reprocess the command line and execute the file
525; being CALLed.
526
527$CALL:
528
529; strip off CALL from command line
530
531 ASSUME DS:trangroup,ES:trangroup
532 push si
533 push di
534 push ax
535 push cx
536 mov si,offset trangroup:combuf+2
537 invoke scanoff ;get to first non-delimeter
538 add si,length_call ;point to char past CALL
539 mov di,offset trangroup:combuf+2
540 mov cx,combuflen-length_call ;get length of buffer
541 rep movsb ;move it
542 pop cx
543 pop ax
544 pop di
545 pop si
546
547
548; set call flag to indicate call in progress
549
550 push ds
551 mov ds,[resseg]
552 ASSUME DS:resgroup,ES:resgroup
553 mov call_flag, call_in_progress
554 mov call_batch_flag, call_in_progress
555;
556; Turn off any pipes in progress.
557;
558 cmp [PIPEFILES],0 ; Only turn off if present.
559 jz NoPipe
560 invoke PipeDel
561NoPipe:
562 pop ds
563
564 ret
565
566 break Goto
567
568GOTO:
569
570assume ds:trangroup,es:trangroup
571 MOV DS,[RESSEG]
572ASSUME DS:RESGROUP
573 TEST [BATCH],-1
574 retz ; If not in batch mode, a nop
575 XOR DX,DX
576 PUSH DS
577 MOV DS,Batch
578 MOV WORD PTR DS:[BatSeek],DX ; Back to start
579 MOV WORD PTR DS:[BatSeek+2],DX ; Back to start
580 POP DS
581
582GotoOpen:
583 invoke promptBat
584 MOV DI,FCB+1 ; Get the label
585 MOV CX,11
586 MOV AL,' '
587 REPNE SCASB
588 JNZ NOINC
589 INC CX
590
591NOINC:
592 SUB CX,11
593 NEG CX
594 MOV [GOTOLEN],CX
595;
596; At beginning of file. Skip to first non-delimiter char
597;
598 CALL SkipDelim
599 JC BadGoto
600 CMP AL,':'
601 JZ CHKLABEL
602
603LABLKLP: ; Look for the label
604 CALL GETBATBYT
605 CMP AL,0AH
606 JNZ LABLKTST
607;
608; At beginning of line. Skip to first non-delimiter char
609;
610 CALL SkipDelim
611 JC BadGoto
612 CMP AL,':'
613 JZ CHKLABEL
614
615LABLKTST:
616 TEST [BATCH],-1
617 JNZ LABLKLP
618
619BadGoto:
620 CALL BATCLOSE
621 PUSH CS
622 POP DS
623 MOV DX,OFFSET TRANGROUP:BADLAB_ptr
624 JMP CERROR
625
626;
627; Found the :. Skip to first non-delimiter char
628;
629
630CHKLABEL:
631 CALL SkipDelim
632 JC BadGoto
633 MOV DI,FCB+1
634 MOV CX,[GOTOLEN]
635 JMP SHORT GotByte
636
637NEXTCHRLP:
638 PUSH CX
639 CALL GETBATBYT
640 POP CX
641
642GotByte:
643 INVOKE TESTKANJ ;AN000; 3/3/KK
644 JZ NOTKANJ1 ;AN000; 3/3/KK
645 CMP AL, ES:[DI] ;AN000; 3/3/KK
646 JNZ LABLKTST ;AN000; 3/3/KK
647 INC DI ;AN000; 3/3/KK
648 DEC CX ;AN000; 3/3/KK
649 JCXZ LABLKTST ;AN000; 3/3/KK
650 PUSH CX ;AN000; 3/3/KK
651 CALL GETBATBYT ;AN000; 3/3/KK
652 POP CX ;AN000; 3/3/KK
653 CMP AL, ES:[DI] ;AN000; 3/3/KK
654 JMP SHORT KNEXTLABCHR ;AN000; 3/3/KK
655
656NOTKANJ1: ;AN000; 3/3/KK
657 OR AL,20H
658 CMP AL,ES:[DI]
659 JNZ TRYUPPER
660 JMP SHORT NEXTLABCHR
661
662TRYUPPER:
663 SUB AL,20H
664 CMP AL,ES:[DI]
665
666KNEXTLABCHR: ;AN000; 3/3/KK
667 JNZ LABLKTST
668
669NEXTLABCHR:
670 INC DI
671 LOOP NEXTCHRLP
672 CALL GETBATBYT
673 cmp [GOTOLEN],8 ; Is the label atleast 8 chars long?
674 jge gotocont ; Yes, then the next char doesn't matter
675 CMP AL,' '
676 JA LABLKTST
677
678gotocont:
679 CMP AL,0DH
680 JZ SKIPLFEED
681
682TONEXTBATLIN:
683 CALL GETBATBYT
684 CMP AL,0DH
685 JNZ TONEXTBATLIN
686
687SKIPLFEED:
688 CALL GETBATBYT
689 CALL BatClose
690
691 return
692
693Procedure BatClose,NEAR
694
695 MOV BX,CS:[BATHAND]
696 CMP BX,5
697 JB CloseReturn
698 MOV AH,CLOSE
699 INT int_command
700
701CloseReturn:
702 mov byte ptr [In_Batch],0 ; reset flag
703 return
704
705EndProc BatClose
706
707;
708; Open the BATCH file, If open fails, AL is drive of batch file (A=1)
709; Also, fills internal batch buffer. If access denied, then AX = -1
710;
711
712Procedure BatOpen,NEAR
713
714ASSUME DS:RESGROUP,ES:TRANGROUP
715
716 PUSH DS
717 MOV DS,[BATCH]
718ASSUME DS:NOTHING
719
720 MOV DX,BatFile
721 MOV AX,OPEN SHL 8
722 INT int_command ; Open the batch file
723 JC SETERRDL
724 MOV DX,WORD PTR DS:[BatSeek]
725 MOV CX,WORD PTR DS:[BatSeek+2]
726 POP DS
727ASSUME DS:RESGROUP
728
729 MOV [BATHAND],AX
730 MOV BX,AX
731 MOV AX,LSEEK SHL 8 ; Go to the right spot
732 INT int_command
733 MOV BatBufPos,-1 ; nuke batch buffer position
734
735 return
736
737SETERRDL:
738 MOV BX,DX
739 invoke get_ext_error_number ;AN022; get the extended error
740 mov dx,ax ;AN022; save extended error in DX
741 MOV AL,[BX] ; Get drive spec
742 SUB AL,'@' ; A = 1
743 POP DS
744 STC ; SUB mucked over carry
745
746 return
747
748EndProc BatOpen
749
750
751TRANCODE ENDS
752 END
753 \ No newline at end of file