Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/diff3/diff3.c
| Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | |||||
| /* | /* | ||||
| * "de" is used to gather editing scripts. These are later spewed out in | * "de" is used to gather editing scripts. These are later spewed out in | ||||
| * reverse order. Its first element must be all zero, the "old" and "new" | * reverse order. Its first element must be all zero, the "old" and "new" | ||||
| * components of "de" contain line positions. Array overlap indicates which | * components of "de" contain line positions. Array overlap indicates which | ||||
| * sections in "de" correspond to lines that are different in all three files. | * sections in "de" correspond to lines that are different in all three files. | ||||
| */ | */ | ||||
| static struct diff *de; | static struct diff *de; | ||||
| static char *overlap; | static char *overlap; | ||||
| static int *de_delta; /* file1-file3 line number delta per edit */ | |||||
| static int overlapcnt; | static int overlapcnt; | ||||
| static FILE *fp[3]; | static FILE *fp[3]; | ||||
| static int cline[3]; /* # of the last-read line in each file (0-2) */ | static int cline[3]; /* # of the last-read line in each file (0-2) */ | ||||
| /* | /* | ||||
| * The latest known correspondence between line numbers of the 3 files | * The latest known correspondence between line numbers of the 3 files | ||||
| * is stored in last[1-3]; | * is stored in last[1-3]; | ||||
| */ | */ | ||||
| static int last[4]; | static int last[4]; | ||||
| ▲ Show 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| struct diff *d1, *d2, *d3; | struct diff *d1, *d2, *d3; | ||||
| int j, t1, t2; | int j, t1, t2; | ||||
| bool dup = false; | bool dup = false; | ||||
| d1 = d13; | d1 = d13; | ||||
| d2 = d23; | d2 = d23; | ||||
| j = 0; | j = 0; | ||||
| int f1f3delta = 0; | |||||
| for (;;) { | for (;;) { | ||||
| t1 = (d1 < d13 + m1); | t1 = (d1 < d13 + m1); | ||||
| t2 = (d2 < d23 + m2); | t2 = (d2 < d23 + m2); | ||||
| if (!t1 && !t2) | if (!t1 && !t2) | ||||
| break; | break; | ||||
| /* first file is different from the others */ | /* first file is different from the others */ | ||||
| if (!t2 || (t1 && d1->new.to < d2->new.from)) { | if (!t2 || (t1 && d1->new.to < d2->new.from)) { | ||||
| /* stuff peculiar to 1st file */ | /* stuff peculiar to 1st file */ | ||||
| if (eflag == EFLAG_NONE) { | if (eflag == EFLAG_NONE) { | ||||
| separate("1"); | separate("1"); | ||||
| change(1, &d1->old, false); | change(1, &d1->old, false); | ||||
| keep(2, &d1->new); | keep(2, &d1->new); | ||||
| change(3, &d1->new, false); | change(3, &d1->new, false); | ||||
| } else if (eflag == EFLAG_OVERLAP) { | } else if (eflag == EFLAG_OVERLAP) { | ||||
| j = edit(d2, dup, j, DIFF_TYPE1); | j = edit(d2, dup, j, DIFF_TYPE1); | ||||
| } | } | ||||
| f1f3delta += (d1->old.to - d1->old.from) - | |||||
| (d1->new.to - d1->new.from); | |||||
| d1++; | d1++; | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* second file is different from others */ | /* second file is different from others */ | ||||
| if (!t1 || (t2 && d2->new.to < d1->new.from)) { | if (!t1 || (t2 && d2->new.to < d1->new.from)) { | ||||
| if (eflag == EFLAG_NONE) { | if (eflag == EFLAG_NONE) { | ||||
| separate("2"); | separate("2"); | ||||
| keep(1, &d2->new); | keep(1, &d2->new); | ||||
| change(3, &d2->new, false); | change(3, &d2->new, false); | ||||
| change(2, &d2->old, false); | change(2, &d2->old, false); | ||||
| } else if (Aflag || mflag) { | } else if (Aflag || mflag) { | ||||
| // XXX-THJ: What does it mean for the second file to differ? | if (eflag == EFLAG_UNMERGED) { | ||||
| if (eflag == EFLAG_UNMERGED) | |||||
| j = edit(d2, dup, j, DIFF_TYPE2); | j = edit(d2, dup, j, DIFF_TYPE2); | ||||
| de_delta[j] = f1f3delta; | |||||
| } | } | ||||
| } | |||||
| d2++; | d2++; | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* | /* | ||||
| * Merge overlapping changes in first file | * Merge overlapping changes in first file | ||||
| * this happens after extension (see below). | * this happens after extension (see below). | ||||
| */ | */ | ||||
| if (d1 + 1 < d13 + m1 && d1->new.to >= d1[1].new.from) { | if (d1 + 1 < d13 + m1 && d1->new.to >= d1[1].new.from) { | ||||
| Show All 22 Lines | if (d1->new.from == d2->new.from && d1->new.to == d2->new.to) { | ||||
| change(1, &d1->old, dup); | change(1, &d1->old, dup); | ||||
| change(2, &d2->old, false); | change(2, &d2->old, false); | ||||
| d3 = d1->old.to > d1->old.from ? d1 : d2; | d3 = d1->old.to > d1->old.from ? d1 : d2; | ||||
| change(3, &d3->new, false); | change(3, &d3->new, false); | ||||
| } else { | } else { | ||||
| j = edit(d1, dup, j, DIFF_TYPE3); | j = edit(d1, dup, j, DIFF_TYPE3); | ||||
| } | } | ||||
| dup = false; | dup = false; | ||||
| f1f3delta += (d1->old.to - d1->old.from) - | |||||
| (d1->new.to - d1->new.from); | |||||
| d1++; | d1++; | ||||
| d2++; | d2++; | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* | /* | ||||
| * Overlapping changes from file 1 and 2; extend changes | * Overlapping changes from file 1 and 2; extend changes | ||||
| * appropriately to make them coincide. | * appropriately to make them coincide. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 271 Lines • ▼ Show 20 Lines | for (; n > 0; n--) { | ||||
| deletenew = (new->from == new->to); | deletenew = (new->from == new->to); | ||||
| deleteold = (old->from == old->to); | deleteold = (old->from == old->to); | ||||
| if (de[n].type == DIFF_TYPE2) { | if (de[n].type == DIFF_TYPE2) { | ||||
| if (!oflag || !overlap[n]) { | if (!oflag || !overlap[n]) { | ||||
| prange(old, deletenew); | prange(old, deletenew); | ||||
| printrange(fp[2], new); | printrange(fp[2], new); | ||||
| } else { | } else { | ||||
| startmark = new->to - 1; | startmark = new->to - 1 + de_delta[n]; | ||||
| printf("%da\n", startmark); | printf("%da\n", startmark); | ||||
| printf("%s %s\n", newmark, f3mark); | printf("%s %s\n", newmark, f3mark); | ||||
| printf(".\n"); | printf(".\n"); | ||||
| printf("%da\n", startmark - | printf("%da\n", startmark - | ||||
| (new->to - new->from)); | (new->to - new->from)); | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | for (n = 1; n <= i; n++) { | ||||
| * print deleted ranges. | * print deleted ranges. | ||||
| */ | */ | ||||
| delete = (new->from == new->to); | delete = (new->from == new->to); | ||||
| if (de[n].type == DIFF_TYPE1 && delete) | if (de[n].type == DIFF_TYPE1 && delete) | ||||
| r.to = new->from - 1; | r.to = new->from - 1; | ||||
| else if (de[n].type == DIFF_TYPE3 && (old->from == old->to)) { | else if (de[n].type == DIFF_TYPE3 && (old->from == old->to)) { | ||||
| r.from = old->from - 1; | r.from = old->from - 1; | ||||
| r.to = new->from; | r.to = new->from; | ||||
| } else | } else if (de[n].type == DIFF_TYPE2) | ||||
| r.to = new->from + de_delta[n]; | |||||
| else | |||||
| r.to = old->from; | r.to = old->from; | ||||
| printrange(fp[0], &r); | printrange(fp[0], &r); | ||||
| switch (de[n].type) { | switch (de[n].type) { | ||||
| case DIFF_TYPE1: | case DIFF_TYPE1: | ||||
| /* If this isn't a delete print it */ | /* If this isn't a delete print it */ | ||||
| if (!delete) | if (!delete) | ||||
| printrange(fp[2], new); | printrange(fp[2], new); | ||||
| Show All 31 Lines | case DIFF_TYPE3: | ||||
| printf("%s %s\n", newmark, f3mark); | printf("%s %s\n", newmark, f3mark); | ||||
| } | } | ||||
| break; | break; | ||||
| default: | default: | ||||
| printf("Error: Unhandled diff type - exiting\n"); | printf("Error: Unhandled diff type - exiting\n"); | ||||
| exit(EXIT_FAILURE); | exit(EXIT_FAILURE); | ||||
| } | } | ||||
| if (old->from == old->to) | if (de[n].type == DIFF_TYPE2) | ||||
| r.from = new->to + de_delta[n]; | |||||
| else if (old->from == old->to) | |||||
| r.from = new->to; | r.from = new->to; | ||||
| else | else | ||||
| r.from = old->to; | r.from = old->to; | ||||
| } | } | ||||
| /* | /* | ||||
| * Print from the final range to the end of 'myfile'. Any deletions or | * Print from the final range to the end of 'myfile'. Any deletions or | ||||
| * additions to this file should have been handled by now. | * additions to this file should have been handled by now. | ||||
| * | * | ||||
| * If the ranges are the same we need to rewind a line. | * If the ranges are the same we need to rewind a line. | ||||
| * If the new range is 0 length (from == to), we need to use the old | * If the new range is 0 length (from == to), we need to use the old | ||||
thj: This comment is out of date now. | |||||
| * range. | * range. | ||||
| */ | */ | ||||
| new = &de[n-1].new; | new = &de[n-1].new; | ||||
| old = &de[n-1].old; | old = &de[n-1].old; | ||||
| if (old->from == new->from && old->to == new->to) | if (old->from == new->from && old->to == new->to) | ||||
| r.from--; | r.from--; | ||||
| else if (new->from == new->to) | else if (new->from == new->to) | ||||
| r.from = old->from; | r.from = new->from; | ||||
| r.to = INT_MAX; | r.to = INT_MAX; | ||||
| printrange(fp[2], &r); | printrange(fp[2], &r); | ||||
| exit(overlapcnt > 0); | exit(overlapcnt > 0); | ||||
| } | } | ||||
| static void | static void | ||||
| increase(void) | increase(void) | ||||
| { | { | ||||
| struct diff *p; | struct diff *p; | ||||
| char *q; | char *q; | ||||
| int *s; | |||||
| size_t newsz, incr; | size_t newsz, incr; | ||||
| /* are the memset(3) calls needed? */ | /* are the memset(3) calls needed? */ | ||||
| newsz = szchanges == 0 ? 64 : 2 * szchanges; | newsz = szchanges == 0 ? 64 : 2 * szchanges; | ||||
| incr = newsz - szchanges; | incr = newsz - szchanges; | ||||
| p = reallocarray(d13, newsz, sizeof(*p)); | p = reallocarray(d13, newsz, sizeof(*p)); | ||||
| if (p == NULL) | if (p == NULL) | ||||
| Show All 10 Lines | if (p == NULL) | ||||
| err(1, NULL); | err(1, NULL); | ||||
| memset(p + szchanges, 0, incr * sizeof(*p)); | memset(p + szchanges, 0, incr * sizeof(*p)); | ||||
| de = p; | de = p; | ||||
| q = reallocarray(overlap, newsz, 1); | q = reallocarray(overlap, newsz, 1); | ||||
| if (q == NULL) | if (q == NULL) | ||||
| err(1, NULL); | err(1, NULL); | ||||
| memset(q + szchanges, 0, incr * 1); | memset(q + szchanges, 0, incr * 1); | ||||
| overlap = q; | overlap = q; | ||||
| s = reallocarray(de_delta, newsz, sizeof(*s)); | |||||
| if (s == NULL) | |||||
| err(1, NULL); | |||||
| memset(s + szchanges, 0, incr * sizeof(*s)); | |||||
| de_delta = s; | |||||
| szchanges = newsz; | szchanges = newsz; | ||||
| } | } | ||||
| static void | static void | ||||
| wait_and_check(int pd) | wait_and_check(int pd) | ||||
| { | { | ||||
| int status; | int status; | ||||
| ▲ Show 20 Lines • Show All 170 Lines • Show Last 20 Lines | |||||
This comment is out of date now.