home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / PASTUT24.ZIP / PTUTRSRC.ZIP / OT4.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-12-01  |  21.6 KB  |  558 lines

  1.                                      (* Chapter 14 - Program 13 *)
  2. program Oak_Tree;         (* This version is for TURBO Pascal 4.0 *)
  3.  
  4. (*                 XXX     X    X   X  XXXXX  XXXX   XXXXX  XXXXX
  5.   Oct 18, 1988    X   X   X X   X  X     X    X   X  X      X
  6.                   X   X  X   X  X X      X    X   X  X      X
  7.                   X   X  X   X  XX       X    XXXX   XXX    XXX
  8.                   X   X  XXXXX  X X      X    X X    X      X
  9.                   X   X  X   X  X  X     X    X  X   X      X
  10.                    XXX   X   X  X   X    X    X   X  XXXXX  XXXXX
  11. *)
  12.  
  13. uses Dos, Printer;
  14.  
  15. const  Page_Size = 66;
  16.        Max_Lines = 55;
  17.  
  18. type   Command_String = string[127];
  19.  
  20.        Output_Type = (Directories,Files);
  21.  
  22.        Dir_Rec     = ^Dirtree;    (* Dynamic storage for dir names *)
  23.        Dirtree     = record
  24.          Next      : Dir_Rec;
  25.          Dir_Name  : string[12];
  26.       end;
  27.  
  28.        Filerec     = ^Filetree;         (* Dynamic storage for the *)
  29.        Filetree    = record             (* filename sorting tree   *)
  30.          Left      : Filerec;
  31.          Right     : Filerec;
  32.          FileData  : SearchRec;                 (* From Dos module *)
  33.        end;
  34.  
  35. (*  Record definition from page 408 of the TURBO Pascal 4.0 manual *)
  36. (*     type SearchRec = record                                     *)
  37. (*                        Fill : array[1..21] of byte;             *)
  38. (*                        Attr : byte;                             *)
  39. (*                        Time : longint;                          *)
  40. (*                        Size : longint;                          *)
  41. (*                        Name : string[12];                       *)
  42. (*                      end;                                       *)
  43.  
  44. var   File_Record    : SearchRec;      (* A working file record    *)
  45.       File_Point     : Filerec;        (* Pointer to a file record *)
  46.       Page_Number    : integer;
  47.       Line_Number    : integer;
  48.       Directory_Count : integer;
  49.       Recpack        : Registers;               (* From Dos module *)
  50.       File_Request   : string[25];
  51.       Root_Mask      : Command_String;(* Used for vol-label search *)
  52.       Starting_Path  : Command_String;
  53.  
  54.       Total_Clusters      : longint;
  55.       Disk_Total_Bytes    : longint;
  56.       Cluster_Size        : integer;
  57.       Sectors_Per_Cluster : integer;
  58.       Bytes_Per_Sector    : integer;
  59.       Free_Clusters       : longint;
  60.       Free_Bytes          : longint;
  61.       Total_Cbytes        : longint;
  62.       Total_Bytes         : longint;
  63.       All_Files           : integer;    (* Number of files on disk *)
  64.       Req_Files           : integer; (* Number of files in request *)
  65.  
  66.       Do_We_Print    : boolean;           (* Print or not          *)
  67.       Do_All_Stats   : boolean;           (* List all disk stats?  *)
  68.       No_Files_Out   : boolean;           (* List no files         *)
  69.       Date_Time_Rec  : DateTime;          (* From Dos module       *)
  70.  
  71. (* **************************************************** Initialize *)
  72. (* This procedure is used to initialize some variables and strings *)
  73. (* prior to starting the disk search.                              *)
  74. procedure Initialize;
  75. begin
  76.    Page_Number := 1;
  77.    Line_Number := 1;
  78.    Directory_Count := 0;
  79.    Total_Cbytes := 0;
  80.    Total_Bytes := 0;
  81.    All_Files := 0;
  82.    Req_Files := 0;
  83.    Root_Mask := 'C:\*.*';
  84.    Root_Mask[Length(Root_Mask) + 1] := Chr(0);
  85.                            (* Get the current default drive letter *)
  86.    Recpack.AX := $1900;
  87.    Intr($21,Recpack);
  88.    Root_Mask[1] := Chr(Recpack.AX and $F + Ord('A'));
  89. end;
  90.  
  91. (* ****************************** Read And Parse Command Arguments *)
  92. (* This procedure reads in the command line arguments, parses them,*)
  93. (* and sets up the switches and defaults for the disk searches.    *)
  94. procedure Read_And_Parse_Command_Arguments;
  95. var    Parameters         : Command_String;
  96.        Index              : byte;
  97. begin
  98.    Do_We_Print := FALSE;
  99.    Do_All_Stats := FALSE;
  100.    No_Files_Out := FALSE;
  101.    File_Request := '*.*';
  102.  
  103.    for Index := 1 to ParamCount do begin
  104.       Parameters := ParamStr(Index);
  105.                                      (* Find command line switches *)
  106.       if Parameters[1] = '/' then begin
  107.          if Upcase(Parameters[2]) = 'P' then Do_We_Print := TRUE;
  108.          if Upcase(Parameters[2]) = 'N' then No_Files_Out := TRUE;
  109.          if Upcase(Parameters[2]) = 'S' then Do_All_Stats := TRUE;
  110.       end
  111.       else begin                   (* Find designated drive letter *)
  112.          if Parameters[2] = ':' then begin
  113.             Root_Mask[1] := Parameters[1];
  114.             Delete(Parameters,1,2);
  115.          end;
  116.  
  117.          if Parameters = '' then              (* No filename given *)
  118.             File_Request := '*.*'
  119.          else                                   (* Filename listed *)
  120.             File_Request := Parameters;
  121.       end;
  122.    end;
  123.                      (* get the current path on the selected drive *)
  124.    Getdir(Ord(Root_Mask[1])-Ord('A') + 1,Starting_Path);
  125.    if Length(Starting_Path) > 3 then
  126.       Starting_Path := Starting_Path + '\';
  127.  
  128. end;
  129.  
  130. (* ********************************************* count print lines *)
  131. procedure Count_Print_Lines(Line_Count : byte);
  132. var Count : byte;
  133. begin
  134.    if Do_We_Print then begin
  135.       if Line_Count > 250 then (* This signals the end of the tree *)
  136.       begin                    (* Space up to a new page           *)
  137.          Writeln(Lst,Char(12));
  138.          Line_Number := 1;
  139.          Line_Count := 0;
  140.       end;
  141.       Line_Number := Line_Number + Line_Count;
  142.       if Line_Number > Max_Lines then begin
  143.          Page_Number := Page_Number +1;
  144.          Writeln(Lst,Char(12));                (* Go to a new page *)
  145.          Writeln(Lst);                       (* Move down one line *)
  146.          Writeln(Lst,'Page':60,
  147.                                                Page_Number:4);
  148.          Writeln(Lst);
  149.          Line_Number := 1;
  150.       end;
  151.    end;
  152. end;
  153.  
  154. (* ************************************************** Print Header *)
  155. (* In this section of code, the volume label is found and displayed*)
  156. (* and the present time and date are determined and displayed.     *)
  157. procedure Print_Header;
  158. var Year,Month,Day,DayOfWeek  : word;
  159.     Hour,Minute,Second,Sec100 : word;
  160.     Index                 : integer;
  161. begin
  162.    if Do_We_Print then begin
  163.       Writeln(Lst);
  164.       Write(Lst,'          Directory for ');
  165.    end;
  166.    Write('          Directory for ');
  167. {  Recpack.AX := $1A00;                          (* Set up the DTA *)
  168.    Recpack.DS := Seg(Dta);
  169.    Recpack.DX := Ofs(Dta);
  170.    Msdos(Recpack);                           (* DTA setup complete *)
  171.    Error := Recpack.AX and $FF;
  172.    if Error > 0 then Writeln('DTA setup error ',Error);
  173.  }
  174.    FindFirst(Root_Mask,$08,File_Record);      (* Get the volume ID *)
  175.    if ((DosError > 0) or (File_Record.Attr <> 8)) then begin
  176.       if Do_We_Print then
  177.          Write(Lst,' <no vol label> ');
  178.       Write(' <no vol label> ');
  179.    end
  180.    else begin                            (* Write out Volume Label *)
  181.       if Do_we_Print then
  182.          Write(Lst,File_Record.Name);
  183.       Write(File_Record.Name);
  184.    end;
  185.  
  186.    GetDate(Year,Month,Day,DayOfWeek);      (* Get the present date *)
  187.    GetTime(Hour,Minute,Second,Sec100);     (* Get the present time *)
  188.    Write('             ');
  189.    Write(Month,'/',Day,'/',Year);
  190.    Writeln('    ',Hour,':',Minute);
  191.    Writeln;
  192.    if Do_We_Print then begin
  193.       Write(Lst,'             ');
  194.       Write(Lst,Month,'/',Day,'/',Year);
  195.       Writeln(Lst,'    ',Hour,':',Minute);
  196.       Writeln(Lst);
  197.       Count_Print_Lines(2);
  198.    end;
  199.                                   (* get all of the disk constants *)
  200.    Recpack.AX := $3600;
  201.    Recpack.DX := (Ord(Root_Mask[1]) - 64) and $F;
  202.    Msdos(Recpack);
  203.    Sectors_Per_Cluster := Recpack.AX;
  204.    Free_Clusters := Recpack.BX;
  205.    Bytes_Per_Sector := Recpack.CX;
  206.    Total_Clusters := Recpack.DX;
  207.  
  208.    Cluster_Size := Bytes_Per_Sector * Sectors_Per_Cluster;
  209.  
  210.    if Do_All_Stats then begin (* Print out disk stats if asked for *)
  211.       Write('             bytes/sector =',Bytes_Per_Sector:6);
  212.       Disk_Total_Bytes := Total_Clusters * Cluster_Size;
  213.       Writeln('       total disk space =',Disk_Total_Bytes:12);
  214.       Write('            bytes/cluster =',Cluster_Size:6);
  215.       Free_Bytes := Free_Clusters * Cluster_Size;
  216.       Writeln('        free disk space =',Free_Bytes:12);
  217.       Writeln;
  218.       if Do_We_Print then begin
  219.          Write(Lst,'             bytes/sector =',Bytes_Per_Sector:6);
  220.          Writeln(Lst,'       total disk space =',
  221.                                              Disk_Total_Bytes:12);
  222.          Write(Lst,'            bytes/cluster =',Cluster_Size:6);
  223.          Writeln(Lst,'        free disk space =',Free_Bytes:12);
  224.          Writeln(Lst);
  225.          Count_Print_Lines(3);
  226.       end;
  227.    end;
  228. end;
  229.  
  230.  
  231. (* *************************************** Position a new filename *)
  232. (* When a new filename is found, this routine is used to locate it *)
  233. (* in the B-TREE that will be used to sort the filenames alphabet- *)
  234. (* ically.                                                         *)
  235. procedure Position_A_New_Filename(Root, New : Filerec);
  236. var    Index   : integer;
  237.        Done    : boolean;
  238. begin
  239.    Index := 1;
  240.    Done := FALSE;
  241.    repeat
  242.       if New^.FileData.Name < Root^.FileData.Name then begin
  243.          Done := TRUE;
  244.          if Root^.Left = nil then Root^.Left := New
  245.          else
  246.             Position_A_New_Filename(Root^.Left,New);
  247.       end
  248.       else if New^.FileData.Name > Root^.FileData.Name then
  249.       begin
  250.          Done := TRUE;
  251.          if Root^.Right = nil then
  252.             Root^.Right := New
  253.          else
  254.             Position_A_New_Filename(Root^.Right,New);
  255.       end;
  256.       Index := Index +1;
  257.    until (Index = 13) or Done;
  258. end;
  259.  
  260.  
  261. (* ************************************************** Print a file *)
  262. (* This is used to print the data for one complete file.  It is    *)
  263. (* called with a pointer to the root and an attribute that is to be*)
  264. (* printed.  Either the directories are printed (attribute = $10), *)
  265. (* or the files are printed.                                       *)
  266. procedure Print_A_File(Root : Filerec;
  267.                        Which_List : Output_Type);
  268. var Index,Temp  : byte;
  269. begin
  270.    Temp := Root^.FileData.Attr;
  271.    if ((Temp =  $10) and (Which_List = Directories)) or
  272.                  ((Temp <> $10) and (Which_List = Files)) then begin
  273.       Write('                ');
  274.       case Temp of
  275.          $27 : Write('<HID>  ');
  276.          $10 : Write('<DIR>  ');
  277.          $20 : Write('       ')
  278.          else  Write('<',Temp:3,'>  ');
  279.       end;   (* of case *)
  280.       if Do_We_Print then begin
  281.          Write(Lst,'                ');
  282.          case Temp of
  283.             $27 : Write(Lst,'<HID>  ');
  284.             $10 : Write(Lst,'<DIR>  ');
  285.             $20 : Write(Lst,'       ')
  286.             else  Write(Lst,'<',Temp:3,'>  ');
  287.          end;   (* of case *)
  288.       end;
  289.                                          (* Write out the filename *)
  290.       Write(Root^.FileData.Name);
  291.       for Index := 1 to (15 - Length(Root^.FileData.Name)) do
  292.          Write(' ');
  293.       if Do_We_Print then begin
  294.          Write(Lst,Root^.FileData.Name);
  295.          for Index := 1 to (15 - Length(Root^.FileData.Name)) do
  296.             Write(Lst,' ');
  297.       end;
  298.                                         (* Write out the file size *)
  299.       Write(Root^.FileData.Size:9);
  300.       if Do_We_Print then
  301.          Write(Lst,Root^.FileData.Size:9);
  302.                                (* Write out the file date and time *)
  303.       UnpackTime(Root^.FileData.Time, Date_Time_Rec);
  304.       Write('   ',Date_Time_Rec.Month:2,'/');
  305.       Write(Date_Time_Rec.Day:2,'/');
  306.       Write(Date_Time_Rec.Year,'   ');
  307.       Write('  ',Date_Time_Rec.Hour:2,':');
  308.       Writeln(Date_Time_Rec.Min:2);
  309.       if Do_We_Print then begin
  310.          Write(Lst,'   ',Date_Time_Rec.Month:2,'/');
  311.          Write(Lst,Date_Time_Rec.Day:2,'/');
  312.          Write(Lst,Date_Time_Rec.Year,'   ');
  313.          Write(Lst,'  ',Date_Time_Rec.Hour:2,':');
  314.          Writeln(Lst,Date_Time_Rec.Min:2);
  315.          Count_Print_Lines(1);
  316.       end;
  317.    end;
  318. end;
  319.  
  320. (* ********************************************* Print a directory *)
  321. (* This is a recursive routine to print out the filenames in alpha-*)
  322. (* betical order.  It uses a B-TREE with "infix" notation.  The    *)
  323. (* actual printing logic was removed to another procedure so that  *)
  324. (* the recursive part of the routine would not be too large and    *)
  325. (* fill up the heap too fast.                                      *)
  326. procedure Print_A_Directory(Root         : Filerec;
  327.                             Which_List   : Output_Type);
  328. begin
  329.    if Root^.Left <> nil then
  330.       Print_A_Directory(Root^.Left,Which_List);
  331.  
  332.    Print_A_File(Root,Which_List);        (* Write out the filename *)
  333.  
  334.    if Root^.Right <> nil then
  335.       Print_A_Directory(Root^.Right,Which_List);
  336. end;
  337.  
  338. (* **************************************************** Erase tree *)
  339. (* After the directory is printed and counted, it must be erased or*)
  340. (* the "heap" may overflow for a large disk with a lot of files.   *)
  341. procedure Erase_Tree(Root : Filerec);
  342. begin
  343.    if Root^.Left  <> nil then Erase_Tree(Root^.Left);
  344.    if Root^.Right <> nil then Erase_Tree(Root^.Right);
  345.    Dispose(Root);
  346. end;
  347.  
  348. (* ************************************************ Do A Directory *)
  349. (* This procedure reads all entries in any directory and sorts the *)
  350. (* filenames alphabetically.  Then it prints out the complete stat-*)
  351. (* istics, and calls itself to do all of the same things for each  *)
  352. (* of its own subdirectories.  Since each subdirectory also calls  *)
  353. (* each of its subdirectories, the recursion continues until there *)
  354. (* are no more subdirectories.                                     *)
  355. procedure Do_A_Directory(Input_Mask : Command_String);
  356. var   Mask          : Command_String;
  357.       Count,Index   : integer;
  358.       Cluster_Count : longint;
  359.       Cluster_Bytes : longint;
  360.       Byte_Count    : longint;
  361.       Tree_Root     : Filerec;                (* Root of file tree *)
  362.       Dir_Root      : Dir_Rec;
  363.       Dir_Point     : Dir_Rec;
  364.       Dir_Last      : Dir_Rec;
  365.       File_Record   : SearchRec;
  366.  
  367.     (* This embedded procedure is called upon to store all of the  *)
  368.     (* directory names in a linear linked list rather than a       *)
  369.     (* B-TREE since it should be rather short and efficiency of    *)
  370.     (* sorting is not an issue.  A bubble sort will be used on it. *)
  371.     procedure Store_Dir_Name;
  372.     begin
  373.        if File_Record.Attr = $10 then begin (* Pick out directories*)
  374.                     (* Directory name found, ignore if it is a '.' *)
  375.           if File_Record.Name[1] <> '.' then begin
  376.              New(Dir_Point);
  377.              Dir_Point^.Dir_Name := File_Record.Name;
  378.              Dir_Point^.Next := nil;
  379.              if Dir_Root = nil then
  380.                 Dir_Root := Dir_Point
  381.              else
  382.                 Dir_Last^.Next := Dir_Point;
  383.              Dir_Last := Dir_Point;
  384.           end;
  385.        end;
  386.     end;
  387.  
  388.      (* This is the procedure that sorts the directory names after *)
  389.      (* they are all accumulated.  It uses a bubble sort technique *)
  390.      (* which is probably the most inefficient sort available.  It *)
  391.      (* is perfectly acceptable for what is expected to be a very  *)
  392.      (* short list each time it is called.  More than 30 or 40     *)
  393.      (* subdirectories in one directory would not be good practice *)
  394.      (* but this routine would sort any number given to it.        *)
  395.      procedure Sort_Dir_Names;
  396.      var Change      : byte;
  397.          Save_String : string[15];
  398.          Dir_Next    : Dir_Rec;
  399.      begin
  400.         repeat
  401.            Change := 0;
  402.            Dir_Point := Dir_Root;
  403.            while Dir_Point^.Next <> nil do
  404.               begin
  405.               Dir_Next := Dir_Point^.Next;
  406.               Save_String := Dir_Next^.Dir_Name;
  407.               if Save_String < Dir_Point^.Dir_Name then begin
  408.                  Dir_Next^.Dir_Name := Dir_Point^.Dir_Name;
  409.                  Dir_Point^.Dir_Name := Save_String;
  410.                  Change := 1;
  411.               end;
  412.               Dir_Point := Dir_Point^.Next;
  413.            end;
  414.         until Change = 0;    (* No swaps in this pass, we are done *)
  415.      end;
  416.  
  417. begin (* Do_A_Directory procedure *)
  418.    Count := 0;
  419.    Cluster_Count := 0;
  420.    Dir_Root := nil;
  421.    Mask := Input_Mask + '*.*';
  422.    Mask[Length(Mask) + 1] := Chr(0);    (* A trailing zero for DOS *)
  423.                                    (* Count all files and clusters *)
  424.    repeat
  425.       if Count = 0 then               (* Get first directory entry *)
  426.          FindFirst(Mask,$17,File_Record)
  427.       else                     (* Get additional directory entries *)
  428.          FindNext(File_Record);
  429.       if DosError = 0 then begin       (* A good filename is found *)
  430.          Count := Count +1;            (* Add one for a good entry *)
  431.  
  432.                            (* Count up the number of clusters used *)
  433.          Index := File_Record.Size div Cluster_size;
  434.          if File_Record.Size mod Cluster_Size > 0 then
  435.             Index := Index + 1;            (* If a fractional part *)
  436.          Cluster_Count := Cluster_Count + Index;
  437.          if Index = 0 then     (* This is a directory, one cluster *)
  438.             Cluster_Count := Cluster_Count + 1;
  439.          Store_Dir_Name;
  440.       end;
  441.    until DosError > 0;
  442.    Cluster_Bytes := Cluster_Count * Cluster_Size;
  443.    Directory_Count := Directory_Count + 1;
  444.    Write('    ',Directory_Count:3,'. ');
  445.    Write(Input_Mask);
  446.    for Index := 1 to (32 - Length(Input_Mask)) do Write(' ');
  447.    Writeln(Count:4,' Files  Cbytes =',Cluster_Bytes:9);
  448.    if Do_We_Print then begin
  449.       Write(Lst,'    ',Directory_Count:3,'. ');
  450.       Write(Lst,Input_Mask);
  451.       for Index := 1 to (32 - Length(Input_Mask)) do Write(Lst,' ');
  452.       Writeln(Lst,Count:4,' Files  Cbytes =',Cluster_Bytes:9);
  453.       Count_Print_Lines(1);
  454.    end;
  455.    Total_Cbytes := Total_Cbytes + Cluster_Bytes;
  456.    All_Files := All_Files + Count;
  457.  
  458.                            (* files counted and clusters counted   *)
  459.                            (* Now read in only the requested files *)
  460.  
  461.    Count := 0;
  462.    Byte_Count := 0;
  463.    Tree_Root := nil;
  464.    if No_Files_Out <> TRUE then begin
  465.       Mask := Input_Mask + File_Request;
  466.       Mask[Length(Mask) + 1] := Chr(0); (* A trailing zero for DOS *)
  467.       repeat
  468.          New(File_Point);
  469.          if Count = 0 then            (* Get first directory entry *)
  470.             FindFirst(Mask,$17,File_Record)
  471.          else                  (* Get additional directory entries *)
  472.             FindNext(File_Record);
  473.          if DosError = 0 then begin    (* A good filename is found *)
  474.             Count := Count +1;         (* Add one for a good entry *)
  475.             File_Point^.Left := nil;
  476.             File_Point^.Right := nil;
  477.             File_Point^.FileData := File_Record;
  478.             if Tree_Root = nil then begin (* Pt to 1st elem in tree*)
  479.                Tree_Root := File_Point;
  480.             end
  481.             else begin     (* Point to additional elements in tree *)
  482.                Position_A_New_Filename(Tree_Root,File_Point);
  483.             end;
  484.  
  485.             Byte_Count := Byte_Count + File_Record.Size;
  486.          end;
  487.       until DosError > 0;
  488.    end;
  489.  
  490.    if Tree_Root <> nil then
  491.       Print_A_Directory(Tree_Root,Directories);
  492.    if Tree_Root <> nil then
  493.       Print_A_Directory(Tree_Root,Files);
  494.    if Count > 0 then begin
  495.       Writeln('                  ',Count:5,' Files ',
  496.                                  Byte_Count:17,' Bytes');
  497.       Writeln;
  498.       if Do_We_Print then begin
  499.          Writeln(Lst,'                  ',Count:5,' Files ',
  500.                                     Byte_Count:17,' Bytes');
  501.          Writeln(Lst);
  502.          Count_Print_Lines(2);
  503.       end;
  504.       Total_Bytes := Total_Bytes + Byte_Count;
  505.       Req_Files := Req_Files + Count;
  506.    end;
  507.                             (* Now go do all of the subdirectories *)
  508.    if Dir_Root <> nil then Sort_Dir_Names;
  509.    Dir_Point := Dir_Root;
  510.    while Dir_Point <> nil do begin
  511.       Mask := Input_Mask + Dir_Point^.Dir_Name + '\';
  512.       Do_A_Directory(Mask);
  513.       Dir_Point := Dir_Point^.Next;
  514.    end;
  515.                            (* Finally, erase the tree and the list *)
  516.    if Tree_Root <> nil then
  517.       Erase_Tree(Tree_Root);
  518.  
  519.    while Dir_Root <> nil do begin
  520.       Dir_Point := Dir_Root^.Next;
  521.       Dispose(Dir_Root);
  522.       Dir_Root := Dir_Point;
  523.    end;
  524. end;
  525.  
  526. (* ******************************************* Output Summary Data *)
  527. procedure Output_Summary_Data;
  528.  
  529. begin
  530.    Writeln;
  531.    Write('                     ',Req_Files:5,' Files');
  532.    Writeln(Total_Bytes:15,' Bytes in request');
  533.    Write('                     ',All_Files:5,' Files');
  534.    Writeln(Total_Cbytes:15,' Cbytes in tree');
  535.    Write('                                   ');
  536.    Free_Bytes := Free_Clusters * Cluster_Size;
  537.    Writeln(Free_Bytes:12,' Bytes free on disk');
  538.    if Do_We_Print then begin
  539.       Writeln(Lst);
  540.       Write(Lst,'                     ',Req_Files:5,' Files');
  541.       Writeln(Lst,Total_Bytes:15,' Bytes in request');
  542.       Write(Lst,'                     ',All_Files:5,' Files');
  543.       Writeln(Lst,Total_Cbytes:15,' Cbytes in tree');
  544.       Write(Lst,'                                   ');
  545.       Writeln(Lst,Free_Bytes:12,' Bytes free on disk');
  546.       Count_Print_Lines(4);      (* Signal the end, space paper up *)
  547.    end;
  548. end;
  549.  
  550. begin  (* Main program - Oak Tree ******************************** *)
  551.    Initialize;
  552.    Read_And_Parse_Command_Arguments;
  553.    Print_Header;
  554.    Do_A_Directory(Starting_Path);
  555.    Output_Summary_Data;
  556.    Count_Print_Lines(255);
  557. end.  (* Main Program *)
  558.