home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / CATLOG / CCAT26.LBR / CCAT26.PQS / CCAT26.PAS
Pascal/Delphi Source File  |  2000-06-30  |  19KB  |  600 lines

  1.  
  2. {                                    =========================================
  3.     program: CCAT                    | CCAT is a program which compares two  |
  4.     author:  Richard F. Mack         | MAST.LST output files from the MCAT   |
  5.              3407A Courtleigh Dr.    | and XCAT programs.  The output of     |
  6.              Baltimore, MD 21207     | CCAT is a double-ended listing of the |
  7.              301-922-1176            | the files in each MAST.LST which are  |
  8.     date:    24 DEC 85               | not common to both.  The output of    |
  9.     version: 2.6                     | CCAT is displayed on the screen and   |
  10.                                      | is written either to the printer or   |
  11.                                      | or to a disk file.  This version of   |
  12.                                      | CCAT is a complete rewrite of early   |
  13.                                      | versions and adds nice formatting to  |
  14.                                      | the output display.                   |
  15.                                      =========================================
  16.  
  17. NOTES:  If user wishes to rename CCATxx.COM,  the source file
  18.         must be recompiled - otherwise the overlay will not be found at
  19.         run-time.  A run-time error (F0) will be indicated.
  20.  
  21.         Arrays below are dimensioned for 62K of available memory.  If
  22.         memory overflow occurs, reduce the values of MaxCatSize and
  23.         MaxNumberOfLines (just below) in a 10:1 ratio and recompile.
  24.  
  25.         CCAT must be run from the logged drive.  (The program
  26.         expects the to find the overlay on the logged drive during
  27.         execution.)
  28.  
  29. version 2.6 - correct identification of EMPTY filename
  30.  
  31. }
  32.  
  33.  
  34. Program CompareCatalogs;
  35.  
  36. {$U-,C-}
  37.  
  38. Const
  39.   NameLength       = 12;
  40.   NameWithDrive    = 14;
  41.   HeaderLength     = 65;
  42.  
  43.   MaxCatSize       = 3000;      { This or less in reference list - FileOne. }
  44.   MaxNumberOfLines = 300;
  45.  
  46.   TempOut1         = 'Temp1.$$$';
  47.   TempOut2         = 'Temp2.$$$';
  48.  
  49. Type
  50.   FileName       = string[NameLength];
  51.   FNameWithDrive = string[NameWithDrive];
  52.   Header         = string[HeaderLength];
  53.   Sentence       = string[60];
  54.  
  55. Var
  56.   FirstCatSize,SecondCatSize,MismatchCount1,MismatchCount2: integer;
  57.   OutFileOpen,FirstPass,Mismatch1,Mismatch2,Hardcopy: boolean;
  58.   BakUpName,LineBuffer: FileName;
  59.   ReferenceList,ExaminedList,OutFileName: FNameWithDrive;
  60.   FileHeader1,FileHeader2: Header;
  61.   FileOne,FileTwo,OutFile,TempOutFile1,TempOutFile2: text;
  62.  
  63.   procedure Help;
  64.   type
  65.     Paragraph = array[1..14] of Sentence;
  66.   const
  67.     Instruction: Paragraph =
  68.     ('Usage:',
  69.      '',
  70.      'Place CCAT on the logged drive.',
  71.      '',
  72.      'Input MAST.LST files may be entered on the command line:',
  73.      '',
  74.      '            A>CCAT MAST.LST B:MAST.LST',
  75.      '',
  76.      'If not entered on the command line, user is prompted',
  77.      'for data.',
  78.      '',
  79.      'Output may be directed either to the printer or to disk.',
  80.      'Unless otherwise specified, differences between the',
  81.      'MAST.LST input files are written to ODDFILE.LST.');
  82.   var
  83.     i: integer;
  84.   begin
  85.     writeln(^J);
  86.     for i := 1 to 14 do writeln(^I,Instruction[i]);
  87.     halt
  88.   end;
  89.  
  90.   function Open(var fp:text; name: FNameWithDrive): boolean;
  91.   begin
  92.     Assign(fp,Name);
  93.     {$I-} reset(fp); {$I+}
  94.     If IOResult <> 0 then
  95.       begin
  96.         Open := False;
  97.         close(fp);
  98.       end
  99.       else
  100.         Open := True;
  101.   end { Open };
  102.  
  103.   procedure Abort(s: Sentence; f: FNameWithDrive);
  104.   begin
  105.     writeln(^J,'ABORT - ',s,f);
  106.     halt;
  107.   end;
  108.  
  109.   procedure OpenInputFiles;
  110.   var
  111.     Answer: char;
  112.  
  113.     procedure CapStr(LowCaseStr: FNameWithDrive; var UpCaseStr: FNameWithDrive);
  114.     var
  115.       i: integer;
  116.     begin
  117.       UpCaseStr := '';
  118.       for i := 1 to length(LowCaseStr) do
  119.       begin
  120.         UpCaseStr := UpCaseStr + UpCase(copy(LowCaseStr,i,1));
  121.       end;
  122.     end {CapStr};
  123.  
  124.     procedure WriteHeader;
  125.     begin
  126.       Writeln('CCAT Catalog Comparison Utility - Version 2.6   12/24/85',^J);
  127.     end;
  128.  
  129.  
  130.   begin {OpenInputFiles}
  131.     OutFileName := '';
  132.     If ParamCount = 0 then
  133.     begin
  134.       WriteHeader;
  135.       Write('Enter first filename: ');
  136.       readln(ReferenceList);
  137.       Write(^J,'Enter second filename: ');
  138.       readln(ExaminedList);
  139.     end
  140.     else
  141.     begin
  142.       WriteHeader;
  143.       ReferenceList := ParamStr(1);
  144.       ExaminedList  := ParamStr(2);
  145.       if ParamCount <> 2 then
  146.       begin
  147.         if ParamStr(1) = '?' then Help
  148.         else if UpCase(copy(ParamStr(1),1,1)) = 'H' then Help
  149.         else
  150.         begin
  151.           writeln(^J,'Try again - ERROR in entering input filenames.');
  152.           halt
  153.         end;
  154.       end;
  155.     end;
  156.     writeln(^J,'Do you want hard copy instead of disk file? (Y/N)');
  157.     read(kbd,Answer);
  158.     Hardcopy := (UpCase(Answer) = 'Y');
  159.     if not Hardcopy then
  160.     begin
  161.       Write(^J,'Enter output filename or <RET> : ');
  162.       readln(OutFileName);
  163.     end;
  164.     if OutFileName = '' then OutFileName := 'ODDFILE.LST';
  165.     CapStr(ReferenceList,ReferenceList);
  166.     CapStr(ExaminedList,ExaminedList);
  167.     CapStr(OutFileName,OutFileName);
  168.     if not Open(FileOne,ReferenceList) then
  169.          Abort('File not found:  ',ReferenceList);
  170.     if not Open(FileTwo,ExaminedList) then
  171.          Abort('File not found:  ',ExaminedList);
  172.     FirstPass := true;
  173.   end {OpenInputFiles};
  174.  
  175.   procedure ExchangeInputFiles;
  176.   begin
  177.     if not Open(FileOne,ExaminedList) then
  178.          Abort('File not found:  ',ExaminedList);
  179.     if not Open(FileTwo,ReferenceList) then
  180.          Abort('File not found:  ',ReferenceList);
  181.     FirstPass := false;
  182.   end {ExchangeInputFiles};
  183.  
  184.   function Exist(FileN: FNameWithDrive): boolean;
  185.   var F: file;
  186.   begin
  187.     assign(F,FileN);
  188.     {$I-} reset(F); {$I+}
  189.     Exist := (IOResult = 0);
  190.   end {Exist};
  191.  
  192.   procedure BakUp;
  193.   begin
  194.     if Exist(OutFileName) then
  195.     begin
  196.       BakUpName:=copy(OutFileName,1,length(OutfileName)-3)+'BAK';
  197.       if Exist(BakUpName) then
  198.       begin
  199.         assign(OutFile,BakUpName);
  200.         erase(OutFile)
  201.       end;
  202.       assign(OutFile,OutFileName);
  203.       rename(OutFile,BakUpName)
  204.     end;
  205.   end {BakUp};
  206.  
  207.   procedure OpenOutputFile;
  208.   Begin
  209.     Assign(OutFile,OutFileName);
  210.     {$I-} Rewrite(OutFile); {$I+}
  211.     OutFileOpen := (IOResult = 0);
  212.     if not OutFileOpen then Abort('Can''t open ',OutFileName);
  213.   end {OpenOutputFile};
  214.  
  215.   procedure OpenTempFiles;
  216.   var
  217.     TempFileOpen: boolean;
  218.   Begin
  219.     Assign(TempOutFile1,TempOut1);
  220.     {$I-} Rewrite(TempOutFile1); {$I+}
  221.     TempFileOpen := (IOResult = 0);
  222.     if not TempFileOpen then Abort('Can''t open temporary file:  ',TempOut1);
  223.     Assign(TempOutFile2,TempOut2);
  224.     {$I-} Rewrite(TempOutFile2); {$I+}
  225.     TempFileOpen := (IOResult = 0);
  226.     if not TempFileOpen then Abort('Can''t open temporary file:  ',TempOut2);
  227.   end {OpenTempFile};
  228.  
  229.   procedure ReopenTempFile(var TempOutFile: text; TempOut: FileName);
  230.   var
  231.     TempFileOpen: boolean;
  232.   begin
  233.     Assign(TempOutFile,TempOut);
  234.     {$I-} Reset(TempOutFile); {$I+}
  235.     TempFileOpen := (IOResult = 0);
  236.     if not TempFileOpen then Abort('Can''t open temporary file:  ',TempOut);
  237.   end; {ReopenTempFile}
  238.  
  239.   overlay procedure ProcessFile;
  240.   const
  241.     BuffSize      = 100;   { bite of FileTwo taken at each disk access }
  242.   type
  243.     InputBuff      = array[1..BuffSize] of FileName;
  244.     Catalog        = array[1..MaxCatSize] of FileName;
  245.   var
  246.     i,n,MismatchCounter,StartSearchPoint: integer;
  247.     CompareBuffFull,Mismatch,Temp1Open,Temp2Open: boolean;
  248.     OddOne,ProgramName: FileName;
  249.     CompareBuff: InputBuff;
  250.     RefFile: Catalog;
  251.  
  252.     procedure BinarySearch;
  253.     var
  254.       j,OffSet: integer;
  255.       Match,NotOnList: boolean;
  256.  
  257.       procedure OutMismatchToDisk;
  258.       var
  259.         TempFile1Open,TempFile2Open: boolean;
  260.       begin
  261.         if FirstPass then
  262.         begin
  263.           FileHeader1 := 'The following files in ' + ExaminedList +
  264.                          ' do not appear in ' + ReferenceList;
  265.           writeln(TempOutFile1,OddOne);
  266.         end
  267.         else
  268.         begin
  269.           FileHeader2 := 'The following files in ' + ReferenceList +
  270.                          ' do not appear in ' + ExaminedList;
  271.           writeln(TempOutFile2,OddOne);
  272.         end;
  273.       end {OutMismatchToDisk};
  274.  
  275.     begin {BinarySearch}
  276.       j := StartSearchPoint;
  277.       OffSet := j;
  278.       Match := false;
  279.       NotOnList := false;
  280.       repeat
  281.         if ProgramName = RefFile[j] then
  282.         begin
  283.           Match := true;
  284.         end
  285.         else
  286.         if ProgramName < RefFile[j] then
  287.         begin
  288.           OffSet := OffSet div 2;
  289.           if OffSet = 0 then NotOnList := true
  290.           else j := j - OffSet;
  291.         end
  292.         else
  293.         if ProgramName > RefFile[j] then
  294.         begin
  295.           if j + OffSet div 2 > FirstCatSize then
  296.           begin
  297.             repeat
  298.               OffSet := OffSet div 2;
  299.             until j + OffSet div 2 <= FirstCatSize
  300.           end;
  301.         OffSet := OffSet div 2;
  302.         if OffSet = 0 then NotOnList := true
  303.         else j := j + OffSet;
  304.         end;
  305.       until Match or NotOnList;
  306.       If not Match then
  307.       begin
  308.         if ProgramName <> '' then      {string empty?  Not enough data
  309.                                         in grab to completely fill buffer.}
  310.         begin
  311.           Mismatch := true;
  312.           OddOne := ProgramName;
  313.           OutMismatchToDisk;
  314.           MismatchCounter := succ(MismatchCounter);
  315.           if FirstPass then
  316.           begin
  317.             writeln(OddOne,' doesn''t appear in ',ReferenceList)
  318.           end
  319.           else
  320.           begin
  321.             writeln(OddOne,' doesn''t appear in ',ExaminedList);
  322.           end;
  323.         end;
  324.       end;
  325.     end    { BinarySearch };
  326.  
  327.   begin  {Process File}
  328.     MismatchCounter := 0;
  329.     For i := 1 to MaxCatSize do RefFile[i] := '';  { initialize buffer }
  330.     if FirstPass then
  331.     begin
  332.       OutFileOpen := false;
  333.       Writeln(^J,'Reading ',ReferenceList,'  . . . ');
  334.     end
  335.     else Writeln(^J,'Reading ',ExaminedList,'  . . . ');
  336.     i:=1;
  337.     while not Eof(FileOne) do
  338.     begin
  339.       Readln(FileOne,LineBuffer);
  340.       if copy(LineBuffer,9,1) = '.' then
  341.       begin
  342.         if copy(lineBuffer,10,3) <> 'FRE' then
  343.         begin
  344.           RefFile[i] := copy(LineBuffer,1,12);
  345.           FirstCatSize := i;
  346.           i := succ(i);
  347.         end;
  348.       end;
  349.     end;
  350.     if i = 1 then
  351.     begin
  352.       if FirstPass then writeln(^J,ReferenceList,' is an EMPTY file.')
  353.                    else writeln(^J,ExaminedList,' is an EMPTY file.');
  354.       close(TempOutFile1); erase(TempOutFile1);
  355.       close(TempOutFile2); erase(TempOutFile2);
  356.       halt
  357.     end;
  358.     close(FileOne);
  359.  
  360.     StartSearchPoint := 2;
  361.     if StartSearchPoint < FirstCatSize then
  362.     repeat
  363.       StartSearchPoint := StartSearchPoint * 2
  364.     until StartSearchPoint >= FirstCatSize;
  365.     StartSearchPoint := StartSearchPoint div 2;
  366.  
  367.     Mismatch := false;
  368.     if FirstPass then Writeln(^J,'Reading ',ExaminedList,'  . . . ',^J)
  369.                  else Writeln(^J,'Reading ',ReferenceList,'  . . . ',^J);
  370.     begin
  371.       SecondCatSize := 0;
  372.       repeat
  373.         For i := 1 to BuffSize do CompareBuff[i] := '';  { initialize buffer }
  374.         i := 1;
  375.         CompareBuffFull := false;
  376.         repeat
  377.           readln(FileTwo,LineBuffer);
  378.           if copy(LineBuffer,9,1) = '.' then
  379.           begin
  380.             if copy(lineBuffer,10,3) <> 'FRE' then
  381.             begin
  382.               CompareBuff[i] := copy(LineBuffer,1,12);
  383.               if i >= BuffSize then CompareBuffFull := true;
  384.               i:=succ(i);
  385.               SecondCatSize := succ(SecondCatSize);
  386.             end;
  387.           end;
  388.         until CompareBuffFull or Eof(FileTwo);
  389.  
  390.         { begin comparing the big reference array against chunks
  391.                  of the other list taken from disk }
  392.  
  393.         n := 1;
  394.         while n <= BuffSize do
  395.         begin
  396.           ProgramName := CompareBuff[n];
  397.           BinarySearch;
  398.           n := succ(n);
  399.         end;
  400.       until Eof(FileTwo);
  401.     end;
  402.     close(FileTwo);
  403.     if not Mismatch then
  404.     begin
  405.       if FirstPass then
  406.       begin
  407.         Mismatch1 := false;
  408.         writeln(^J,'Everything in the ',ExaminedList,
  409.                          ' file also appears in the ',ReferenceList,' file.');
  410.       end
  411.       else
  412.       begin
  413.         Mismatch2 := false;
  414.         writeln(^J,'Everything in the ',ReferenceList,
  415.                          ' file also appears in the ',ExaminedList,' file.');
  416.       end;
  417.     end;
  418.     if FirstPass then writeln(^J,'First comparison complete')
  419.                  else writeln(^J,'Second comparison complete');
  420.     if not Mismatch1 and not Mismatch2 and not FirstPass then
  421.     begin
  422.         writeln(^J,'Files in ' + ReferenceList + ' = ',SecondCatSize);
  423.         writeln(^J,'Files in ' + ExaminedList + ' = ',FirstCatSize);
  424.     end;
  425.     if Mismatch then
  426.     begin
  427.       if FirstPass then
  428.       begin
  429.         Mismatch1 := true;
  430.         MismatchCount1 := MismatchCounter
  431.       end
  432.       else
  433.       begin
  434.         Mismatch2 := true;
  435.         MismatchCount2 := MismatchCounter;
  436.       end;
  437.       if not FirstPass then writeln(^J,'Formatting output . . .');
  438.     end;
  439.     if FirstPass then close(TempOutFile1) else close(TempOutFile2);
  440.   end {Process File};
  441.  
  442.   overlay procedure FormatOutput;
  443.   const
  444.     NumberOfColumns = 5;
  445.   type
  446.     Page = array[1..MaxNumberOfLines] of array[1..NumberOfColumns] of FileName;
  447.   var
  448.     MinColumnLength: integer;
  449.     LineBuffer: string[79];
  450.     NoMatch1,NoMatch2: Page;
  451.  
  452.     procedure ClrArray(var FileDisplay: Page; MismatchCount: integer);
  453.     var
  454.       i,j: integer;
  455.     begin
  456.       MinColumnLength := MismatchCount div NumberOfColumns;
  457.       for i := 1 to NumberOfColumns do
  458.       begin
  459.         for j := 1 to MinColumnLength + 1 do FileDisplay[j,i] := '';
  460.       end;
  461.       LineBuffer := '';
  462.     end; {ClrArray}
  463.  
  464.     procedure PrettyItUp(var FileDisplay: Page;
  465.                          var TFile: text;
  466.                              MismatchCount: integer);
  467.     var
  468.       i,j,Residue,AddOn: integer;
  469.     begin
  470.       MinColumnLength := MismatchCount div NumberOfColumns;
  471.       Residue := MismatchCount - NumberOfColumns * MinColumnLength;
  472.       for i := 1 to NumberOfColumns do
  473.       begin
  474.         AddOn := 0;
  475.         if Residue > 0 then
  476.         begin
  477.           AddOn := 1;
  478.           Residue := Residue - 1;
  479.         end;
  480.         for j := 1 to MinColumnLength + AddOn do
  481.         begin
  482.           readln(TFile,LineBuffer);
  483.           FileDisplay[j,i] := LineBuffer;
  484.         end; {j loop}
  485.       end; {i loop}
  486.       close(TFile); erase(TFile);
  487.     end; {PrettyItUp}
  488.  
  489.     procedure WriteItOut(var FileDisplay: Page; FileHeader: Header;
  490.                              NumOfMismatches: integer);
  491.     var
  492.       i,j: integer;
  493.  
  494.       procedure Summary;
  495.       var
  496.         SummaryStringA,SummaryStringB,
  497.         SummaryStringC,SummaryStringD: string[79];
  498.       begin
  499.         SummaryStringA := 'Files in ' + ReferenceList + ' = ';
  500.         SummaryStringB := 'Files in ' + ExaminedList + ' = ';
  501.         SummaryStringC := 'Files in ' + ExaminedList +
  502.           ' which are not found in ' + ReferenceList + ' = ';
  503.         SummaryStringD := 'Files in ' + ReferenceList +
  504.           ' which are not found in ' + ExaminedList + ' = ';
  505.         writeln(^J,SummaryStringA,SecondCatSize);
  506.         writeln(SummaryStringB,FirstCatSize);
  507.         if FileHeader = FileHeader1 then
  508.                          writeln(SummaryStringC,NumOfMismatches,^J)
  509.                                     else
  510.                          writeln(SummaryStringD,NumOfMismatches);
  511.         if not Hardcopy then
  512.         begin
  513.           writeln(OutFile,^J,SummaryStringA,SecondCatSize);
  514.           writeln(OutFile,SummaryStringB,FirstCatSize);
  515.           if FileHeader = FileHeader1 then
  516.                          writeln(OutFile,SummaryStringC,NumOfMismatches,^J)
  517.                                       else
  518.                          writeln(OutFile,SummaryStringD,NumOfMismatches);
  519.         end
  520.         else
  521.         begin
  522.           writeln(lst,^J,SummaryStringA,SecondCatSize);
  523.           writeln(lst,SummaryStringB,FirstCatSize);
  524.           if FileHeader = FileHeader1 then
  525.                          writeln(lst,SummaryStringC,NumOfMismatches,^J)
  526.                                       else
  527.                          writeln(lst,SummaryStringD,NumOfMismatches);
  528.         end;
  529.       end; {Summary}
  530.  
  531.     begin {WriteItOut}
  532.       writeln(^J,FileHeader,^J);
  533.       if not Hardcopy then writeln(OutFile,^J,FileHeader,^J)
  534.                       else writeln(lst,^J,FileHeader,^J);
  535.       for j := 1 to MinColumnLength +1 do
  536.       begin
  537.         write(FileDisplay[j,1]);
  538.         if not Hardcopy then write(OutFile,FileDisplay[j,1])
  539.                         else write(lst,FileDisplay[j,1]);
  540.         for i := 2 to NumberOfColumns do
  541.         begin
  542.           write(FileDisplay[j,i]:16);
  543.           if not Hardcopy then write(OutFile,FileDisplay[j,i]:16)
  544.                           else write(OutFile,FileDisplay[j,i]:16);
  545.         end;
  546.         writeln;
  547.         if not Hardcopy then writeln(OutFile)
  548.                         else writeln(lst);
  549.       end;
  550.       Summary;
  551.    end; {WriteItOut}
  552.  
  553.   begin {FormatOutput}
  554.     if not Hardcopy then
  555.     begin
  556.       if Mismatch1 or Mismatch2 then
  557.       begin
  558.         BakUp;
  559.         OpenOutputFile;
  560.       end;
  561.     end;
  562.     if Mismatch1 then
  563.     begin
  564.       ReopenTempFile(TempOutFile1,TempOut1);
  565.       ClrArray(NoMatch1,MismatchCount1);
  566.       PrettyItUp(NoMatch1,TempOutFile1,MismatchCount1);
  567.       WriteItOut(NoMatch1,FileHeader1,MismatchCount1);
  568.     end;
  569.     if Mismatch2 then
  570.     begin
  571.       ReopenTempFile(TempOutFile2,TempOut2);
  572.       ClrArray(NoMatch2,MismatchCount2);
  573.       PrettyItUp(NoMatch2,TempOutFile2,MismatchCount2);
  574.       WriteItOut(NoMatch2,FileHeader2,MismatchCount2);
  575.     end;
  576.     if not Mismatch1 then
  577.     begin
  578.       close(TempOutFile1); erase(TempOutFile1);
  579.     end;
  580.     if not Mismatch2 then
  581.     begin
  582.       close(TempOutFile2); erase(TempOutFile2);
  583.     end;
  584.     if not Hardcopy then
  585.     begin
  586.       if Mismatch1 or Mismatch2 then writeln(^J,'Output File = ',OutFileName);
  587.     end;
  588.     if OutFileOpen then close(OutFile);
  589.   end; {FormatOutput}
  590.  
  591. BEGIN {main program}
  592.   ClrScr;
  593.   OpenInputFiles;
  594.   OpenTempFiles;
  595.   ProcessFile;
  596.   ExchangeInputFiles;
  597.   ProcessFile;
  598.   FormatOutput;
  599. END.
  600.