home *** CD-ROM | disk | FTP | other *** search
-
-
-
- program BATMAKER;
-
- {------------------------------------------------------------------------------
- BATMAKER version 2.00 R.L. Miller
-
- Program to read file names from a disk directory, and put them into a
- batch file called NAMES.BAT. Several formats are supported: see accompanying
- file, BATMAKER.DOC.
-
- >>> Turbo Database Toolbox needed to compile this program. <<<
-
- BATMAKER uses MSDos to get file names from an IBM formated diskette.
- The function calls used can be found in the DOS Technical Reference Manual.
- This program uses the current Data Transfer Area ( DTA ) in the variables
- DTAseg and DTAofs.
-
- ------------------------------------------------------------------------------}
- {$I-,U+,C+,V-}
-
- const
- Scrful = 20;
-
-
- type { TYPE declarations }
- Registers =
- record { register pack used in MSDos call }
- AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : Integer;
- end;
- Char80arr = array [ 1..80 ] of Char;
- String80 = string[ 80 ];
- BigString = string[255];
- CommandString = string[127];
- sptr = ^BigString;
-
- var { VARIABLE declarations }
- DTA : array [ 1..43 ] of Byte; { Data Transfer Area Buffer }
- DTAseg, { DTA Segment before exicution }
- DTAofs, { DTA Offset " " }
- SetDTAseg, { DTA Segment and Offset set after }
- SetDTAofs, { start of program }
- Error, { Error return }
- I, J, { used as counters }
- Option : Integer; { used to specify file types }
- Regs : registers; { register pack for the DOS call }
- Buffer, { generic Buffer }
- Fname : String80; { file name }
- Afn : Char80arr; { file Mask: "Ambiguous File Name" }
- Lines : Integer; { no. lines on screen already }
- Status: Integer; { Status number returned by TurboSort }
- ComLine : CommandString; { COPY of invoking Command line, for parsing}
- CL : CommandString absolute CSEG:$80; {ACTUAL command line string }
- OutFile : text; { File handle for NAMES.BAT, the output file}
- Opt : string[3]; {Option string}
-
- Delim : string[20];
- FirstWord,NextWord,NewWord : string[80];
- FlagWords : string[255];
- start, next : integer;
- strptr : sptr;
-
-
- (**************************************************************************)
- (* *)
- (* NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE *)
- (* *)
- (* Turbo Database Toolbox needed to compile this program! *)
- (* *)
- (**************************************************************************)
-
- {$ISORT.BOX}
-
-
- {-----------------------------------------------------------------------------
- SetLen: sets length of ASCIZ string passed to it as a parameter.
- ------------------------------------------------------------------------------}
- Procedure SetLen(var ST: bigstring);
-
- Const
- MAX : Char = #255;
- var
- Segment,Offset : Integer;
- Terminator : Integer;
- Null : String[2];
-
- Begin
- Null := #0;
- ST[0] := MAX; { Initially set length to Max }
- Terminator := Pos(null,ST) - 1;
- ST[0] := Chr(Lo(Terminator));
- end; {of proc SetLen}
-
- {----------------------------------------------------------------------------
- PrtPath: prints out full path string (including drive name).
- -----------------------------------------------------------------------------}
- Procedure PrtPath;
-
- Const
- Carry = $0001;
-
- Var
- Disk : String[4];
- Path : String[80];
- Ichar : Integer;
- Pathseg,Pathofs : integer;
-
- Begin
- Regs.AX := $1900; { Set up for "Current Disk" DOS call }
- MSDOS( Regs);
- Ichar := Lo(Regs.AX) + $41;
- Disk := Chr(Ichar);
- Disk := Disk + ':';
- { Now set up for "Return Text of Current Directory" DOS call }
- Regs.DX := 0;
- Regs.AX := $4700;
- Regs.DS := Seg(path);
- Regs.SI := ofs(Path) + 1;
- Pathseg := Regs.DS;
- Pathofs := Regs.SI;
- MSDOS( Regs);
- Error := Regs.Flags and Carry;
- {$V-}
- Setlen(Path); { Turn path string into something familiar to Turbo }
- Writeln(' Reading Directory of: ',Disk+Buffer);
- Writeln(' (Current directory is: ',Disk+'\'+Path,')');
- Writeln;
- End; {of proc PrtPath}
-
-
- {------------------------------------------------------------------------------
- GetDTA is used to get the current Disk Transfer Area ( DTA )
- address. A function code of $2F is stored in the high Byte of the AX
- register and a call to the MSDos INT 21H is made, by using the "Intr"
- procedure with a $21 specification for the interrupt.
- ------------------------------------------------------------------------------}
-
- procedure GetDTA( var Segment, Offset : Integer;
- var Error : Integer );
- begin
- Regs.AX := $2F00; { Function used to get current DTA address }
- { $2F00 is used instead of $2F shl 8 to save
- three assembly instructions. An idea for
- optimization. }
- Intr( $21, Regs ); { Execute MSDos function request }
- Segment := Regs.ES; { Segment of DTA returned by DOS }
- Offset := Regs.BX; { Offset of DTA returned }
- Error := Regs.AX and $FF;
- end; { of proc GetDTA }
-
- {------------------------------------------------------------------------------
- GetFirst gets the first directory entry of a particular file Mask. The
- Afn is passed as a parameter 'Afn' and, the Option was previosly specified
- in the SpecifyOption procedure.
- ------------------------------------------------------------------------------}
-
- procedure GetFirst( Afn : Char80arr; var Fname : String80;
- Segment, Offset : Integer; Option : Integer;
- var Error : Integer );
- var
- I : Integer;
- begin
- Error := 0;
- Regs.AX := $4E00; { Get first directory entry }
- Regs.DS := Seg( Afn ); { Point to the file Mask }
- Regs.DX := Ofs( Afn );
- Regs.CX := Option; { Store the Option }
- MSDos( Regs ); { Execute MSDos call }
- Error := Regs.AX and $FF; { Get Error return }
- strptr := ptr(segment, offset+29);
- setlen( strptr^);
- Fname := strptr^;
- end; { of proc GetFirst }
-
- {------------------------------------------------------------------------------
- GetNext uses the first bytes of the DTA for the file Mask, and
- returns the next file entry on disk corresponding to the file Mask.
- ------------------------------------------------------------------------------}
-
- procedure GetNext( var Fname : String80; Segment, Offset : Integer;
- Option : Integer; var Error : Integer );
- var
- I : Integer;
-
- begin
- Error := 0;
- Regs.AX := $4F00; { Function used to get the next }
- { directory entry }
- Regs.CX := Option; { Set the file option }
- MSDos( Regs ); { Call MSDos }
- Error := Regs.AX and $FF; { get the Error return }
- strptr := ptr(segment, offset+29);
- setlen( strptr^);
- Fname := strptr^;
- end; { of proc GetNext }
-
- {===========================================================================
- ABORT procedure: Prints out help message & halts program
- =============================================================================}
-
- Procedure Abort;
-
- begin
- WriteLn('Usage: BATMAKER Filename.Typ -O)ption_Letter');
- Writeln;
- Writeln('Option_Letter Output ');
- Writeln('============= ====== ');
- Writeln(' -A %1 Filename.Typ %2 %3');
- Writeln(' -B %1 %2 Filename.Typ %3 %4');
- Writeln(' -C %1 %2Filename.Typ %3 %4');
- Writeln(' -D %1 <Filename.Typ >%2 %3');
- Writeln(' -E %1 <Filename.Typ >>%2 %3');
- Writeln(' -F %1 <Filename.Typ |%2 >%3 %4');
- Writeln(' -G %1 <Filename.Typ |%2 >>%3 %4');
- Writeln(' -H -- Prints this help message --');
- Writeln(' -any other Filename.Typ');
- Writeln;
- Writeln('Output for all options but -H go to file NAMES.BAT in current directory');
- Writeln('Command line can handle paths, e.g.:');
- Writeln(' A>BATMAKER B:\BIN\*.COM -A');
- Writeln;
- HALT; {Stop program here}
- end; {of procedure ABORT}
-
- {============================================================================
- PARSE Procedure: Finds first word in <line> and returns it in <word>.
- =============================================================================}
-
- procedure Parse(Line:Bigstring; var Word:Bigstring );
- (* Looks for next word in string <Line>, starting at character position *)
- (* <start>, returns the substring in <Word>, and position of the trailing *)
- (* delimiter in <next>. Uses global string variable <delim> as the *)
- (* collection of valid delimiters. *)
- var
- i,indx,len,len2 : integer;
- c : char;
- yesno : string[20];
-
- procedure geti; (* a helpful procedure local to Parse *)
- begin
- indx := indx + 1;
- c := line[indx];
- i := pos(c,delim);
- end; (* geti *)
-
- begin (* Parse procedure body *)
- (* First, move past any leading delimiters: *)
- len := length(line);
- indx := start - 1;
- repeat geti until i=0;
- start := indx;
- (* Now find trailing delimiter: *)
- repeat geti until ((i>0) or (indx>=len));
- next := indx + 1; (* This is the place to start looking for next word *)
- if indx = len then len2 := next-start else len2 := indx-start;
- Word := copy(Line, start, len2);
- end; (* of PARSE *)
-
- {============================================================================
- GetBoth procedure: Looks at 1st 2 words in command line, tries to find one
- with a leading dash for option string, other for file
- mask.
- ============================================================================}
-
- Procedure GetBoth(var Opt,Buffer,ComLine:BigString);
- var
- Word1,Word2 : Bigstring;
- begin
- start := 1;
- Parse(ComLine,Word1);
- start := next;
- If Length(ComLine)<>0 then Parse(Comline,Word2) else Word2:='';
- If Pos('-',Word1)=1 then begin {Word1 contains option string}
- Opt:=Copy(Word1,2,1);
- Buffer:=Word2;
- end
- else if Pos('-',Word2)=1 then begin {Word2 contains option string}
- Opt:= Copy(Word2,2,1);
- Buffer:=Word1;
- end
- else Abort; {Abort if no option string present}
- end; {of Procedure GetBoth}
-
-
- {============================================================================
- Routines needed by Turbo Sort
- =============================================================================}
-
- procedure inp;
- begin
- GetFirst( Afn, Fname, SetDTAseg, SetDTAofs, Option, Error );
- if ( Error = 0 ) then begin { Get the first directory entry }
- SortRelease( Fname )
- end;
- while ( Error = 0 ) do begin
- GetNext( Fname, SetDTAseg, SetDTAofs, Option, Error );
- if ( Error = 0 ) then begin
- SortRelease( Fname );
- end;
- end;
- end;
-
-
- function less;
- var
- String1 : String80 absolute X;
- String2 : String80 absolute Y;
- begin
- less:=String1<String2;
- end;
-
- Procedure OutP;
- var
- Prestring,Poststring : string[15];
- begin
- PrtPath;
- case Opt of
- 'a','A' : begin Prestring:='%1 '; PostString:=' %2 %3'; end;
- 'b','B' : begin Prestring:='%1 %2 '; Poststring:=' %3 %4'; end;
- 'c','C' : begin Prestring:='%1 %2'; Poststring:=' %3 %4'; end;
- 'd','D' : begin Prestring:='%1 <'; Poststring:=' >%2 %3'; end;
- 'e','E' : begin Prestring:='%1 <'; Poststring:=' >>%2 %3'; end;
- 'f','F' : begin Prestring:='%1 <'; Poststring:=' |%2 >%3 %4'; end;
- 'g','G' : begin Prestring:='%1 <'; Poststring:=' |%2 >>%3 %4'; end;
- 'h','H' : Abort;
- else
- begin Prestring:=''; Poststring:=''; end;
- end;
- repeat
- SortReturn(Fname);
- WriteLn( OutFile,Prestring,Fname,Poststring );
- until SortEOS;
- end;
-
-
- {****************************************************************************
- *****************************************************************************
-
- main body of program BATMAKER
-
- *****************************************************************************
- *****************************************************************************
- }
-
- begin
- ComLine:=CL; {Read the commandline immediately}
- WRITELN;
- WriteLn( 'BATMAKER version 2.00 R.L. Miller' );
- WriteLn;
- delim := ' '^I'';
- If Length(ComLine)=0 then Abort;
- GetBoth(Opt,Buffer,ComLine); {Parse command line into option & file mask}
- If UpCase(Opt)='H' then Abort; {If H)elp option, abort right away..}
- for I := 1 to 80 do begin { Initialize the Afn and }
- Afn[ I ] := Chr( 0 ); { file name buffers }
- Fname[ I ] := Chr( 0 );
- end;
- Fname[ 0 ] := Chr( 0 ); { Set the file name length to 0 }
- GetDTA( DTAseg, DTAofs, Error ); { Get the current DTA address }
- if ( Error <> 0 ) then begin { Check for errors }
- WriteLn( 'Unable to get current DTA' );
- WriteLn( 'Program aborting.' ); { and abort. }
- Halt; { end program now }
- end;
- SetDTAseg := DTAseg;
- SetDTAofs := DTAofs;
- Error := 0;
- Option:=1; {Handle only standard files for now...}
- if ( length( Buffer ) = 0 ) then { if nothing was entered }
- Buffer := '????????.???'; { then use global search }
- for I := 1 to length( Buffer ) do { Assign Buffer to Afn }
- Afn[ I ] := Buffer[ I ];
- Assign (Outfile,'NAMES.BAT');
- Rewrite(Outfile);
- Writeln('Sorting...');
- Status := TurboSort(14);
- Write('Status = ');
- case Status of
- 0 : Writeln('OK');
- 3 : Writeln('ERROR: Insufficient memory');
- 8 : Writeln('ERROR: Illegal item length');
- 9 : Writeln('ERROR: More than ',Maxint,' files');
- 10: Writeln('ERROR: During sorting. Bad or full disk.');
- 11: Writeln('ERROR: During read of directory. Probable bad disk.');
- 12: Writeln('ERROR: Unable to create temporary file');
- else Writeln(' +++ Unknown ERROR');
- end;
- Close(Outfile);
- end. { end Main }
-
-