Newsgroups: comp.os.msdos.programmer
Subject: Re: Another MsDos batch programming challenge
From: cctr132@csc.canterbury.ac.nz (Nick FitzGerald, CSC, Uni. of Canterbury, NZ)
Date: 7 Sep 92 21:11:28 +1200
 <1992Sep4.032836.7299@cs.ubc.ca> <1992Sep4.213842.14734@mits.mdata.fi>
Organization: University of Canterbury, Christchurch, New Zealand

In article <1992Sep4.213842.14734@mits.mdata.fi>, kennu@mits.mdata.fi
(Kenneth Falck) writes:
> In article <1992Sep4.032836.7299@cs.ubc.ca> yogi@cs.ubc.ca (Yossi Gil)
writes:
>>Yes, I tested it. It works. It relies on the way DOS does batch file:
>>	
>>	1. Open file.
>>	2. Seek in file to current statement. 
>>	3. Interpret statement. 
>>	4. Close file.
>>	5. Execute statement
>>	6. Goto 1 if not done.
>>
>>This is why Batch Programming is so inefficient.

I missed Yossi's original post on this, so apologies if he covered some
of the following.

The actual DOS batch processor is a tad more involved than Yossi's
outline suggests.  Whilst the following may not seem much different from
what Yossi suggests, some subtle implications of batch processor
operations are more clearly apparent from it.  To the best of my ability
to tell, the following is a more accurate outline:

 1.  Open file
 2.  Read first line
 3.  Note number of -chars- read thus far
 4.  Parse line (for redirection, etc)
 5.  Close file
 6.  Execute command
 7.  Open file
 8.  Read to number of chars recorded in 4.
 9.  Read to next EOL or EOF
10.  If command is null and EOF goto 12.
11.  Loop to 3.
12.  Close file

(NB:  Steps 3, 4 and 5 are arbitrarily ordered here -- I can't think of
any way to test this.  I could roll them into one step I suppose.  8-) )

This implies that one line and null batches will be opened twice --
anyone with an interrupt tracer care to test this out?  If null batches
aren't opened twice, I'll have to revise Steps 2 and 3.

Some other implications of this are easily tested.  In LAN environments
batch files whose last act is to remove the drive mapping for the drive
they are running from will generate an error message from DOS about an
invalid command or bad filename (depending on DOS version) as the batch
processor fails to find the file, to reopen it (if the EOF testing was
part of the "read command" logic, this wouldn't happen).

> By the way, does MSDOS store the current statement of
> a batch file as an absolute byte location from the
> beginning of the file, or perhaps as the line number
> (lines separated by CRLF's)?

According to the above, byte offset, but don't just take my word for it,
try the following:

Copy the following batch files to a suitable directory.  Make a backup
copy of BATTEST.BAT (say BATTEST1.BAT ).


-----------------------  BATTEST.BAT  -----------------------
echo off
echo Batch test 1
copy battest2.bat battest.bat
echo Batch test 1

-----------------------  BATTEST2.BAT  -----------------------
echo off
echo Batch test 2
copy battest2.bat battest.bat  dir
echo Batch test 2

NOTE:  The "dir" on line 3 of BATTEST2.BAT is preceded by -TWO- spaces. 
It is most important that both are included (but more won't hurt  8-) ).

Change to the directory where these batches are, and execute BATTEST. 
Your output should look something like:

*************************************************
Batch test 1
        1 file(s) copied

 Volume in drive C has no label
 Volume Serial Number is 0E5C-07CE
 Directory of C:\BATTEST

.            <DIR>     23-08-92  12:06p
..           <DIR>     23-08-92  12:06p
BATTEST  BAT        85 07-09-92   1:27p
BATTEST1 BAT        80 07-09-92   1:27p
BATTEST2 BAT        85 07-09-92   1:27p
       12 file(s)       1804 bytes
                    13506560 bytes free
Batch test 2
*************************************************

Note that the "dir" command on line 3 of BATTEST2 executed -- if the
batch processor were simply keeping a line count this wouldn't occur. 
Now it should be obvious why there need to be two spaces before the
"dir" on line 3 -- remember, DOS uses CR/LF for end-of-line!

Take out one of the two spaces before the "dir" in BATTEST2.BAT and what
happens? -- You get a "bad command or filename" error, as DOS tries to
execute the command "ir" (unless you have an "IR.BAT", .EXE or .COM in
your path or current directory).

Make sure SHARE is loaded and run the original test again.  You will
-NOT- get a sharing violation on BATTEST.BAT while the "copy" command
on line 3 executes, supporting my contention that the batch file is
closed between reads.

I have only tested this systematically under MS-DOS 5.0, but from much
batch experience under MS-DOS 3.3 and 4.0, feel it (mostly ?) holds for
those versions as well.  Would someone with DR-DOS 5.0 and/or 6.0 like
to test this out and send me the results?  Also, anyone with an "old"
version of MS-DOS (say, pre-3.2) ?

I hope you found this weeks installment of the DOS batch file saga
interesting!

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 Nick FitzGerald, PC Applications Consultant, CSC, Uni of Canterbury, N.Z.
 n.fitzgerald@csc.canterbury.ac.nz  (64)(3)  364-2337 Voice,  364-2332 FAX
Newsgroups: comp.os.msdos.programmer