rbthomas@athos.rutgers.edu (Rick Thomas) (09/18/89)
Here is round two of my fixes for diff to deal with changes near the end of file. I found that the changes I posted a while ago caused diff to loop forever when there were alot of changes at the exact end of the file. The problem turned out to be that the "end-of-file" signal I was using was also used to indicate "end-of-incore-images", and the two were fighting. I had to create a separate "end-of-file" signal. I have not extensively tested these changes, so please try them out and let me know what you find, good *or* bad. Thanks! The whole thing is only about 30 percent larger than the cdiff's so I am posting the whole thing. Enjoy, Rick ======================================================================== Rick Thomas, Manager Supercomputer Remote Access Center Rutgers University, College of Engineering Brett and Bowser Roads Piscataway, NJ 08855-0909 Phone: (201) 932-4301 Internet: rbthomas@jove.rutgers.edu UUCP: {any backbone site}!rutgers!jove.rutgers.edu!rbthomas Alternate UUCP: {convex|c1apple|karna}!kingtut!rbthomas There are lots of dangerous people on the streets of Manhattan... muggers, rapists, mimes... ======================================================================== $ crc diff.c 15312 6054 diff.c ====================================================================== : This is a shell archive. : Remove everything above this line and : run the following text with /bin/sh to create: : diff.c : This archive created: Sun Sep 17 22:44:30 1989 cat << 'SHAR_EOF' > diff.c /* diff - print differences between 2 files Author: Erik Baalbergen */ /* Poor man's implementation of diff(1) - no options available - may give more output than other diffs, due to the straight-forward algorithm - runs out of memory if the differing chunks become too large - input line length should not exceed LINELEN; longer lines are truncated, while only the first LINELEN characters are compared Please report bugs and suggestions to erikb@cs.vu.nl */ #include <stdio.h> FILE *fopen(); #define LINELEN 128 char *prog; int diffs = 0; main(argc, argv) char **argv; { FILE *fp1 = NULL, *fp2 = NULL; prog = *argv++; if (argc != 3) fatal("use: %s file1 file2", prog); if (strcmp(argv[0], "-") == 0) fp1 = stdin; else if (strcmp(argv[1], "-") == 0) fp2 = stdin; if (fp1 == NULL && (fp1 = fopen(argv[0], "r")) == NULL) fatal("can't read %s", argv[0]); if (fp2 == NULL && (fp2 = fopen(argv[1], "r")) == NULL) fatal("can't read %s", argv[1]); diff(fp1, fp2); exit(diffs > 0); } fatal(fmt, s) char *fmt, *s; { fprintf(stderr, "%s: ", prog); fprintf(stderr, fmt, s); fprintf(stderr, "\n"); exit(2); } /* the line module */ char *malloc(); char *fgets(); struct line { struct line *l_next; char l_text[LINELEN + 2]; char l_eof; }; struct line *freelist = 0; #define stepup(ll) ( ((ll) && ((ll)->l_eof==0)) ? (ll)->l_next : (ll) ) struct line * new_line() { register struct line *l; if (l = freelist) freelist = freelist->l_next; else if ((l = (struct line *)malloc(sizeof(struct line))) == 0) fatal("out of memory"); return l; } free_line(l) register struct line *l; { l->l_next = freelist; freelist = l; } int equal_line(l1,l2) struct line *l1, *l2; { if (l1==0||l2==0) return(0); else if (l1->l_eof || l2->l_eof) return (l1->l_eof == l2->l_eof); else return(strcmp(l1->l_text,l2->l_text)==0); } int equal_3(l1, l2) struct line *l1, *l2; { register int i,ansr; ansr = 1; #ifdef DEBUG if (l1==0) fprintf(stderr,"\t(null)\n"); else if (l1->l_eof) fprintf(stderr,"\t(eof)\n"); else fprintf(stderr,"\t%s",l1->l_text); if (l2==0) fprintf(stderr,"\t(null)\n"); else if (l2->l_eof) fprintf(stderr,"\t(eof)\n"); else fprintf(stderr,"\t%s",l2->l_text); #endif for (i=0; i < 3; ++i) { if (!equal_line(l1, l2)) { ansr=0; break; } l1 = stepup(l1); l2 = stepup(l2); } #ifdef DEBUG fprintf(stderr,"\t%d\n",ansr); #endif return (ansr); } struct line * read_line(fp) FILE *fp; { register struct line *l = new_line(); register char *p; register int c; (p = &(l->l_text[LINELEN]))[1] = '\377'; l->l_eof = 0; if (fgets(l->l_text, LINELEN + 2, fp) == NULL) { l->l_eof = 1; l->l_text[0] = 0; } else if ((p[1] & 0377) != 0377 && *p != '\n') { while ((c = fgetc(fp)) != '\n' && c != EOF) {} *p++ = '\n'; *p = '\0'; } l->l_next = 0; return l; } /* file window handler */ struct f { struct line *f_bwin, *f_ewin; struct line *f_aside; int f_linecnt; /* line number in file of last advanced line */ FILE *f_fp; }; advance(f) register struct f *f; { register struct line *l; if (l = f->f_bwin) { if (f->f_ewin == l) f->f_bwin = f->f_ewin = 0; else f->f_bwin = l->l_next; free_line(l); (f->f_linecnt)++; } } aside(f, l) struct f *f; struct line *l; { register struct line *ll; if (l == 0) return; if (ll = l->l_next) { while (ll->l_next) ll = ll->l_next; ll->l_next = f->f_aside; f->f_aside = l->l_next; l->l_next = 0; f->f_ewin = l; } } struct line * next(f) register struct f *f; { register struct line *l; if (l = f->f_aside) { f->f_aside = l->l_next; l->l_next = 0; } else l = read_line(f->f_fp); if (l) { if (f->f_bwin == 0) f->f_bwin = f->f_ewin = l; else { if (f->f_ewin->l_eof && l->l_eof) { free_line(l); return (f->f_ewin); } f->f_ewin->l_next = l; f->f_ewin = l; } } return l; } init_f(f, fp) register struct f *f; FILE *fp; { f->f_bwin = f->f_ewin = f->f_aside = 0; f->f_linecnt = 0; f->f_fp = fp; } update(f, s) register struct f *f; char *s; { while (f->f_bwin && f->f_bwin != f->f_ewin) { printf("%s%s", s, f->f_bwin->l_text); advance(f); } } /* diff procedure */ diff(fp1, fp2) FILE *fp1, *fp2; { struct f f1, f2; struct line *l1, *s1, *b1, *l2, *s2, *b2; register struct line *ll; init_f(&f1, fp1); init_f(&f2, fp2); l1 = next(&f1); l2 = next(&f2); while ((l1->l_eof==0) || (l2->l_eof==0)) { if (equal_line(l1, l2)) { equal: advance(&f1); advance(&f2); l1 = next(&f1); l2 = next(&f2); continue; } s1 = b1 = l1; s2 = b2 = l2; /* read several more lines */ next(&f1); next(&f1); next(&f2); next(&f2); /* start searching */ search: next(&f2); ll = s1; do { if (equal_3(ll, b2)) { l1 = ll; l2 = b2; aside(&f1, ll); aside(&f2, b2); differ(&f1, &f2); goto equal; } if (ll->l_eof) break; ll = stepup(ll); } while (ll); b2 = stepup(b2); next(&f1); ll = s2; do { if (equal_3(b1, ll)) { l1 = b1; l2 = ll; aside(&f2, ll); aside(&f1, b1); differ(&f1, &f2); goto equal; } if (ll->l_eof) break; ll = stepup(ll); } while (ll); b1 = stepup(b1); goto search; } /* both of the files reached EOF */ } differ(f1, f2) register struct f *f1, *f2; { int cnt1 = f1->f_linecnt, len1 = wlen(f1), cnt2 = f2->f_linecnt, len2 = wlen(f2); if ((len1 = wlen(f1)) || (len2 = wlen(f2))) { if (len1 == 0) { printf("%da", cnt1); range(cnt2 + 1, cnt2 + len2); } else if (len2 == 0) { range(cnt1 + 1, cnt1 + len1); printf("d%d", cnt2); } else { range(cnt1 + 1, cnt1 + len1); putchar('c'); range(cnt2 + 1, cnt2 + len2); } putchar('\n'); if (len1) update(f1, "< "); if (len1 && len2) printf("---\n"); if (len2) update(f2, "> "); diffs++; } } wlen(f) struct f *f; { register cnt = 0; register struct line *l = f->f_bwin, *e = f->f_ewin; while (l && l != e) { cnt++; l = l->l_next; } return cnt; } range(a, b) { printf(((a == b) ? "%d" : "%d,%d"), a, b); } SHAR_EOF : End of shell archive exit 0 -- Rick Thomas uucp: {ames, att, harvard}!rutgers!jove.rutgers.edu!rbthomas internet: rbthomas@JOVE.RUTGERS.EDU bitnet: rbthomas@zodiac.bitnet Phone: (201) 932-4301