home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ADC_TP3.ZIP / BUILD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-03-01  |  15.8 KB  |  499 lines

  1. { This program is hereby placed in the public domain and may be freely copied
  2.   and distributed as long as the author is given due credit.  Comments,
  3.   suggestions and patches are more then welcome. Forward to me on CompuServe
  4.   or Delphi and I will see that they are incorporated with credit due.
  5.  
  6. 12-26-85 Version 1.00
  7. 12-30-85 Extract Procedure Replaced by breaking Dos file into seperate
  8.          components when they are extracted from the Buffer Version 1.05   }
  9.  
  10.  
  11. program Batch_File_Builder ( input, output );
  12.  
  13. {$C-,U-,V-,R-}
  14.  
  15. const
  16.   Version       = '1.05';
  17.   Max_Path      = 63;       { Maximum Characters in any DOS path }
  18.   Max_Lines     = 10;       { Maximum Batch file Lines }
  19.   Register      : record    { MsDos and Bios function calls }
  20.                     case integer of
  21.                       1 : ( AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : Integer );
  22.                       2 : ( AL, AH, BL, BH, CL, CH, DL, DH            : Byte    );
  23.                     end = ( AX : 0 );
  24.  
  25.  
  26. type
  27.   String3       = String[  3 ];
  28.   String8       = String[  8 ];
  29.   String12      = String[ 12 ];
  30.   String80      = String[ 80 ];
  31.   Buffer        = array[ 1..128 ] of byte;            { Disk Transfer Area }
  32.   Sort_Type     = (  N, E, NE, EN );                  { Name, Extension }
  33.   Dos_File_Type = String[ Max_Path ];                 { All Dos Files   }
  34.   Batch_Lines   = array[ 1.. Max_Lines ] of String80; { Batch Line Storage }
  35.   Entry         = record
  36.                     Name : String8;
  37.                     Ext  : String3;
  38.                   end;
  39.   Link          = ^Node;                              { Dynamic Heap Structure }
  40.   Node          = record
  41.                     Dos_File : Entry;
  42.                     Process  : Boolean;             { Used if Negate active }
  43.                     Left     : Link;                { Left and Right Node Pointers }
  44.                     Right    : Link;
  45.                   end;
  46.  
  47.  
  48. var
  49.   Batch_Spec    : Dos_File_Type;      { Batch File Name to Create }
  50.   File_Spec     : Dos_File_Type;      { Files to qualify or not qualify }
  51.   Mask          : String12;           { Used if Negate active }
  52.   File_Var      : Text;               { Batch File handle }
  53.   DTA           : Buffer;             { Disk Transfer Area }
  54.   Sort_On       : Sort_Type;          { What order to Sort by }
  55.   Reverse       : Boolean;            { Ascending or Descending Sort }
  56.   Negate        : Boolean;            { Negate on or off }
  57.   Line          : Batch_Lines;        { Batch file lines }
  58.   Num_Lines     : byte;               { Total of batch lines }
  59.   Index         : byte;               { General String Index }
  60.   Dir_File      : Entry;              { File as returned by DOS }
  61.   Binary_Tree   : Link;               { Tree of File Names }
  62.   Now_Tree      : Link;               { Temporary Holding Pointer }
  63.   File_Count    : integer;            { Count of files to Process }
  64.   Back_Color    : byte;               { Color variables for Mono and Color }
  65.   Hi_Fore_Color : byte;
  66.   Lo_Fore_Color : byte;
  67.   Message_Color : byte;
  68.  
  69.  
  70.  
  71.   procedure Set_Border( Color : byte);   { Bios Video Call to set Border Color }
  72.   begin
  73.     Register.AH := 11;                   { Set Color Palette }
  74.     Register.BH :=  0;
  75.     Register.BL :=  Color;
  76.     Intr( $10, Register );
  77.   end; { procedure Set_Border }
  78.  
  79.  
  80.  
  81.   function Video_Mode : byte;         { Bios Video Call to determine Monitor }
  82.   begin                               { Commercial Programmers take note this }
  83.     Register.AH := 15;                { call really eats up a lot of code,    }
  84.     Intr( $10, Register );            { slows execution down, and frustrates  }
  85.     Video_Mode := Register.AL;        { users by not asking for Monitor type  }
  86.   end; { function Video_Mode }
  87.  
  88.  
  89.   procedure Set_DTA;                  { Set the Disk Transfer Area }
  90.   begin                               { This call could be eliminated as DOS  }
  91.     File_Spec   := File_Spec + #00;   { defaults a DTA at offset $80 into the }
  92.     Register.AH := $1A;               { Program Segment Prefix. However program }
  93.     Register.DS := Seg( DTA );        { will not run in Turbo Enviorment }
  94.     Register.DX := Ofs( DTA );
  95.     MsDos( Register );                            { Set DTA Location }
  96.   end; { procedure Set_DTA; }
  97.  
  98.  
  99.   procedure Get_First;                { Get the first matching file }
  100.   begin
  101.     Register.AH := $4E;
  102.     Register.DS :=       Seg( File_Spec );
  103.     Register.DX := succ( Ofs( File_Spec )) ;
  104.     Register.CX := 32;
  105.     MsDos( Register );
  106.   end; { procedure Get_First; }
  107.  
  108.  
  109.  
  110.   procedure Decode_Buffer;            { Extract the file name from the DTA }
  111.  
  112.   var
  113.     Dot : boolean;
  114.  
  115.   begin
  116.     Dir_File.Name := '';
  117.     Dir_File.Ext  := '';
  118.     Index := 31;
  119.     Dot   := FALSE;
  120.     while ( DTA[ Index ] <> 0 ) do
  121.       with Dir_File do
  122.         begin
  123.           Dot := Dot or ( DTA[ Index ] = ord( '.' ));
  124.           if Not Dot then
  125.             Name := Name + chr( DTA[ Index ] )
  126.           else
  127.             if DTA[ Index ] <> ord( '.' ) then
  128.               Ext := Ext + chr( DTA[ Index ] );
  129.           Index := succ( Index );
  130.         end;
  131.   end; { procedure Decode_Buffer; }
  132.  
  133.  
  134.  
  135.  
  136.   function Less( File1, File2 : Entry ) : boolean;
  137.   begin
  138.     case Reverse of
  139.       FALSE : case Sort_On of
  140.                  N : Less :=    File1.Name < File2.Name;
  141.                  E : Less :=    File1.Ext  < File2.Ext;
  142.                 NE : Less :=  ( File1.Name < File2.Name ) or
  143.                              (( File1.Name = File2.Name ) and
  144.                               ( File1.Ext  < File2.Ext  ));
  145.                 EN : Less :=  ( File1.Ext  < File2.Ext  ) or
  146.                              (( File1.Ext  = File2.Ext  ) and
  147.                               ( File1.Name < File2.Name ));
  148.               end;
  149.       TRUE  : case Sort_On of
  150.                  N : Less :=    File1.Name > File2.Name;
  151.                  E : Less :=    File1.Ext  > File2.Ext;
  152.                 NE : Less :=  ( File1.Name > File2.Name ) or
  153.                              (( File1.Name = File2.Name ) and
  154.                               ( File1.Ext  > File2.Ext  ));
  155.                 EN : Less :=  ( File1.Ext  > File2.Ext  ) or
  156.                              (( File1.Ext  = File2.Ext  ) and
  157.                               ( File1.Name > File2.Name ));
  158.               end;
  159.     end;
  160.   end; { function Less }
  161.  
  162.  
  163.  
  164.  
  165.   procedure Insert( var Tree : Link; New_File : Entry );
  166.   begin
  167.     if Tree = Nil then
  168.       begin
  169.         New( Tree );
  170.         with Tree^ do
  171.           begin
  172.             Left     := Nil;            { Either a new Tree or a new node }
  173.             Right    := Nil;
  174.             Dos_File := New_File;
  175.             Process  := TRUE;
  176.           end
  177.       end
  178.     else
  179.       with Tree^ do                         { Recursive call to find the right }
  180.         if Less( New_File, Dos_File ) then  { spot on the tree }
  181.           Insert( Left, New_File )
  182.         else
  183.           Insert( Right, New_File );
  184.   end; { procedure Insert }
  185.  
  186.  
  187.  
  188.   function Find( Tree : Link; This_File : Entry ) : Link;
  189.   begin
  190.     if Tree = Nil then
  191.       Find := Nil
  192.     else
  193.       with Tree^ do
  194.         if ( This_File.Name = Dos_File.Name) and
  195.            ( This_File.Ext  = Dos_File.Ext ) then
  196.           Find := Tree                            { We found it or }
  197.         else
  198.           if Less( This_File, Dos_File ) then     { we need to look further }
  199.             Find := Find( Left, This_File )
  200.           else
  201.             Find := Find( Right, This_File );
  202.   end; { function Find }
  203.  
  204.  
  205.  
  206.   procedure Print_Tree( Tree : Link );
  207.  
  208.   var
  209.     I : byte;
  210.  
  211.   begin
  212.     if Tree <> Nil then
  213.       with Tree^ do
  214.         begin
  215.           Print_Tree( Left );
  216.           if Tree^.Process then
  217.             begin                                  { Batch file lines are }
  218.               for Index := 1 to Num_Lines do       { created here }
  219.                 begin
  220.                   for I := 1 to length( Line[ Index ] ) do
  221.                     if Line[ Index ][ I ] <> '!' then
  222.                       write( File_Var, Line[ Index ][ I ] )
  223.                     else
  224.                       write( File_Var, Tree^.Dos_File.Name, '.', Tree^.Dos_File.Ext );
  225.                   writeln( File_Var );
  226.                   write( '.' );
  227.                 end;
  228.             end;
  229.           Print_Tree( Right );
  230.         end;
  231.   end; { procedure Print_Tree }
  232.  
  233.  
  234.  
  235.   procedure Build_Batch;
  236.   begin
  237.     write( 'Creating Batch File ' );   { Batch file is opened and closed here }
  238.     assign( File_Var, Batch_Spec );
  239.     rewrite( File_Var );
  240.     writeln( File_Var, 'ECHO OFF' );
  241.     writeln( File_Var, 'CLS' );
  242.     writeln( File_Var, 'ECHO Batch File Builder  Version ', Version );
  243.     Print_Tree( Binary_Tree );
  244.     close( File_Var );
  245.     writeln( ' Finished.' );
  246.   end; { procedure Build_Batch; }
  247.  
  248.  
  249.  
  250.   procedure Build_Tree;
  251.   begin
  252.     write( 'Building Tree ' );
  253.     Set_DTA;
  254.     Get_First;
  255.     while Register.AX = 0 do                { Are there still more files? }
  256.       begin
  257.         Decode_Buffer;
  258.         Insert( Binary_Tree, Dir_File );
  259.         write( '.' );                       { User friendly }
  260.         File_Count := succ( File_Count );
  261.         Register.AH := $4F;                 { Dos call for next match }
  262.         MsDos( Register );
  263.       end;
  264.     if Negate then
  265.       begin
  266.         writeln;
  267.         write( 'Searching Tree ' );
  268.         Delete( File_Spec, pos( '*.*', File_Spec ), 4 );
  269.         File_Spec := File_Spec + Mask;
  270.         Set_DTA;
  271.         Get_First;
  272.         while Register.AX = 0 do            { If the user opted to negate   }
  273.           begin                             { we first build a tree for *.* }
  274.             Decode_Buffer;                  { and then for the users mask   }
  275.             Now_Tree := Find( Binary_Tree, Dir_File );
  276.             Now_Tree^.Process := FALSE;     { we then search the tree for the }
  277.             write( '.' );                   { file and flag it as no process }
  278.             File_Count := pred( File_Count );
  279.             Register.AH := $4F;
  280.             MsDos( Register );
  281.           end;
  282.       end;
  283.     writeln;
  284.   end; { procedure Build_Tree; }
  285.  
  286.  
  287.  
  288.  
  289.   procedure Get_User_Info;
  290.  
  291.   const
  292.     Yes_No   : set of char = [ 'Y', 'y', 'N', 'n' ];
  293.     Yes      : set of char = [ 'Y', 'y' ];
  294.  
  295.   type
  296.     Char_Set = set of Char;
  297.  
  298.   var
  299.     C        : char;
  300.  
  301.  
  302.     function Get_Key( Prompt : String80; Valid : Char_Set ) : char;
  303.     begin
  304.       TextColor( Lo_Fore_Color );
  305.       repeat
  306.         write( #13, Prompt + '-'#16' ':20 );
  307.         read ( kbd, C );
  308.       until C in Valid;
  309.       TextColor( Hi_Fore_Color );
  310.       writeln( C );
  311.       Get_Key := C;
  312.     end; { function Get_Key }
  313.  
  314.  
  315.     procedure Get_Batch_Spec;
  316.  
  317.     var
  318.       Temp_File : File;
  319.  
  320.       function Exist( File_Name : Dos_File_Type ) : boolean;
  321.       begin
  322.         assign( Temp_File, File_Name );      { Guess what this does and }
  323.         {$I-} reset( Temp_File ); {$I+}      { where it came from }
  324.         Exist := IOResult = 0;
  325.         Close( Temp_File );
  326.       end; { function Exist }
  327.  
  328.  
  329.       function Validate( File_Name : Dos_File_Type ) : boolean;
  330.  
  331.       var
  332.         Dummy : boolean;
  333.  
  334.       begin
  335.         if Exist( File_Name ) then
  336.           Validate := TRUE
  337.         else
  338.           begin
  339.             assign( Temp_File, File_Name );      { This procedure validates     }
  340.             {$I-} rewrite( Temp_File );  {$I+}   { the drive path and file name }
  341.             Validate := IOResult = 0;            { but not wild cards. Dos }
  342.             {$I-} Erase( Temp_File );    {$I+}   { calls validate wild cards }
  343.             Dummy := IOResult = 0;               { with Register.AX returns. }
  344.             Close( Temp_File );
  345.           end;
  346.       end; { function Validate }
  347.  
  348.  
  349.     begin
  350.       while not Validate( Batch_Spec ) do
  351.         begin
  352.           gotoxy( 1, WhereY );
  353.           ClrEol;
  354.           TextColor( Lo_Fore_Color );
  355.           write( 'Batch File Name -'#16' ':20 );
  356.           TextColor( Hi_Fore_Color );
  357.           read( Batch_Spec );
  358.         end;
  359.       writeln;
  360.     end;  { procedure Get_Batch_Spec; }
  361.  
  362.  
  363.     procedure Get_File_Spec;
  364.     begin
  365.       Register.AX := 99;
  366.       while Register.AX <> 0 do
  367.         begin
  368.           gotoxy( 1, WhereY );
  369.           ClrEol;
  370.           TextColor( Lo_Fore_Color );
  371.           write( 'File Spec -'#16' ':20 );
  372.           TextColor( Hi_Fore_Color );
  373.           read( File_Spec );
  374.           Set_DTA;
  375.           Get_First;
  376.         end;
  377.       writeln;
  378.     end; { procedure Get_File_Spec; }
  379.  
  380.  
  381.     procedure Get_Sort;
  382.     begin
  383.       TextColor( Lo_Fore_Color );
  384.       write( 'Sort Orders -'#16' ' :20 );
  385.       TextColor( Message_Color );
  386.       writeln( '1. Name              '    );
  387.       writeln( '2. Extension         ':41 );
  388.       writeln( '3. Name and Extension':41 );
  389.       writeln( '4. Extension and Name':41 );
  390.       case Get_Key( 'Sort Order ', [ '1'..'4' ] ) of
  391.         '1' : Sort_On := N;
  392.         '2' : Sort_On := E;
  393.         '3' : Sort_On := NE;
  394.         '4' : Sort_On := EN;
  395.       end;
  396.       Reverse := Get_Key( 'Reverse Sort ', Yes_No ) in Yes;
  397.     end; { procedure Get_Sort; }
  398.  
  399.  
  400.     procedure Get_Negate;
  401.     begin
  402.       Negate := Get_Key( 'Negate Mask ',  Yes_No ) in Yes;
  403.       if Negate then   { If negate we strip off user mask and change to *.* }
  404.         begin          { later we will change back }
  405.           Index := length( File_Spec );
  406.           while not ( File_Spec[ Index ] in [ '\', ':' ] ) and ( Index > 1 ) do
  407.             Index := pred( Index );
  408.           if File_Spec[ Index ] in [ '\', ':' ] then
  409.             Index := succ( Index );
  410.           Mask := copy( File_Spec, Index, length( File_Spec ) - Index );
  411.           Delete( File_Spec, Index, length( File_Spec ) - pred( Index ) );
  412.           File_Spec := File_Spec + '*.*';
  413.         end;
  414.     end; { procedure Get_Negate; }
  415.  
  416.  
  417.  
  418.     procedure Get_Batch_Lines;
  419.  
  420.     var
  421.       More : boolean;
  422.  
  423.     begin
  424.       writeln;
  425.       writeln;
  426.       TextColor( Message_Color );
  427.       writeln( 'Enter Batch Files Lines.  Use ''!'' for file name substitution symbol.' );
  428.       writeln;
  429.       Index := 1;
  430.       More  := TRUE;
  431.       while More do
  432.         begin
  433.           TextColor( Lo_Fore_Color );
  434.           write( '-'#16' ' );
  435.           TextColor( Hi_Fore_Color );
  436.           readln( Line[ Index ] );
  437.           More  := ( length( Line[ Index ] ) <> 0 ) and ( Index < Max_Lines );
  438.           if More then
  439.             Index := succ( Index )
  440.           else
  441.             Num_Lines := pred(Index );
  442.       end;
  443.     end; { procedure Get_Batch_Lines; }
  444.  
  445.  
  446.   begin
  447.     Get_Batch_Spec;
  448.     Get_File_Spec;
  449.     Get_Negate;
  450.     Get_Sort;
  451.     Get_Batch_Lines;
  452.   end; { procedure Get_User_Info; }
  453.  
  454.  
  455.  
  456.   procedure Init;
  457.   begin
  458.     Binary_Tree := Nil;
  459.     Batch_Spec  := '';
  460.     File_Spec   := '';
  461.     Mask        := '';
  462.     File_Count  := 0;
  463.     if Video_Mode = 7 then
  464.       begin
  465.         Back_Color    := Black;            { MonoChrome defaults }
  466.         Hi_Fore_Color := White;
  467.         Lo_Fore_Color := LightGray;
  468.         Message_Color := White;
  469.         TextMode;
  470.       end
  471.     else
  472.       begin
  473.         Back_Color    := Black;            { Color defaults }
  474.         Hi_Fore_Color := LightCyan;
  475.         Lo_Fore_Color := Yellow;
  476.         Message_Color := LightMagenta;
  477.         Set_Border( Back_Color );
  478.         TextMode( C80 );
  479.       end;
  480.     TextBackGround( Back_Color );
  481.     TextColor( Message_Color );
  482.     ClrScr;
  483.     writeln( 'Batch File Builder Version ', Version );
  484.     writeln( 'Public Domain Software by Jay S Pondy' );
  485.     writeln;
  486.   end; { Init }
  487.  
  488.  
  489. begin
  490.   Init;
  491.   Get_User_Info;
  492.   TextColor( Message_Color );
  493.   Build_Tree;
  494.   if ( File_Count > 0 ) and ( Num_Lines > 0 ) then
  495.     Build_Batch
  496.   else
  497.     writeln( 'Batch File not built. No Files and / or No Lines to Process.' );
  498. end.  { program Batch_File_Builder ( input, output ); }
  499.