morearty@cory.Berkeley.EDU.UUCP (06/04/87)
There is a bug in the (very useful) 'diffc' program recently posted.
(Someone mentioned the bug in a recent posting.) This article
contains the fix for it. Also, I have changed the 'diff' program
so that it looks for THREE matching lines instead of one, which
greatly improves its ability to produce a minimal listing of
differences between files.
==================
Following is a hand-done 'diff' on the 'diffc.c' program. I didn't
save the original and don't feel like looking it up; but if I
remember right, this is the only important change.
*** old diffc.c, in main() ***
newbeg = max(newmin - context, 1);
newend = newmax + context;
! if (preoldend < newbeg - 1) {
if (preoldend >= 0) {
dumphunk();
}
--- new diffc.c ---
newbeg = max(newmin - context, 1);
newend = newmax + context;
! if (preoldend < oldbeg) {
if (preoldend >= 0) {
dumphunk();
}
==================
And now, the changes for 'diff.c'. I made extensive changes to this
program for my own use, so the same warning applies -- I hope I
haven't left out any of the important changes. Let me know if I did.
You can stick the equal_3() routine anywhere in the program; right
below equal_line() would probably be the best place. And I have
only included below my version of diff(), not the original one, but
I have marked the changed lines.
Note that my changes produce slightly undesirable results in one
case -- if there is a difference right at the end of the files. For
example, if file 'a' reads
hello
and file 'b' reads
hi there
hello
then instead of producing
1a1
> hi there
(or something like that) it produces
1c1,2
< hello
---
> hi there
> hello
So who cares; it's still accurate.
+ /* equal_3: return whether THREE pairs of lines are equal */
+
+ int equal_3(struct line *l1, struct line *l2)
+ {
+ register int i;
+
+ for (i=0; i<3 && l1 && l2; ++i, l1=l1->l_next, l2=l2->l_next) {
+ if (!equal_line(l1, l2))
+ return 0;
+ }
+ return (i==3);
+ }
*********************
/* diff procedure */
void diff(FILE *fp1, FILE *fp2)
{
struct f f1, f2;
! struct line *l1, *s1, *b1, *l2, *s2, *b2;
register struct line *ll;
/* initialize windows to empty */
init_f(&f1, fp1);
init_f(&f2, fp2);
/* read first line of each file */
l1 = next(&f1);
l2 = next(&f2);
while (l1 && l2) {
if (equal_line(l1, l2)) { /* lines are equal */
equal:
advance(&f1); /* remove lines from windows */
advance(&f2);
l1 = next(&f1); /* read next lines */
l2 = next(&f2);
continue;
}
! s1 = b1 = l1;
! s2 = b2 = l2;
+ /* read several more lines, so we have 3 from each file */
+ next(&f1); next(&f1);
+ next(&f2); next(&f2);
/* start searching */
search:
/* read line from file2. If EOF, exit loop */
if ((l2 = next(&f2)) == 0)
continue;
ll = s1;
+ b2 = b2->l_next;
do {
! if (equal_3(ll, b2)) {
aside(&f1, ll);
+ aside(&f2, b2);
differ(&f1, &f2);
goto equal;
}
} while (ll = ll->l_next);
/* read line from file1. If EOF, exit loop */
if ((l1 = next(&f1)) == 0)
continue;
ll = s2;
+ b1 = b1->l_next;
do {
! if (equal_3(ll, b1)) {
aside(&f2, ll);
+ aside(&f1, b1);
differ(&f1, &f2);
goto equal;
}
} while (ll = ll->l_next);
goto search;
}
/* one of the files reached EOF */
if (l1) /* eof on 2 */
while (next(&f1)) {}
if (l2)
while (next(&f2)) {}
f1.f_ewin = 0;
f2.f_ewin = 0;
differ(&f1, &f2);
}
--
Mike Morearty
ARPA: morearty@cory.Berkeley.EDU USENET: ucbvax!cory!moreartyallbery@ncoast.UUCP (Brandon Allbery) (06/10/87)
I have the original "diffc" for UNIX available somewhere or other. It works
fine -- been using it for a few years now -- but is very pre-"new context
diffs", so someone may want to update it. If there's interest, I think I can
drop in into comp.os.minix. (Or you can get it from someone archiving the
mod.sources/comp.sources.unix newsgroup.)
++Brandon
--
Copyright (C) 1987 Brandon S. Allbery. Redistribution permitted only if the
redistributor permits further redistribution.
---- Moderator for comp.sources.misc ----
Brandon S. Allbery {decvax,cbosgd}!cwruecmp!ncoast!allbery
aXcess Company {ames,mit-eddie,talcott}!necntc!ncoast!allbery
6615 Center St. #A1-105 necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060-4101 +01 216 974 9210 (also eddie.MIT.EDU)