/* diff3 - 3-way differential file comparison*/
/* diff3 [-e] d13 d23 f1 f2 f3
* d13 = diff report on f1 vs f3
* d23 = diff report on f2 vs f3
struct range
{int from
,to
; };
/* from is first in range of changed lines
* from=to=line after point of insertion
struct diff
{struct range old
, new;};
/* de is used to gather editing scripts,
* that are later spewed out in reverse order.
* its first element must be all zero
* the "new" component of de contains line positions
* or byte positions depending on when you look(!?)
/* the number of the last-read line in each file
/* the latest known correspondence between line
* numbers of the 3 files is stored in last[1-3]
fprintf(stderr
,"diff3: arg count\n");
if((fp
[i
] = fopen(argv
[i
+3],"r")) == NULL
) {
printf("diff3: can't open %s\n",argv
[i
+3]);
/*pick up the line numbers of allcahnges from
* (this puts the numbers in a vector, which is not
* strictly necessary, since the vector is processed
* in one sequential pass. The vector could be optimized
for(i
=0;getchange(fp
[0]);i
++) {
fprintf(stderr
,"diff3: too many changes\n");
dd
[i
].old
.from
= dd
[i
-1].old
.to
;
dd
[i
].new.from
= dd
[i
-1].new.to
;
nn
= nn
*10 + *(*lc
)++ - '0';
for(i
=0;i
<sizeof(line
)-1;i
++) {
register struct diff
*d1
, *d2
, *d3
;
for(;(t1
= d1
<d13
+m1
) | (t2
= d2
<d23
+m2
);) {
printf("%d,%d=%d,%d %d,%d=%d,%d\n",
d2
->new.from
,d2
->new.to
);
/* first file is different from others*/
if(!t2
||t1
&&d1
->new.to
< d2
->new.from
) {
/* stuff peculiar to 1st file */
keep(2,&d1
->old
,&d1
->new);
/* second file is different from others*/
if(!t1
||t2
&&d2
->new.to
< d1
->new.from
) {
keep(1,&d2
->old
,&d2
->new);
/* merge overlapping changes in first file
* this happens after extension see below*/
d1
->new.to
>=d1
[1].new.from
) {
d1
[1].old
.from
= d1
->old
.from
;
d1
[1].new.from
= d1
->new.from
;
/* merge overlapping changes in second*/
d2
->new.to
>=d2
[1].new.from
) {
d2
[1].old
.from
= d2
->old
.from
;
d2
[1].new.from
= d2
->new.from
;
/* stuff peculiar to third file or different in all*/
if(d1
->new.from
==d2
->new.from
&&
d1
->new.to
==d2
->new.to
) {
dup
= duplicate(&d1
->old
,&d2
->old
);
/* dup=0 means all files differ
* dup =1 meands files 1&2 identical*/
d3
= d1
->old
.to
>d1
->old
.from
?d1
:d2
;
/* overlapping changes from file1 & 2
* extend changes appropriately to
if(d1
->new.from
<d2
->new.from
) {
d2
->old
.from
-= d2
->new.from
-d1
->new.from
;
d2
->new.from
= d1
->new.from
;
else if(d2
->new.from
<d1
->new.from
) {
d1
->old
.from
-= d1
->new.from
-d2
->new.from
;
d1
->new.from
= d2
->new.from
;
if(d1
->new.to
>d2
->new.to
) {
d2
->old
.to
+= d1
->new.to
- d2
->new.to
;
else if(d2
->new.to
>d1
->new.to
) {
d1
->old
.to
+= d2
->new.to
- d1
->new.to
;
/* the range of ines rold.from thru rold.to in file i
* is to be changed. it is to be printed only if
* it does not duplicate something to be printed later
skip(i
,rold
->from
,(char *)0);
/* print the range of line numbers, rold.from thru rold.to
printf("%da\n",rold
->from
-1);
if(rold
->to
> rold
->from
+1)
printf(",%d",rold
->to
-1);
/* no difference was reported by diff between file 1(or 2)
* and file 3, and an artificial dummy difference (trange)
* must be ginned up to correspond to the change reported
struct range
*rold
, *rnew
;
delta
= last
[3] - last
[i
];
trange
.from
= rnew
->from
- delta
;
trange
.to
= rnew
->to
- delta
;
/* skip to just befor line number from in file i
* if "pr" is nonzero, print all skipped stuff
* w with string pr as a prefix
for(n
=0;cline
[i
]<from
-1;n
+=j
) {
if((j
=getline(fp
[i
]))==0)
/* return 1 or 0 according as the old range
* (in file 1) contains exactly the same data
* as the new range (in file 2)
if(r1
->to
-r1
->from
!= r2
->to
-r2
->from
)
skip(0,r1
->from
,(char *)0);
skip(1,r2
->from
,(char *)0);
for(nline
=0;nline
<r1
->to
-r1
->from
;nline
++) {
fseek(fp
[i
], (long)-nchar
, 1);
fprintf(stderr
,"diff3: logic error\n");
/* collect an editing script for later regurgitation
de
[j
].old
.from
= diff
->old
.from
;
de
[j
].old
.to
= diff
->old
.to
;
de
[j
].new.from
= de
[j
-1].new.to
+skip(2,diff
->new.from
,(char *)0);
de
[j
].new.to
= de
[j
].new.from
+skip(2,diff
->new.to
,(char *)0);
fseek(fp
[2], (long)de
[n
].new.from
, 0);
for(k
=de
[n
].new.to
-de
[n
].new.from
;k
>0;k
-= j
) {
if(fread(block
,1,j
,fp
[2])!=j
)
fwrite(block
, 1, j
, stdout
);