home *** CD-ROM | disk | FTP | other *** search
- /* fcomp.c: file comparator that beats DIFF! */
-
- #include <stdio.h>
-
- #define MAXLINES 1000
- #define ORIGIN MAXLINES
- #define INSERT 1
- #define DELETE 2
-
- struct edit {
- struct edit *link;
- int op;
- int line1;
- int line2;
- };
-
- char *A[MAXLINES], *B[MAXLINES];
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int max_d,
- m,
- n,
- lower,
- upper,
- d,
- k,
- row,
- col;
-
- int last_d[2*MAXLINES+1];
- struct edit *script[2*MAXLINES+1];
-
- struct edit *new;
- char *malloc();
-
- if (argc > 1 && argv[1][0] == '-')
- {
- max_d = atoi(&argv[1][1]);
- ++argv;
- --argc;
- }
- else
- max_d = 2*MAXLINES;
-
- if(argc != 3)
- fatal("diff requires two file names.");
-
- m = in_file(argv[1],A);
- n = in_file(argv[2],B);
-
- for (row=0 ; row<m && row < n && strcmp(A[row],B[row]) == 0 ; ++row)
- ;
- last_d[ORIGIN] = row;
- script[ORIGIN] = NULL;
- lower = (row == m) ? ORIGIN + 1 : ORIGIN - 1;
- upper = (row == n) ? ORIGIN - 1 : ORIGIN + 1;
- if (lower > upper)
- {
- puts("The files are identical.");
- exit();
- }
-
- for (d = 1 ; d <= max_d ; ++d)
- {
- for ( k = lower ; k <= upper ; k +=2)
- {
- new = (struct edit *) malloc(sizeof(struct edit));
- if (new == NULL)
- exceed(d);
-
- if (k == ORIGIN-d || k != ORIGIN+d && last_d[k+1] >= last_d[k-1])
- {
- row = last_d[k+1]+1;
- new->link = script[k+1];
- new->op = DELETE;
- }
- else
- {
- row = last_d[k-1];
- new->link = script[k-1];
- new->op = INSERT;
- }
- new->line1 = row;
- new->line2 = col = row + k - ORIGIN;
- script[k] = new;
-
- while(row < m && col < n && strcmp(A[row],B[col]) == 0)
- {
- ++row;
- ++col;
- }
- last_d[k] = row;
-
- if (row == m && col == n)
- {
- put_scr(script[k]);
- exit();
- }
- if (row == m)
- lower = k+2;
-
- if (col == n)
- upper = k-2;
- }
- --lower;
- ++upper;
- }
- exceed(d);
- }
-
- in_file(filename,P)
- char *filename, *P[];
- {
- char buf[100], *malloc(), *fgets(), *save, *b;
- FILE *fp, *fopen();
- int lines = 0;
-
- if ((fp = fopen(filename,"r")) == NULL)
- {
- fprintf(stderr, "Cannot open file %s.\n",filename);
- exit();
- }
-
- while(fgets(buf,100,fp) != NULL)
- {
- if (lines >= MAXLINES)
- fatal("File is to large for diff.");
- if ((save = malloc(strlen(buf)+1)) == NULL)
- fatal("Not enough room to save the files.");
- P[lines++] = save;
- for (b = buf ; *save++ = *b++ ; )
- ;
- }
- fclose(fp);
- return(lines);
- }
-
- put_scr(start)
- struct edit *start;
- {
- struct edit *ep, *behind, *ahead, *a, *b;
- int change;
-
- ahead = start;
- ep = NULL;
- while (ahead != NULL)
- {
- behind = ep;
- ep = ahead;
- ahead = ahead->link;
- ep->link = behind;
- }
-
- while( ep != NULL)
- {
- b = ep;
- if (ep->op == INSERT)
- printf("Inserted after line %d:\n",ep->line1);
- else
- {
- do
- {
- a = b;
- b = b->link;
- } while (b!=NULL && b->op == DELETE && b->line1 == a->line1+1);
-
- change = (b!=NULL && b->op == INSERT && b->line1 == a->line1);
- if (change)
- printf("\nChanged ");
- else
- printf("\nDeleted ");
- if (a == ep)
- printf("line %d\n",ep->line1);
- else
- printf("lines %d-%d:\n",ep->line1,a->line1);
-
- do
- {
- printf(" %s",A[ep->line1-1]);
- ep = ep->link;
- } while (ep != b);
-
- if (!change)
- continue;
- printf("To:\n");
- }
- do
- {
- printf(" %s",B[ep->line2-1]);
- ep = ep->link;
- } while (ep != NULL && ep->op == INSERT && ep->line1 == b->line1);
- }
- }
-
- fatal(msg)
- char *msg;
- {
- fprintf(stderr,"%s\n",msg);
- exit();
- }
-
- exceed(d)
- int d;
- {
- fprintf(stderr,"The files differ in at least %d lines. \n",d);
- exit();
- }
- y d$ SUBST C