static char sccsid[] = "@(#)diffh.c 4.1 10/9/80"; #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #define C 3 #define RANGE 30 #define LEN 255 #define INF 16384 char *text[2][RANGE]; long lineno[2] = {1, 1}; /*no. of 1st stored line in each file*/ int ntext[2]; /*number of stored lines in each*/ long n0,n1; /*scan pointer in each*/ int bflag; int debug = 0; FILE *file[2]; /* return pointer to line n of file f*/ char *getl(f,n) long n; { register char *t; char *malloc(); register delta, nt; again: delta = n - lineno[f]; nt = ntext[f]; if(delta<0) progerr("1"); if(delta<nt) return(text[f][delta]); if(delta>nt) progerr("2"); if(nt>=RANGE) progerr("3"); if(feof(file[f])) return(NULL); t = text[f][nt]; if(t==0) { t = text[f][nt] = malloc(LEN+1); if(t==NULL) if(hardsynch()) goto again; else progerr("5"); } t = fgets(t,LEN,file[f]); if(t!=NULL) ntext[f]++; return(t); } /*remove thru line n of file f from storage*/ clrl(f,n) long n; { register i,j; j = n-lineno[f]+1; for(i=0;i+j<ntext[f];i++) movstr(text[f][i+j],text[f][i]); lineno[f] = n+1; ntext[f] -= j; } movstr(s,t) register char *s, *t; { while(*t++= *s++) continue; } main(argc,argv) char **argv; { char *s0,*s1; FILE *dopen(); extern char _sobuf[]; setbuf(stdout, _sobuf); while(*argv[1]=='-') { argc--; argv++; while(*++argv[0]) if(*argv[0]=='b') bflag++; } if(argc!=3) error("must have 2 file arguments",""); file[0] = dopen(argv[1],argv[2]); file[1] = dopen(argv[2],argv[1]); for(;;) { s0 = getl(0,++n0); s1 = getl(1,++n1); if(s0==NULL||s1==NULL) break; if(cmp(s0,s1)!=0) { if(!easysynch()&&!hardsynch()) progerr("5"); } else { clrl(0,n0); clrl(1,n1); } } if(s0==NULL&&s1==NULL) return; if(s0==NULL) output(-1,INF); if(s1==NULL) output(INF,-1); } /* synch on C successive matches*/ easysynch() { int i,j; register k,m; char *s0,*s1; for(i=j=1;i<RANGE&&j<RANGE;i++,j++) { s0 = getl(0,n0+i); if(s0==NULL) return(output(INF,INF)); for(k=C-1;k<j;k++) { for(m=0;m<C;m++) if(cmp(getl(0,n0+i-m), getl(1,n1+k-m))!=0) goto cont1; return(output(i-C,k-C)); cont1: ; } s1 = getl(1,n1+j); if(s1==NULL) return(output(INF,INF)); for(k=C-1;k<=i;k++) { for(m=0;m<C;m++) if(cmp(getl(0,n0+k-m), getl(1,n1+j-m))!=0) goto cont2; return(output(k-C,j-C)); cont2: ; } } return(0); } output(a,b) { register i; char *s; if(a<0) change(n0-1,0,n1,b,"a"); else if(b<0) change(n0,a,n1-1,0,"d"); else change(n0,a,n1,b,"c"); for(i=0;i<=a;i++) { s = getl(0,n0+i); if(s==NULL) break; printf("< %s",s); clrl(0,n0+i); } n0 += i-1; if(a>=0&&b>=0) printf("---\n"); for(i=0;i<=b;i++) { s = getl(1,n1+i); if(s==NULL) break; printf("> %s",s); clrl(1,n1+i); } n1 += i-1; return(1); } change(a,b,c,d,s) long a,c; char *s; { range(a,b); printf("%s",s); range(c,d); printf("\n"); } range(a,b) long a; { if(b==INF) printf("%ld,$",a); else if(b==0) printf("%ld",a); else printf("%ld,%ld",a,a+b); } cmp(s,t) char *s,*t; { if(debug) printf("%s:%s\n",s,t); for(;;){ if(bflag&&isspace(*s)&&isspace(*t)) { while(isspace(*++s)) ; while(isspace(*++t)) ; } if(*s!=*t||*s==0) break; s++; t++; } return(*s-*t); } FILE *dopen(f1,f2) char *f1,*f2; { FILE *f; char b[100],*bptr,*eptr; struct stat statbuf; if(cmp(f1,"-")==0) if(cmp(f2,"-")==0) error("can't do - -",""); else return(stdin); if(stat(f1,&statbuf)==-1) error("can't access ",f1); if((statbuf.st_mode&S_IFMT)==S_IFDIR) { for(bptr=b;*bptr= *f1++;bptr++) ; *bptr++ = '/'; for(eptr=f2;*eptr;eptr++) if(*eptr=='/'&&eptr[1]!=0&&eptr[1]!='/') f2 = eptr+1; while(*bptr++= *f2++) ; f1 = b; } f = fopen(f1,"r"); if(f==NULL) error("can't open",f1); return(f); } progerr(s) char *s; { error("program error ",s); } error(s,t) char *s,*t; { fprintf(stderr,"diffh: %s%s\n",s,t); exit(1); } /*stub for resychronization beyond limits of text buf*/ hardsynch() { change(n0,INF,n1,INF,"c"); printf("---change record omitted\n"); error("can't resynchronize",""); return(0); }