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!morearty
allbery@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)