From ab5153e97557791e2c12418ad3f53f53bed2a67a Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Mon, 6 Jan 2014 20:44:03 -0500 Subject: Prism now supports diff versus the repository --- fcomp.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 fcomp.c (limited to 'fcomp.c') diff --git a/fcomp.c b/fcomp.c new file mode 100644 index 0000000..41c5694 --- /dev/null +++ b/fcomp.c @@ -0,0 +1,240 @@ +/* fcomp.c: + + This code has been adapted from: + + Software Practice and Experience + Vol 15, pp. 1025-1040, November 1985. + + "A File Comparison Program" + by Miller and Myers + http://tx0.org/7eq + + The modifications basically allow calling the diff routine + from a separate program, upping the max lines, and modernizing + some portions of the code. Please don't ask me about the + theory involved, I do not understand it. +*/ + +#include +#include +#include + +#include "prism.h" + +#define MAXLINES 15000 +#define ORIGIN MAXLINES +#define INSERT 1 +#define DELETE 2 + +struct edit { + struct edit *link; + int op; + int line1; + int line2; +}; + +static char **A, **B; + +static void fatal(const char *msg) +{ + printf(" ERR: %s\n",msg); +} + +static void exceed(int d) +{ + printf(" ERR: the files differ in at least %d lines\n",d); +} + +static int in_file(const char *filename, char **P) +{ +char *buf, *save; +FILE *fp, *fopen(); +int lines = 0; + + if ((fp = fopen(filename,"r")) == NULL) + { + fatal("cannot open file"); + return PRET_READERROR; + } + + buf = (char *)malloc(256*sizeof(char)); + if(buf == NULL) + return PRET_ERROR; + + while(fgets(buf,100,fp) != NULL) + { + if (lines >= MAXLINES) { + fatal("file is to large for diff"); + return PRET_ERROR; + } + + save = (char *)malloc((strlen(buf)+1)*sizeof(char)); + if (save == NULL) { + fatal("not enough room to save the files"); + return PRET_ERROR; + } + + P[lines++] = save; + strcpy(save, buf); + } + fclose(fp); + + free(buf); + return(lines); +} + +static void put_scr(struct edit *start, const char *fname1, const char *fname2) +{ + 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 && 0 == 0) + { + b = ep; + if (ep->op == INSERT) + //printf("Inserted after line %d:\n",ep->line1); + printf("line %s:%d || %s:%d\n", fname1, ep->line1, fname2, ep->line2); + 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 (a == ep) + printf("line %s:%d || %s:%d\n", fname1, ep->line1, fname2, ep->line2); + //printf("line %d:\n",ep->line1); + else + printf("line %s:%d-%d || %s:%d-%d\n", fname1, ep->line1, a->line1, fname2, ep->line2, a->line2); + //printf("lines %d-%d:\n",ep->line1,a->line1); + + do + { + printf("-%s",A[ep->line1-1]); + ep = ep->link; + } while (ep != b); + + if (!change) { + printf("\n"); + continue; + } + } + do + { + printf("+%s",B[ep->line2-1]); + ep = ep->link; + } while (ep != NULL && ep->op == INSERT && ep->line1 == b->line1); + + printf("\n"); + } +} + + +int compare_files(const char *fname1, const char *fname2) +{ + int max_d, + m, + n, + lower, + upper, + d, + k, + row, + col; + + int *last_d; + struct edit **script; + + struct edit *new; + + last_d = (int *)malloc((2*MAXLINES+1)*sizeof(int)); + script = (struct edit **)malloc((2*MAXLINES+1)*sizeof(struct edit *)); + + A = (char **)malloc(MAXLINES*sizeof(char *)); + B = (char **)malloc(MAXLINES*sizeof(char *)); + if(A == NULL || B == NULL) return PRET_ERROR; + memset(A, 0, MAXLINES); + memset(B, 0, MAXLINES); + + max_d = 2*MAXLINES; + + m = in_file(fname1,A); + n = in_file(fname2,B); + + for (row=0 ; row upper) + { + printf(" the files are identical\n"); + return PRET_OK; + } + + 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); + return PRET_ERROR; + } + + 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], fname1, fname2); + return PRET_OK; + } + if (row == m) + lower = k+2; + + if (col == n) + upper = k-2; + } + --lower; + ++upper; + } + + exceed(d); + return PRET_ERROR; +} + -- cgit v1.2.3