/* * Displays differences between two ASCII files * * Options: * -d = Inhibit display of differences * -l = Inhibit display of line numbers * r=num = Minimum # lines to re-syncronize * * Copyright 1988-1995 Dave Dunfield * All rights reserved. * * Permission granted for personal (non-commercial) use only. * * Compile command: cc diff -fop */ #include #define LINE_SIZE 100 /* maximum size of input lines */ #define MAX_DIFF 200 /* maximum number of different lines */ char ft1[MAX_DIFF][LINE_SIZE], ft2[MAX_DIFF][LINE_SIZE]; unsigned r1 = 0, r2 = 0, w1 = 0, w2 = 0, l1, l2; unsigned resync = 2, diffs = 0; char diff = -1, line = -1; char *fn1, *fn2; FILE *fp1, *fp2; /* * Main program, compare files */ main(argc, argv) int argc; char *argv[]; { char *ptr; l2 = 0; for(l1 = 1; l1 < argc; ++l1) { ptr = argv[l1]; switch((tolower(*ptr++) << 8) | tolower(*ptr++)) { case 'r=' : /* minimum # lines to resync */ resync = get_num(ptr); break; case '-d' : /* inhibit display of differences */ diff = 0; break; case '-l' : /* inhibit display of line numbers */ line = 0; break; default: /* filename to compare */ if(!(fp2 = fopen(fn2 = argv[l1], "r"))) { fprintf(stderr, "%s: Unable to open\n", fn2); exit(-1); } if(!l2++) { fn1 = fn2; fp1 = fp2; } } } if(l2 != 2) { fputs("\nUse: diff [-d -l r=#lines]\n\nCopyright 1988-1995 Dave Dunfield\nAll rights reserved.\n", stderr); exit(-1); } l1 = l2 = 1; for(;;) { fill_buffer(); if((r1 == w1) || (r2 == w2)) { show_changed(w1, w2); if(diffs) fprintf(stdout,"%u differences.\n", diffs); else fprintf(stdout,"Files match exactly.\n"); exit(diffs); } if(equal(ft1[r1], ft2[r2])) { r1 = (r1 + 1) % MAX_DIFF; r2 = (r2 + 1) % MAX_DIFF; ++l1; ++l2; continue; } scan_buffer(); } } /* * Fill up the buffer with lines from the input file */ fill_buffer() { register int j1, j2; while((j1 = (w1 + 1) % MAX_DIFF) != r1) { if(!fgets(ft1[w1], LINE_SIZE, fp1)) break; w1 = j1; } while((j2 = (w2 + 1) % MAX_DIFF) != r2) { if(!fgets(ft2[w2], LINE_SIZE, fp2)) break; w2 = j2; } } /* * Scan the buffer looking for a pattern */ scan_buffer() { int i, i1, i2, j1, j2; char flag; i1 = r1; i2 = r2; fill_buffer(); do { /* scan with this portion */ j1 = i1; j2 = i2; do { flag = 0; if(j2 != w2) { /* we can check this one */ flag = -1; if(equal(ft1[i1], ft2[j2]) && (i=test_next(i1, j2))) { show_changed(i1, j2); r1 = (r1 + i) % MAX_DIFF; r2 = (r2 + i) % MAX_DIFF; l1 += i; l2 += i; return; } j2 = (j2 + 1) % MAX_DIFF; } if(j1 != w1) { /* we can check this one */ flag = -1; if(equal(ft1[j1], ft2[i2]) && (i=test_next(j1, i2))) { show_changed(j1, i2); r1 = (r1 + i) % MAX_DIFF; r2 = (r2 + i) % MAX_DIFF; l1 += i; l2 += i; return; } j1 = (j1 + 1) % MAX_DIFF; } } while(flag); if(i1 != w1) { /* More lines in buffer */ i1 = (i1 + 1) % MAX_DIFF; flag = -1; } if(i2 != w2) { /* More lines in buffer */ i2 = (i2 + 1) % MAX_DIFF; flag = -1; } } while(flag); /* Cannot accept any more data into buffers, check for overflow */ if((((w1 + 1) % MAX_DIFF) == r1) || (((w2 + 1) % MAX_DIFF) == r2)) { fprintf(stdout,"Differences to great at %u < > %u\n", l1, l2); exit(-1); } /* Buffers not full, must be end of file */ show_changed(w1, w2); } /* * Test that the next "resync" entries match */ test_next(i1, i2) unsigned i1, i2; { int i; for(i=1; i < resync; ++i) { i1 = (i1 + 1) % MAX_DIFF; i2 = (i2 + 1) % MAX_DIFF; if((i1 == w1) || (i2 == w2)) return i; if(!equal(ft1[i1], ft2[i2])) return 0; } return i; } /* * Display the changed lines & reset read pointers */ show_changed(i1, i2) unsigned i1, i2; { if((r1 != i1) || (r2 != i2)) { ++diffs; if(line) fprintf(stdout,"*** %s(%u) < > %s(%u) ***\n", fn1, l1, fn2, l2); while(r1 != i1) { ++l1; if(diff) fprintf(stdout,"<%s\n", ft1[r1]); r1 = (r1 + 1) % MAX_DIFF; } while(r2 != i2) { ++l2; if(diff) fprintf(stdout,">%s\n", ft2[r2]); r2 = (r2 + 1) % MAX_DIFF; } } } /* * Get a decimal number from the command line */ get_num(string) char *string; { register unsigned value; register char chr; value = 0; while(isdigit(chr = *string++)) value = (value * 10) + (chr - '0'); if(chr) { fputs("DIFF: Invalid number\n", stderr); exit(-1); } return value; } /* * Test for two strings equal */ equal(str1, str2) char *str1, *str2; { register char c; while((c = *str1++) == *str2++) { if(!c) return 1; } return 0; }