275 lines
4.3 KiB
C
275 lines
4.3 KiB
C
#ifndef lint
|
|
static char *sccsid = "@(#)diffh.c 1.1 94/10/31 SMI; from UCB 4.4 85/11/27";
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <locale.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();
|
|
register int status = 0;
|
|
|
|
setlocale(LC_ALL, "");
|
|
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");
|
|
status = 1;
|
|
} else {
|
|
clrl(0,n0);
|
|
clrl(1,n1);
|
|
}
|
|
}
|
|
if(s0==NULL&&s1==NULL)
|
|
exit(status);
|
|
if(s0==NULL)
|
|
output(-1,INF);
|
|
if(s1==NULL)
|
|
output(INF,-1);
|
|
exit(1);
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
/* 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((unsigned char)*s)
|
|
&&isspace((unsigned char)*t)) {
|
|
while(isspace((unsigned char)*++s)) ;
|
|
while(isspace((unsigned char)*++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(2);
|
|
}
|
|
|
|
/*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);
|
|
}
|