diff options
author | Matheus Izvekov <mizvekov@gmail.com> | 2010-01-21 18:58:03 -0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-22 04:20:16 +0100 |
commit | 6f99c91e431a5afb90ac6d041ea9b08d39c965eb (patch) | |
tree | b31cfab949982043ce993ec240731d2ca4cbc8a4 | |
parent | feadfe742ae9cdc8ddeb425e2b7808c2905bfccb (diff) | |
download | busybox-w32-6f99c91e431a5afb90ac6d041ea9b08d39c965eb.tar.gz busybox-w32-6f99c91e431a5afb90ac6d041ea9b08d39c965eb.tar.bz2 busybox-w32-6f99c91e431a5afb90ac6d041ea9b08d39c965eb.zip |
diff: fix flag -B, cleanups and a couple more tests V2
function old new delta
diffreg 1157 1268 +111
uni_range 51 - -51
Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/diff.c | 94 | ||||
-rwxr-xr-x | testsuite/diff.tests | 31 |
2 files changed, 71 insertions, 54 deletions
diff --git a/editors/diff.c b/editors/diff.c index 2e3a455f7..e4d74abca 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -368,16 +368,6 @@ static int line_compar(const void *a, const void *b) | |||
368 | #undef l1 | 368 | #undef l1 |
369 | } | 369 | } |
370 | 370 | ||
371 | static void uni_range(int a, int b) | ||
372 | { | ||
373 | if (a < b) | ||
374 | printf("%d,%d", a, b - a + 1); | ||
375 | else if (a == b) | ||
376 | printf("%d", b); | ||
377 | else | ||
378 | printf("%d,0", b); | ||
379 | } | ||
380 | |||
381 | static void fetch(FILE_and_pos_t *ft, const off_t *ix, int a, int b, int ch) | 371 | static void fetch(FILE_and_pos_t *ft, const off_t *ix, int a, int b, int ch) |
382 | { | 372 | { |
383 | for (int i = a; i <= b; i++) { | 373 | for (int i = a; i <= b; i++) { |
@@ -561,17 +551,6 @@ start: | |||
561 | return J; | 551 | return J; |
562 | } | 552 | } |
563 | 553 | ||
564 | /* | ||
565 | * The following struct is used to record change information | ||
566 | * doing a "context" or "unified" diff. | ||
567 | */ | ||
568 | struct context_vec { | ||
569 | int a; /* start line in old file */ | ||
570 | int b; /* end line in old file */ | ||
571 | int c; /* start line in new file */ | ||
572 | int d; /* end line in new file */ | ||
573 | }; | ||
574 | |||
575 | static bool diff(FILE* fp[2], char *file[2]) | 554 | static bool diff(FILE* fp[2], char *file[2]) |
576 | { | 555 | { |
577 | int nlen[2]; | 556 | int nlen[2]; |
@@ -580,22 +559,23 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
580 | int *J = create_J(ft, nlen, ix); | 559 | int *J = create_J(ft, nlen, ix); |
581 | 560 | ||
582 | bool anychange = false; | 561 | bool anychange = false; |
583 | struct context_vec *vec = NULL; | 562 | typedef struct { int a, b; } vec_t[2]; |
584 | int idx = -1, i = 1; | 563 | vec_t *vec = NULL; |
564 | int i = 1, idx = -1; | ||
585 | 565 | ||
586 | do { | 566 | do { |
587 | bool nonempty = false; | 567 | bool nonempty = false; |
588 | 568 | ||
589 | while (1) { | 569 | while (1) { |
590 | struct context_vec v; | 570 | vec_t v; |
591 | 571 | ||
592 | for (v.a = i; v.a <= nlen[0] && J[v.a] == J[v.a - 1] + 1; v.a++) | 572 | for (v[0].a = i; v[0].a <= nlen[0] && J[v[0].a] == J[v[0].a - 1] + 1; v[0].a++) |
593 | continue; | 573 | continue; |
594 | v.c = J[v.a - 1] + 1; | 574 | v[1].a = J[v[0].a - 1] + 1; |
595 | 575 | ||
596 | for (v.b = v.a - 1; v.b < nlen[0] && !J[v.b + 1]; v.b++) | 576 | for (v[0].b = v[0].a - 1; v[0].b < nlen[0] && !J[v[0].b + 1]; v[0].b++) |
597 | continue; | 577 | continue; |
598 | v.d = J[v.b + 1] - 1; | 578 | v[1].b = J[v[0].b + 1] - 1; |
599 | /* | 579 | /* |
600 | * Indicate that there is a difference between lines a and b of the 'from' file | 580 | * Indicate that there is a difference between lines a and b of the 'from' file |
601 | * to get to lines c to d of the 'to' file. If a is greater than b then there | 581 | * to get to lines c to d of the 'to' file. If a is greater than b then there |
@@ -603,35 +583,36 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
603 | * lines appended (beginning at b). If c is greater than d then there are | 583 | * lines appended (beginning at b). If c is greater than d then there are |
604 | * lines missing from the 'to' file. | 584 | * lines missing from the 'to' file. |
605 | */ | 585 | */ |
606 | if (v.a <= v.b || v.c <= v.d) { | 586 | if (v[0].a <= v[0].b || v[1].a <= v[1].b) { |
607 | /* | 587 | /* |
608 | * If this change is more than 'context' lines from the | 588 | * If this change is more than 'context' lines from the |
609 | * previous change, dump the record and reset it. | 589 | * previous change, dump the record and reset it. |
610 | */ | 590 | */ |
591 | int ct = (2 * opt_U_context) + 1; | ||
611 | if (idx >= 0 | 592 | if (idx >= 0 |
612 | && v.a > vec[idx].b + (2 * opt_U_context) + 1 | 593 | && v[0].a > vec[idx][0].b + ct |
613 | && v.c > vec[idx].d + (2 * opt_U_context) + 1 | 594 | && v[1].a > vec[idx][1].b + ct |
614 | ) { | 595 | ) { |
615 | break; | 596 | break; |
616 | } | 597 | } |
617 | nonempty |= (v.a >= v.b) && (v.c >= v.d); | 598 | |
599 | for (int j = 0; j < 2; j++) | ||
600 | for (int k = v[j].a; k < v[j].b; k++) | ||
601 | nonempty |= (ix[j][k+1] - ix[j][k] != 1); | ||
602 | |||
618 | vec = xrealloc_vector(vec, 6, ++idx); | 603 | vec = xrealloc_vector(vec, 6, ++idx); |
619 | vec[idx] = v; | 604 | memcpy(vec[idx], v, sizeof(v)); |
620 | } | 605 | } |
621 | 606 | ||
622 | i = v.b + 1; | 607 | i = v[0].b + 1; |
623 | if (i > nlen[0]) | 608 | if (i > nlen[0]) |
624 | break; | 609 | break; |
625 | J[v.b] = v.d; | 610 | J[v[0].b] = v[1].b; |
626 | } | 611 | } |
627 | if (idx < 0) | 612 | if (idx < 0 || ((option_mask32 & FLAG(B)) && !nonempty)) |
628 | continue; | 613 | goto cont; |
629 | if (!(option_mask32 & (FLAG(q)+FLAG(B))) && !nonempty) { | 614 | if (!(option_mask32 & FLAG(q))) { |
630 | struct context_vec *cvp = vec; | 615 | vec_t span, *cvp = vec; |
631 | int lowa = MAX(1, cvp->a - opt_U_context); | ||
632 | int upb = MIN(nlen[0], vec[idx].b + opt_U_context); | ||
633 | int lowc = MAX(1, cvp->c - opt_U_context); | ||
634 | int upd = MIN(nlen[1], vec[idx].d + opt_U_context); | ||
635 | 616 | ||
636 | if (!anychange) { | 617 | if (!anychange) { |
637 | /* Print the context/unidiff header first time through */ | 618 | /* Print the context/unidiff header first time through */ |
@@ -639,28 +620,33 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
639 | printf("+++ %s\n", label[1] ? label[1] : file[1]); | 620 | printf("+++ %s\n", label[1] ? label[1] : file[1]); |
640 | } | 621 | } |
641 | 622 | ||
642 | printf("@@ -"); | 623 | printf("@@"); |
643 | uni_range(lowa, upb); | 624 | for (int j = 0; j < 2; j++) { |
644 | printf(" +"); | 625 | int a = span[j].a = MAX(1, (*cvp)[j].a - opt_U_context); |
645 | uni_range(lowc, upd); | 626 | int b = span[j].b = MIN(nlen[j], vec[idx][j].b + opt_U_context); |
646 | printf(" @@\n"); | ||
647 | 627 | ||
628 | printf(" %c%d", j ? '+' : '-', MIN(a, b)); | ||
629 | if (a == b) | ||
630 | continue; | ||
631 | printf(",%d", (a < b) ? b - a + 1 : 0); | ||
632 | } | ||
633 | printf(" @@\n"); | ||
648 | /* | 634 | /* |
649 | * Output changes in "unified" diff format--the old and new lines | 635 | * Output changes in "unified" diff format--the old and new lines |
650 | * are printed together. | 636 | * are printed together. |
651 | */ | 637 | */ |
652 | while (1) { | 638 | for (int lowa = span[0].a; ; lowa = (*cvp++)[0].b + 1) { |
653 | bool end = cvp > &vec[idx]; | 639 | bool end = cvp > &vec[idx]; |
654 | fetch(&ft[0], ix[0], lowa, end ? upb : cvp->a - 1, ' '); | 640 | fetch(&ft[0], ix[0], lowa, end ? span[0].b : (*cvp)[0].a - 1, ' '); |
655 | if (end) | 641 | if (end) |
656 | break; | 642 | break; |
657 | fetch(&ft[0], ix[0], cvp->a, cvp->b, '-'); | 643 | for (int j = 0; j < 2; j++) |
658 | fetch(&ft[1], ix[1], cvp->c, cvp->d, '+'); | 644 | fetch(&ft[j], ix[j], (*cvp)[j].a, (*cvp)[j].b, j ? '+' : '-'); |
659 | lowa = cvp++->b + 1; | ||
660 | } | 645 | } |
661 | } | 646 | } |
662 | idx = -1; | ||
663 | anychange = true; | 647 | anychange = true; |
648 | cont: | ||
649 | idx = -1; | ||
664 | } while (i <= nlen[0]); | 650 | } while (i <= nlen[0]); |
665 | 651 | ||
666 | free(vec); | 652 | free(vec); |
diff --git a/testsuite/diff.tests b/testsuite/diff.tests index f7bde2f5b..72ebb6c4c 100755 --- a/testsuite/diff.tests +++ b/testsuite/diff.tests | |||
@@ -44,6 +44,17 @@ testing "diff of stdin, twice" \ | |||
44 | "" \ | 44 | "" \ |
45 | "stdin" | 45 | "stdin" |
46 | 46 | ||
47 | testing "diff of empty file against nonempty one" \ | ||
48 | "diff -u - input | $TRIM_TAB" \ | ||
49 | "\ | ||
50 | --- - | ||
51 | +++ input | ||
52 | @@ -0,0 +1 @@ | ||
53 | +a | ||
54 | " \ | ||
55 | "a\n" \ | ||
56 | "" | ||
57 | |||
47 | testing "diff -b treats EOF as whitespace" \ | 58 | testing "diff -b treats EOF as whitespace" \ |
48 | 'diff -ub - input; echo $?' \ | 59 | 'diff -ub - input; echo $?' \ |
49 | "0\n" \ | 60 | "0\n" \ |
@@ -56,6 +67,26 @@ testing "diff -b treats all spaces as equal" \ | |||
56 | "a \t c\n" \ | 67 | "a \t c\n" \ |
57 | "a\t \tc\n" | 68 | "a\t \tc\n" |
58 | 69 | ||
70 | testing "diff -B ignores changes whose lines are all blank" \ | ||
71 | 'diff -uB - input; echo $?' \ | ||
72 | "0\n" \ | ||
73 | "a\n" \ | ||
74 | "\na\n\n" | ||
75 | |||
76 | testing "diff -B does not ignore changes whose lines are not all blank" \ | ||
77 | "diff -uB - input | $TRIM_TAB" \ | ||
78 | "\ | ||
79 | --- - | ||
80 | +++ input | ||
81 | @@ -1,3 +1 @@ | ||
82 | - | ||
83 | -b | ||
84 | - | ||
85 | +a | ||
86 | " \ | ||
87 | "a\n" \ | ||
88 | "\nb\n\n" | ||
89 | |||
59 | testing "diff always takes context from old file" \ | 90 | testing "diff always takes context from old file" \ |
60 | "diff -ub - input | $TRIM_TAB" \ | 91 | "diff -ub - input | $TRIM_TAB" \ |
61 | "\ | 92 | "\ |