aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatheus Izvekov <mizvekov@gmail.com>2010-01-21 18:58:03 -0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-01-22 04:20:16 +0100
commit6f99c91e431a5afb90ac6d041ea9b08d39c965eb (patch)
treeb31cfab949982043ce993ec240731d2ca4cbc8a4
parentfeadfe742ae9cdc8ddeb425e2b7808c2905bfccb (diff)
downloadbusybox-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.c94
-rwxr-xr-xtestsuite/diff.tests31
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
371static 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
381static void fetch(FILE_and_pos_t *ft, const off_t *ix, int a, int b, int ch) 371static 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 */
568struct 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
575static bool diff(FILE* fp[2], char *file[2]) 554static 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
47testing "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
47testing "diff -b treats EOF as whitespace" \ 58testing "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
70testing "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
76testing "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
59testing "diff always takes context from old file" \ 90testing "diff always takes context from old file" \
60 "diff -ub - input | $TRIM_TAB" \ 91 "diff -ub - input | $TRIM_TAB" \
61"\ 92"\