Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

961 lines
21 KiB

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