home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol019 / compare.bbb < prev    next >
Text File  |  1984-04-29  |  11KB  |  376 lines

  1.  
  2. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  3. :
  4. :    I got this program from a UCSD PASCAL USERS GROUP and as
  5. :  such it will not run immediately.  Why is it here?  I included
  6. :  it to give you folks out there practice in converting from UCSD
  7. :  to Pascal/Z.  Once you have done it (and it runs) it would be
  8. :  nice to give it to our users group.  We help you, you help us.
  9. :  I'll be including a UCSD on each volume so we can get the group
  10. :  to help updating various programs that are around and are public
  11. :  domain.
  12. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  13. {Program to compare two sourcecode files and output the differences,
  14.  if any.  Useful to compare two similar textfiles to find out whether and 
  15.  where they have been changed.  Part of original UCSD I.4 release--author
  16.  is unknown.}
  17.  
  18.  PROGRAM SRCCOM;  (* SOURCE COMPARE *)
  19.  
  20.  
  21. CONST
  22.   VERSION = 'v202 27-Oct-77';
  23.   MINLINESFORMATCH = 6;
  24.   MAXTRY = 150;  (*<<<10/27/77 GLH. LIMIT ON SEARCH AHEAD FOR MATCH*)
  25.   LINELENGTH = 90;
  26.  
  27.  
  28.  TYPE
  29.  
  30.   LINEPOINTER = ^LINE;
  31.   LINE =
  32.    RECORD  (*<<<10/26/77 GLH*)
  33.     NEXTLINE : LINEPOINTER;
  34.     IMAGE : STRING[LINELENGTH]
  35.    END;
  36.  
  37.   STREAM =
  38.    RECORD
  39.     CURSOR, HEAD, TAIL : LINEPOINTER;
  40.     CURSORLINENO, HEADLINENO, TAILLINENO : INTEGER;
  41.     ENDFILE : BOOLEAN
  42.    END;
  43.  
  44.  
  45.  VAR
  46.  
  47.   TITLEA, TITLEB : STRING;  (*<<<10/27/77 GLH*)
  48.   FILEA, FILEB : TEXT;
  49.   A, B : STREAM;
  50.   MATCH : BOOLEAN;
  51.   ENDFILE : BOOLEAN;
  52.  
  53.   TEMPLINE : STRING[LINELENGTH];  (*<<<10/26/77 GLH*)
  54.  
  55.   FREELINES : LINEPOINTER;
  56.  
  57.  
  58.  
  59.   SAME : BOOLEAN;
  60.  
  61.  
  62.  
  63.  PROCEDURE COMPARE;
  64.  
  65.  
  66.                                           FUNCTION ENDSTREAM(VAR X : STREAM) : BOOLEAN;
  67.   BEGIN (* ENDSTREAM *)
  68.    ENDSTREAM := (X.CURSOR = NIL) AND X.ENDFILE
  69.   END;  (* ENDSTREAM *)
  70.  
  71.  
  72.   PROCEDURE MARK(VAR X : STREAM);
  73.  
  74.    (* CAUSES BEGINNING OF STREAM TO BE POSITIONED BEFORE *)
  75.    (* CURRENT STREAM CURSOR.  BUFFERS GET RECLAIMED, LINE *)
  76.    (* COUNTERS RESET, ETC. *)
  77.  
  78.    PROCEDURE COLLECT(FWA, LWAPLUS1 : LINEPOINTER);
  79.     VAR P : LINEPOINTER;
  80.    BEGIN (* COLLECT *)
  81.     WHILE FWA <> LWAPLUS1 DO
  82.      BEGIN P := FWA^.NEXTLINE;
  83.       FWA^.NEXTLINE := FREELINES;  FREELINES := FWA;
  84.       FWA := P
  85.      END
  86.    END;  (* COLLECT *)
  87.  
  88.  
  89.   BEGIN (* MARK *)
  90.    IF X.HEAD <> NIL THEN
  91.     BEGIN
  92.      COLLECT(X.HEAD, X.CURSOR);
  93.      X.HEAD := X.CURSOR;  X.HEADLINENO := X.CURSORLINENO;
  94.      IF X.CURSOR = NIL THEN
  95.       BEGIN  X.TAIL := NIL;  X.TAILLINENO := X.CURSORLINENO  END
  96.     END
  97.   END;  (* MARK *)
  98.  
  99.  
  100.   PROCEDURE MOVECURSOR(VAR X : STREAM;  VAR FILEX : TEXT);
  101.  
  102.    (* FILEX IS THE INPUT FILE ASSOCIATED WITH STREAM X.  THE *)
  103.                                             (* CURSOR FOR X IS MOVED FORWARD ONE LINE, READING FROM X *)
  104.    (* IF NECESSARY, AND INCREMENTING THE LINE COUNT.  ENDFILE *)
  105.    (* IS SET IF EOF ENCOUNTERED ON EITHER STREAM. *)
  106.  
  107.    PROCEDURE READLINE;
  108.     VAR
  109.      I : INTEGER;
  110.      CH : CHAR;
  111.      NEWLINE : LINEPOINTER;
  112.      C, C2 : 0..LINELENGTH;
  113.    BEGIN (* READLINE *)
  114.     IF NOT X.ENDFILE THEN
  115.      BEGIN
  116.       C := 0;
  117.       (*<<<10/26/77 GLH. CHANGED WAY CHARS GET INTO TEMPLINE*)
  118.       READ(FILEX, TEMPLINE);
  119.       NEWLINE := FREELINES;
  120.       IF NEWLINE = NIL THEN NEW(NEWLINE)
  121.       ELSE  FREELINES := FREELINES^.NEXTLINE;
  122.       NEWLINE^.IMAGE := TEMPLINE;  (*<<<10/26/77 GLH*)
  123.       NEWLINE^.NEXTLINE := NIL;
  124.       IF X.TAIL = NIL THEN
  125.        BEGIN  X.HEAD := NEWLINE;
  126.         X.TAILLINENO := 1;  X.HEADLINENO := 1
  127.        END
  128.       ELSE
  129.        BEGIN X.TAIL^.NEXTLINE := NEWLINE;
  130.         X.TAILLINENO := X.TAILLINENO + 1
  131.        END;
  132.       X.TAIL := NEWLINE;
  133.       X.ENDFILE := EOF(FILEX);
  134.      END
  135.    END;  (* READLINE *)
  136.  
  137.  
  138.   BEGIN (* MOVECURSOR *)
  139.                IF X.CURSOR <> NIL THEN
  140.     BEGIN
  141.      IF X.CURSOR = X.TAIL THEN READLINE;
  142.      X.CURSOR := X.CURSOR^.NEXTLINE;
  143.      IF X.CURSOR = NIL THEN ENDFILE := TRUE;
  144.      X.CURSORLINENO := X.CURSORLINENO + 1
  145.     END
  146.    ELSE
  147.     IF NOT X.ENDFILE THEN (* BEGINNING OF STREAM *)
  148.      BEGIN
  149.       READLINE; X.CURSOR := X.HEAD;
  150.       X.CURSORLINENO := X.HEADLINENO
  151.      END
  152.     ELSE  (* END OF STREAM *)
  153.      ENDFILE := TRUE;
  154.   END;  (* MOVECURSOR *)
  155.  
  156.  
  157.   PROCEDURE BACKTRACK(VAR X : STREAM;  VAR XLINES : INTEGER);
  158.  
  159.    (* CAUSES THE CURRENT POSITION OF STREAM  THE NEW CURRENT *)
  160.    (* THE LINE COUNTER IS RETURNED IN XLINES.  IT IS THE NUMBER *)
  161.    (* OF THE CURRENT LINE (BEFORE BACKTRACK) RELATIVE TO BEGINNING *)
  162.    (* OF STREAM. *)
  163.  
  164.   BEGIN (* BACKTRACK *)
  165.    XLINES := X.CURSORLINENO + 1 - X.HEADLINENO;
  166.    X.CURSOR := X.HEAD;  X.CURSORLINENO := X.HEADLINENO;
  167.    ENDFILE := ENDSTREAM(A) OR ENDSTREAM(B)
  168.   END;  (* BACKTRACK *)
  169.  
  170.  
  171.   PROCEDURE COMPARELINES(VAR MATCH : BOOLEAN);
  172.  
  173.                                                        (* COMPARE THE CURRENT LINES OF STREAMS A AND B, RETURNING *)
  174.    (* MATCH TO SIGNAL THEIR (NON-) EQUIVALENCE.  EOF ON BOTH STREAMS *)
  175.    (* IS CONSIDERED A MATCH, BUT EOF ON ONLY ONE STREAM IS A MISMATCH *)
  176.  
  177.   BEGIN (* COMPARELINES *)
  178.    IF (A.CURSOR = NIL) OR (B.CURSOR = NIL) THEN
  179.     MATCH := ENDSTREAM(A) AND ENDSTREAM(B)
  180.    ELSE
  181.       MATCH := (A.CURSOR^.IMAGE = B.CURSOR^.IMAGE)
  182.   END;  (* COMPARELINES *)
  183.  
  184.  
  185.   PROCEDURE FINDMISMATCH;
  186.  
  187.  
  188.   BEGIN (* FINDMISMATCH *)
  189.    (* NOT ENDFILE AND MATCH *)
  190.    REPEAT  (* COMPARENEXTLINES *)
  191.     MOVECURSOR(A, FILEA); MOVECURSOR(B,FILEB);
  192.     MARK(A); MARK(B);
  193.     COMPARELINES(MATCH)
  194.    UNTIL ENDFILE OR NOT MATCH;
  195.   END;  (* FINDMISMATCH *)
  196.  
  197.  
  198.   PROCEDURE FINDMATCH;
  199.  
  200.    VAR
  201.       TRYCOUNT : INTEGER;
  202.  
  203.  
  204.    PROCEDURE SEARCH(VAR X : STREAM; (* STREAM TO SEARCH *)
  205.                     VAR FILEX : TEXT;
  206.                     VAR Y : STREAM; (* STREAM TO LOOKAHEAD *)
  207.                     VAR FILEY : TEXT);
  208.  
  209.     (* LOOK AHEAD ONE LINE ON STREAM Y, AND SEARCH FOR THAT LINE *)
  210.             (* BACKTRACKING ON STREAM X. *)
  211.  
  212.     VAR
  213.      COUNT : INTEGER;  (* NUMBER OF LINES BACKTRACKED ON X *)
  214.  
  215.  
  216.     PROCEDURE CHECKFULLMATCH;
  217.      (* FROM THE CURRENT POSITIONS IN X AND Y, WHICH MATCH, *)
  218.      (* MAKE SURE THAT THE NEXT MINLINESFORMATCH-1 LINES ALSO *)
  219.      (* MATCH, OR ELSE SET MATCH := FALSE.  *)
  220.      VAR
  221.       N : INTEGER;
  222.       SAVEXCUR, SAVEYCUR : LINEPOINTER;
  223.       SAVEXLINE, SAVEYLINE : INTEGER;
  224.     BEGIN (* CHECKFULLMATCH *)
  225.      SAVEXCUR := X.CURSOR;  SAVEYCUR := Y.CURSOR;
  226.      SAVEXLINE := X.CURSORLINENO;  SAVEYLINE := Y.CURSORLINENO;
  227.      COMPARELINES(MATCH);
  228.      N := MINLINESFORMATCH - 1;
  229.      WHILE MATCH AND (N <> 0) DO
  230.       BEGIN  MOVECURSOR(X, FILEX);  MOVECURSOR(Y, FILEY);
  231.        COMPARELINES(MATCH);  N := N - 1
  232.       END;
  233.      X.CURSOR := SAVEXCUR;  X.CURSORLINENO := SAVEXLINE;
  234.      Y.CURSOR := SAVEYCUR;  Y.CURSORLINENO := SAVEYLINE;
  235.     END;  (* CHECKFULLMATCH *)
  236.  
  237.  
  238.    BEGIN (* SEARCH *)
  239.     MOVECURSOR(Y, FILEY);  BACKTRACK(X, COUNT);
  240.     CHECKFULLMATCH;  COUNT := COUNT - 1;
  241.      WHILE (COUNT <> 0) AND NOT MATCH DO
  242.      BEGIN
  243.       MOVECURSOR(X, FILEX);  COUNT := COUNT - 1;
  244.       CHECKFULLMATCH
  245.      END
  246.    END;  (* SEARCH *)
  247.  
  248.  
  249.    PROCEDURE PRINTMISMATCH;
  250.     VAR
  251.      EMPTYA, EMPTYB : BOOLEAN;
  252.  
  253.     PROCEDURE WRITETEXT(P, Q : LINEPOINTER);
  254.     BEGIN (* WRITETEXT *)
  255.      WRITELN;
  256.      WHILE (P <> NIL) AND (P <> Q) DO
  257.       BEGIN  WRITE(' * ');
  258.         WRITELN (P^.IMAGE);
  259.        P := P^.NEXTLINE
  260.       END;
  261.      IF P = NIL THEN WRITELN(' *** EOF ***');
  262.      WRITELN
  263.     END;  (* WRITETEXT *)
  264.  
  265.  
  266.     PROCEDURE WRITELINENO(VAR X : STREAM);
  267.      VAR
  268.       F, L : INTEGER;
  269.     BEGIN (* WRITELINENO *)
  270.      F := X.HEADLINENO;  L := X.CURSORLINENO - 1;
  271.      WRITE('LINE');
  272.      IF F = L THEN WRITE(' ', F)
  273.      ELSE WRITE('S ', F, ' TO ', L);
  274.      IF X.CURSOR = NIL THEN WRITE(' (BEFORE EOF)');
  275.     END;  (* WRITELINENO *)
  276.  
  277.  
  278.     PROCEDURE PRINTEXTRATEXT(VAR X : STREAM; XNAME : STRING;
  279.                              VAR Y : STREAM; YNAME : STRING);
  280.     BEGIN (* PRINTEXTRATEXT *)
  281.                              WRITE(' EXTRA TEXT ON ', XNAME, ', ');
  282.      WRITELINENO(X);  WRITELN;
  283.      IF Y.HEAD = NIL THEN
  284.       WRITELN(' BEFORE EOF ON ', YNAME)
  285.      ELSE
  286.       WRITELN(' BETWEEN LINES ', Y.HEADLINENO-1, ' AND ',
  287.               Y.HEADLINENO, ' OF ', YNAME);
  288.      WRITETEXT(X.HEAD, X.CURSOR)
  289.     END;  (* PRINTEXTRATEXT *)
  290.  
  291.  
  292.  
  293.    BEGIN (* PRINTMISMATCH *)
  294.     WRITELN(' ***********************************');
  295.     EMPTYA := (A.HEAD = A.CURSOR);
  296.     EMPTYB := (B.HEAD = B.CURSOR);
  297.     IF EMPTYA OR EMPTYB THEN
  298.      IF EMPTYA THEN PRINTEXTRATEXT(B, TITLEB, A, TITLEA)
  299.      ELSE PRINTEXTRATEXT(A, TITLEA, B, TITLEB)
  300.     ELSE
  301.      BEGIN
  302.       WRITELN(' MISMATCH:');  WRITELN;
  303.       WRITE(' ', TITLEA, ', ');  WRITELINENO(A);  WRITELN(':');
  304.       WRITETEXT(A.HEAD, A.CURSOR);
  305.       WRITE(' ', TITLEB, ', ');  WRITELINENO(B);  WRITELN(':');
  306.       WRITETEXT(B.HEAD, B.CURSOR)
  307.      END
  308.    END;  (* PRINTMISMATCH *)
  309.  
  310.  
  311.   BEGIN (* FINDMATCH *)
  312.         TRYCOUNT := 0;
  313.         WHILE (NOT MATCH) AND (TRYCOUNT <= MAXTRY) DO
  314.           BEGIN
  315.                   SEARCH(A, FILEA, B, FILEB);
  316.             TRYCOUNT := TRYCOUNT+1;
  317.           END;
  318.         IF NOT MATCH THEN
  319.           BEGIN
  320.             TRYCOUNT:=0;
  321.             WHILE (NOT MATCH) AND (TRYCOUNT<=MAXTRY) DO
  322.                 BEGIN
  323.                   SEARCH(B, FILEB, A, FILEA);
  324.                   TRYCOUNT:=TRYCOUNT+1;
  325.                 END;
  326.           END;
  327.         PRINTMISMATCH;
  328.         IF (NOT MATCH) AND (TRYCOUNT>MAXTRY) THEN
  329.           BEGIN  MARK(A); MARK(B) END;
  330.   END;  (* FINDMATCH *)
  331.  
  332.  
  333.  
  334.  
  335.  BEGIN (* COMPARE *)
  336.   ENDFILE := FALSE;  MATCH := TRUE;  (* I.E., BOI MATCHES BOI *)
  337.   REPEAT
  338.    IF MATCH THEN FINDMISMATCH ELSE BEGIN SAME := FALSE; FINDMATCH END
  339.   UNTIL ENDFILE AND MATCH;
  340.   MARK(A);  MARK(B);  (* MARK END OF FILES, THEREBY DISPOSING BUFFERS *)
  341.  END;  (* COMPARE *)
  342.  
  343.  
  344.  PROCEDURE INITSTREAM(VAR X : STREAM; VAR FILEX : TEXT);
  345.  BEGIN (* INITSTREAM *)
  346.   X.CURSOR := NIL;  X.HEAD := NIL;  X.TAIL := NIL;
  347.   X.CURSORLINENO := 0;  X.HEADLINENO := 0;  X.TAILLINENO := 0;
  348.   X.ENDFILE := EOF(FILEX);
  349.                  END;  (* INITSTREAM *)
  350.  
  351.  
  352. BEGIN (* SRCCOM *)
  353.  WRITELN('INPUT FILE NAME:'); READLN(TITLEA);
  354.  OPENOLD(FILEA, TITLEA);
  355.  WRITELN('SECOND INPUT FILE NAME:'); READLN(TITLEB);
  356.  OPENOLD(FILEB, TITLEB);
  357.  RESET(FILEA);  RESET(FILEB);
  358.  INITSTREAM(A, FILEA);  INITSTREAM(B, FILEB);
  359.  FREELINES := NIL;
  360.  WRITELN('Source Compare [', VERSION, ']' );
  361.  WRITELN;
  362.  IF EOF(FILEA) THEN
  363.   BEGIN WRITELN(TITLEA, ' IS EMPTY.');
  364.    IF EOF(FILEB) THEN WRITELN(TITLEB, ' IS EMPTY.')
  365.   END
  366.  ELSE
  367.   IF EOF(FILEB) THEN WRITELN(TITLEB, ' IS EMPTY.')
  368.   ELSE
  369.    BEGIN  SAME := TRUE;
  370.     COMPARE;
  371.     IF SAME THEN WRITELN('No differences encountered.');
  372.    END
  373. END.  (* SRCCOM *)
  374.  
  375. 
  376.