2 ; SCCSID = @(#)tbatch2.asm 4.2 85/07/22
3 ; SCCSID = @(#)tbatch2.asm 4.2 85/07/22
4 TITLE Batch processing routines part II
17 DATARES
SEGMENT PUBLIC BYTE ;AC000;
19 EXTRN Batch_Abort
:byte
20 EXTRN call_batch_flag
:byte
30 TRANDATA
SEGMENT PUBLIC BYTE ;AC000;
34 EXTRN SYNTMES_PTR
:WORD
37 TRANSPACE
SEGMENT PUBLIC BYTE ;AC000;
38 EXTRN arg
:byte ; the arg structure!
46 EXTRN if_not_count
:word
51 TRANCODE
SEGMENT PUBLIC BYTE
53 ASSUME
CS:TRANGROUP
,DS:NOTHING
,ES:NOTHING
,SS:NOTHING
59 public $
if,iferlev
,goto
,shift
,ifexists
,ifnot
,forerror
,$
call
62 Break <GetBatByt
- retrieve a
byte from the batch
file>
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.
68 Procedure GETBATBYT
,NEAR
73 test byte ptr [Batch_Abort
],-1
80 ADD WORD PTR ES:[BatSeek
],1
81 ADC WORD PTR ES:[BatSeek
+2],0
84 ; See if we have bytes buffered...
93 ; There are no bytes in the buffer. Let's try to fill it up.
95 MOV DX,OFFSET TranGROUP
:BatBuf
96 MOV CX,BatBufLen
; max to 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
104 assume
ds:resgroup
;AN022;
105 mov dx,ax ;AN022; put error in DX
106 invoke output_batch_name
;AN022; set up to print the error
108 assume
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
124 MOV AL,BatBuf
[BX] ; get next byte
126 CMP BX,BatBufEnd
; beyond end of buffer?
132 CMP AL,1
AH ; ^Z for termination?
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
147 mov di,offset TRANGROUP
:COMBUF
+2 ; reset pointer to beginning of buffer
148 xor cx,cx ; zero line length
149 jmp short GetByteDone
152 CMP [SINGLECOM
],0FFF0H ; See if we need to set SINGLECOM
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
159 RestoreReg
<DS,CX,BX>
165 break <$
If - conditional execution
>
166 assume
ds:trangroup
,es:trangroup
172 MOV DX,OFFSET TRANGROUP
:SYNTMES_ptr
177 ; Turn off any pipes in progress.
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
187 pop ds ;AN004; get local DS back
188 assume
ds:trangroup
;AN004;
190 mov [if_not_count
], 0
198 MOV DI,OFFSET TRANGROUP
:IFTAB
; Prepare to search if table
217 OR AH,20H
; Try lower case
225 ADD DI,CX ; Bump to next position without affecting flags
226 MOV BX,[DI] ; Get handler address
247 ; We are comparing two strings for equality. First, find the end of the
252 PUSH SI ; save away pointer for later compare
253 XOR CX,CX ; count of chars in first 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
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
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
277 ; The first = has been found. The next char had better be an = too.
281 LODSB ; get potential = char
282 CMP AL,'=' ; is it good?
283 jnz iferrorpj
; no, error
285 ; Find beginning of second string.
292 ; DS:SI points to second string
293 ; CX has number of chars in first string
294 ; ES:DI points to first string
296 ; Perform compare to elicit match
299 JZ MATCH ; match found!
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.
306 ; If it is EOL, then syntax error
308 CMP BYTE PTR [SI],0DH
311 ; Advance pointer over remainder of unmatched text to next delimiter
325 ; Signal that we did NOT have a match
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.
340 JNZ NOTMATCH
; not same.
345 ifexist_attr EQU attr_hidden
+attr_system
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
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
365 mov AL, -1 ; false 'n' fall through...
384 MOV DI,OFFSET TRANGROUP
:COMBUF
+2
390 ; Signal that an IF was done. This prevents the redirections from getting
428 MOV AH,BYTE PTR [RETCODE
]
438 break <Shift
- advance arguments
>
439 assume
ds:trangroup
,es:trangroup
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.
450 MOV AX,[BATCH
] ; get batch pointer
451 OR AX,AX ; in batch mode?
453 MOV ES,AX ; operate in batch segment
456 ASSUME
DS:NOTHING
,ES:NOTHING
459 ; Now move the batch args down by 1 word
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
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
469 CMP WORD PTR [DI],-1 ; if last one was not in use then
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
476 MOV WORD PTR [DI],-1 ; Assume no parm
478 ; The parameters are CR separated. Scan for end of this parm
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.
491 MOV [DI],SI ; Pointer to next parm as %9
498 ; Skip delim reads bytes from the batch file until a non-delimiter is seen.
499 ; returns char in AL, carry set -> eof
502 Procedure SkipDelim
,NEAR
504 ASSUME
DS:ResGroup
,ES:NOTHING
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.
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
529 ; strip off CALL from command line
531 ASSUME
DS:trangroup
,ES:trangroup
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
548 ; set call flag to indicate call in progress
552 ASSUME
DS:resgroup
,ES:resgroup
553 mov call_flag
, call_in_progress
554 mov call_batch_flag
, call_in_progress
556 ; Turn off any pipes in progress.
558 cmp [PIPEFILES
],0 ; Only turn off if present.
570 assume
ds:trangroup
,es:trangroup
574 retz
; If not in batch mode, a nop
578 MOV WORD PTR DS:[BatSeek
],DX ; Back to start
579 MOV WORD PTR DS:[BatSeek
+2],DX ; Back to start
584 MOV DI,FCB
+1 ; Get the label
596 ; At beginning of file. Skip to first non-delimiter char
603 LABLKLP: ; Look for the label
608 ; At beginning of line. Skip to first non-delimiter char
623 MOV DX,OFFSET TRANGROUP
:BADLAB_ptr
627 ; Found the :. Skip to first non-delimiter char
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
656 NOTKANJ1: ;AN000; 3/3/KK
666 KNEXTLABCHR: ;AN000; 3/3/KK
673 cmp [GOTOLEN
],8 ; Is the label atleast 8 chars long?
674 jge gotocont
; Yes, then the next char doesn't matter
693 Procedure BatClose
,NEAR
702 mov byte ptr [In_Batch
],0 ; reset flag
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
712 Procedure BatOpen
,NEAR
714 ASSUME
DS:RESGROUP
,ES:TRANGROUP
722 INT int_command
; Open the batch file
724 MOV DX,WORD PTR DS:[BatSeek
]
725 MOV CX,WORD PTR DS:[BatSeek
+2]
731 MOV AX,LSEEK
SHL 8 ; Go to the right spot
733 MOV BatBufPos
,-1 ; nuke batch buffer position
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
744 STC ; SUB mucked over carry