aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-24 14:44:20 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-24 14:44:20 +0000
commitdc1cbf839dc68f6f3fdd4a7dd007b1763b7c8c3c (patch)
tree2998c76189b169fcd8d3cc1013ac68dd0fbcf14d
parentc693840fe81e59a308e0c6e3d2bafae728d1caff (diff)
downloadbusybox-w32-dc1cbf839dc68f6f3fdd4a7dd007b1763b7c8c3c.tar.gz
busybox-w32-dc1cbf839dc68f6f3fdd4a7dd007b1763b7c8c3c.tar.bz2
busybox-w32-dc1cbf839dc68f6f3fdd4a7dd007b1763b7c8c3c.zip
diff: shrink
function old new delta check 678 1607 +929 files_differ - 175 +175 do_diff 436 433 -3 asciifile 94 90 -4 print_only 23 16 -7 diff_main 868 842 -26 prepare 339 301 -38 print_status 316 178 -138 diffreg 2993 1818 -1175 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/7 up/down: 1104/-1391) Total: -287 bytes
-rw-r--r--editors/diff.c230
1 files changed, 126 insertions, 104 deletions
diff --git a/editors/diff.c b/editors/diff.c
index 486077847..4afe7b2db 100644
--- a/editors/diff.c
+++ b/editors/diff.c
@@ -14,14 +14,17 @@
14 14
15#include "libbb.h" 15#include "libbb.h"
16 16
17#define FSIZE_MAX 32768 17// #define FSIZE_MAX 32768
18
19/* NOINLINEs added to prevent gcc from merging too much into diffreg()
20 * (it bites more than it can (efficiently) chew). */
18 21
19/* 22/*
20 * Output flags 23 * Output flags
21 */ 24 */
22#define D_HEADER 1 /* Print a header/footer between files */ 25#define D_HEADER 1 /* Print a header/footer between files */
23#define D_EMPTY1 2 /* Treat first file as empty (/dev/null) */ 26#define D_EMPTY1 2 /* Treat first file as empty (/dev/null) */
24#define D_EMPTY2 4 /* Treat second file as empty (/dev/null) */ 27#define D_EMPTY2 4 /* Treat second file as empty (/dev/null) */
25 28
26/* 29/*
27 * Status values for print_status() and diffreg() return values 30 * Status values for print_status() and diffreg() return values
@@ -37,35 +40,33 @@
37 * D_SKIPPED1 - skipped path1 as it is a special file 40 * D_SKIPPED1 - skipped path1 as it is a special file
38 * D_SKIPPED2 - skipped path2 as it is a special file 41 * D_SKIPPED2 - skipped path2 as it is a special file
39 */ 42 */
40 43#define D_SAME 0
41#define D_SAME 0 44#define D_DIFFER (1 << 0)
42#define D_DIFFER (1<<0) 45#define D_BINARY (1 << 1)
43#define D_BINARY (1<<1) 46#define D_COMMON (1 << 2)
44#define D_COMMON (1<<2) 47/*#define D_ONLY (1 << 3) - unused */
45#define D_ONLY (1<<3) 48#define D_MISMATCH1 (1 << 4)
46#define D_MISMATCH1 (1<<4) 49#define D_MISMATCH2 (1 << 5)
47#define D_MISMATCH2 (1<<5) 50#define D_ERROR (1 << 6)
48#define D_ERROR (1<<6) 51#define D_SKIPPED1 (1 << 7)
49#define D_SKIPPED1 (1<<7) 52#define D_SKIPPED2 (1 << 8)
50#define D_SKIPPED2 (1<<8)
51 53
52/* Command line options */ 54/* Command line options */
53#define FLAG_a (1<<0) 55#define FLAG_a (1 << 0)
54#define FLAG_b (1<<1) 56#define FLAG_b (1 << 1)
55#define FLAG_d (1<<2) 57#define FLAG_d (1 << 2)
56#define FLAG_i (1<<3) 58#define FLAG_i (1 << 3)
57#define FLAG_L (1<<4) 59#define FLAG_L (1 << 4)
58#define FLAG_N (1<<5) 60#define FLAG_N (1 << 5)
59#define FLAG_q (1<<6) 61#define FLAG_q (1 << 6)
60#define FLAG_r (1<<7) 62#define FLAG_r (1 << 7)
61#define FLAG_s (1<<8) 63#define FLAG_s (1 << 8)
62#define FLAG_S (1<<9) 64#define FLAG_S (1 << 9)
63#define FLAG_t (1<<10) 65#define FLAG_t (1 << 10)
64#define FLAG_T (1<<11) 66#define FLAG_T (1 << 11)
65#define FLAG_U (1<<12) 67#define FLAG_U (1 << 12)
66#define FLAG_w (1<<13) 68#define FLAG_w (1 << 13)
67 69
68#define g_read_buf bb_common_bufsiz1
69 70
70struct cand { 71struct cand {
71 int x; 72 int x;
@@ -90,13 +91,16 @@ struct context_vec {
90 int d; /* end line in new file */ 91 int d; /* end line in new file */
91}; 92};
92 93
94
95#define g_read_buf bb_common_bufsiz1
96
93struct globals { 97struct globals {
94 USE_FEATURE_DIFF_DIR(char **dl;) 98 USE_FEATURE_DIFF_DIR(char **dl;)
95 USE_FEATURE_DIFF_DIR(int dl_count;) 99 USE_FEATURE_DIFF_DIR(int dl_count;)
100 int status;
96 /* This is the default number of lines of context. */ 101 /* This is the default number of lines of context. */
97 int context; 102 int context;
98 size_t max_context; 103 size_t max_context;
99 int status;
100 char *start; 104 char *start;
101 const char *label1; 105 const char *label1;
102 const char *label2; 106 const char *label2;
@@ -157,23 +161,25 @@ struct globals {
157} while (0) 161} while (0)
158 162
159 163
160static void print_only(const char *path, size_t dirlen, const char *entry) 164/*static void print_only(const char *path, size_t dirlen, const char *entry)*/
165static void print_only(const char *path, const char *entry)
161{ 166{
162 if (dirlen > 1) 167 printf("Only in %s: %s\n", path, entry);
163 dirlen--;
164 printf("Only in %.*s: %s\n", (int) dirlen, path, entry);
165} 168}
166 169
167static void print_status(int val, char *path1, char *path2, char *entry) 170
171/*static void print_status(int val, char *path1, char *path2, char *entry)*/
172static void print_status(int val, char *_path1, char *_path2)
168{ 173{
169 const char *const _entry = entry ? entry : ""; 174 /*const char *const _entry = entry ? entry : "";*/
170 char * const _path1 = entry ? concat_path_file(path1, _entry) : path1; 175 /*char *const _path1 = entry ? concat_path_file(path1, _entry) : path1;*/
171 char * const _path2 = entry ? concat_path_file(path2, _entry) : path2; 176 /*char *const _path2 = entry ? concat_path_file(path2, _entry) : path2;*/
172 177
173 switch (val) { 178 switch (val) {
174 case D_ONLY: 179/* case D_ONLY:
175 print_only(path1, strlen(path1), entry); 180 print_only(path1, entry);
176 break; 181 break;
182*/
177 case D_COMMON: 183 case D_COMMON:
178 printf("Common subdirectories: %s and %s\n", _path1, _path2); 184 printf("Common subdirectories: %s and %s\n", _path1, _path2);
179 break; 185 break;
@@ -205,18 +211,23 @@ static void print_status(int val, char *path1, char *path2, char *entry)
205 _path2); 211 _path2);
206 break; 212 break;
207 } 213 }
214/*
208 if (entry) { 215 if (entry) {
209 free(_path1); 216 free(_path1);
210 free(_path2); 217 free(_path2);
211 } 218 }
219*/
212} 220}
221
222
223/* Read line, return its nonzero hash. Return 0 if EOF.
224 *
225 * Hash function taken from Robert Sedgewick, Algorithms in C, 3d ed., p 578.
226 */
213static ALWAYS_INLINE int fiddle_sum(int sum, int t) 227static ALWAYS_INLINE int fiddle_sum(int sum, int t)
214{ 228{
215 return sum * 127 + t; 229 return sum * 127 + t;
216} 230}
217/*
218 * Hash function taken from Robert Sedgewick, Algorithms in C, 3d ed., p 578.
219 */
220static int readhash(FILE *fp) 231static int readhash(FILE *fp)
221{ 232{
222 int i, t, space; 233 int i, t, space;
@@ -224,32 +235,34 @@ static int readhash(FILE *fp)
224 235
225 sum = 1; 236 sum = 1;
226 space = 0; 237 space = 0;
238 i = 0;
227 if (!(option_mask32 & (FLAG_b | FLAG_w))) { 239 if (!(option_mask32 & (FLAG_b | FLAG_w))) {
228 for (i = 0; (t = getc(fp)) != '\n'; i++) { 240 while ((t = getc(fp)) != '\n') {
229 if (t == EOF) { 241 if (t == EOF) {
230 if (i == 0) 242 if (i == 0)
231 return 0; 243 return 0;
232 break; 244 break;
233 } 245 }
234 sum = fiddle_sum(sum, t); 246 sum = fiddle_sum(sum, t);
247 i = 1;
235 } 248 }
236 } else { 249 } else {
237 for (i = 0;;) { 250 while (1) {
238 switch (t = getc(fp)) { 251 switch (t = getc(fp)) {
239 case '\t': 252 case '\t':
240 case '\r': 253 case '\r':
241 case '\v': 254 case '\v':
242 case '\f': 255 case '\f':
243 case ' ': 256 case ' ':
244 space++; 257 space = 1;
245 continue; 258 continue;
246 default: 259 default:
247 if (space && !(option_mask32 & FLAG_w)) { 260 if (space && !(option_mask32 & FLAG_w)) {
248 i++; 261 i = 1;
249 space = 0; 262 space = 0;
250 } 263 }
251 sum = fiddle_sum(sum, t); 264 sum = fiddle_sum(sum, t);
252 i++; 265 i = 1;
253 continue; 266 continue;
254 case EOF: 267 case EOF:
255 if (i == 0) 268 if (i == 0)
@@ -273,7 +286,7 @@ static int readhash(FILE *fp)
273 * Check to see if the given files differ. 286 * Check to see if the given files differ.
274 * Returns 0 if they are the same, 1 if different, and -1 on error. 287 * Returns 0 if they are the same, 1 if different, and -1 on error.
275 */ 288 */
276static int files_differ(FILE *f1, FILE *f2, int flags) 289static NOINLINE int files_differ(FILE *f1, FILE *f2, int flags)
277{ 290{
278 size_t i, j; 291 size_t i, j;
279 292
@@ -288,7 +301,7 @@ static int files_differ(FILE *f1, FILE *f2, int flags)
288 if (i != j) 301 if (i != j)
289 return 1; 302 return 1;
290 if (i == 0) 303 if (i == 0)
291 return (ferror(f1) || ferror(f2)); 304 return (ferror(f1) || ferror(f2)) ? -1 : 0;
292 if (memcmp(g_read_buf, 305 if (memcmp(g_read_buf,
293 g_read_buf + COMMON_BUFSIZE/2, i) != 0) 306 g_read_buf + COMMON_BUFSIZE/2, i) != 0)
294 return 1; 307 return 1;
@@ -310,7 +323,7 @@ static void prepare(int i, FILE *fp /*, off_t filesize*/)
310 323
311 p = xmalloc((sz + 3) * sizeof(p[0])); 324 p = xmalloc((sz + 3) * sizeof(p[0]));
312 j = 0; 325 j = 0;
313 while ((h = readhash(fp))) { 326 while ((h = readhash(fp)) != 0) { /* while not EOF */
314 if (j == sz) { 327 if (j == sz) {
315 sz = sz * 3 / 2; 328 sz = sz * 3 / 2;
316 p = xrealloc(p, (sz + 3) * sizeof(p[0])); 329 p = xrealloc(p, (sz + 3) * sizeof(p[0]));
@@ -433,13 +446,13 @@ static int stone(int *a, int n, int *b, int *c)
433 int i, k, y, j, l; 446 int i, k, y, j, l;
434 int oldc, tc, oldl; 447 int oldc, tc, oldl;
435 unsigned int numtries; 448 unsigned int numtries;
436
437#if ENABLE_FEATURE_DIFF_MINIMAL 449#if ENABLE_FEATURE_DIFF_MINIMAL
438 const unsigned int bound = 450 const unsigned int bound =
439 (option_mask32 & FLAG_d) ? UINT_MAX : MAX(256, isqrt(n)); 451 (option_mask32 & FLAG_d) ? UINT_MAX : MAX(256, isqrt(n));
440#else 452#else
441 const unsigned int bound = MAX(256, isqrt(n)); 453 const unsigned int bound = MAX(256, isqrt(n));
442#endif 454#endif
455
443 k = 0; 456 k = 0;
444 c[0] = newcand(0, 0, 0); 457 c[0] = newcand(0, 0, 0);
445 for (i = 1; i <= n; i++) { 458 for (i = 1; i <= n; i++) {
@@ -500,7 +513,7 @@ static void unsort(struct line *f, int l, int *b)
500} 513}
501 514
502 515
503static int skipline(FILE * f) 516static int skipline(FILE *f)
504{ 517{
505 int i, c; 518 int i, c;
506 519
@@ -516,7 +529,7 @@ static int skipline(FILE * f)
516 * to confounding by hashing (which result in "jackpot") 529 * to confounding by hashing (which result in "jackpot")
517 * 2. collect random access indexes to the two files 530 * 2. collect random access indexes to the two files
518 */ 531 */
519static void check(FILE * f1, FILE * f2) 532static NOINLINE void check(FILE *f1, FILE *f2)
520{ 533{
521 int i, j, jackpot, c, d; 534 int i, j, jackpot, c, d;
522 long ctold, ctnew; 535 long ctold, ctnew;
@@ -536,8 +549,7 @@ static void check(FILE * f1, FILE * f2)
536 ixnew[j] = ctnew += skipline(f2); 549 ixnew[j] = ctnew += skipline(f2);
537 j++; 550 j++;
538 } 551 }
539 if ((option_mask32 & FLAG_b) || (option_mask32 & FLAG_w) 552 if (option_mask32 & (FLAG_b | FLAG_w | FLAG_i)) {
540 || (option_mask32 & FLAG_i)) {
541 while (1) { 553 while (1) {
542 c = getc(f1); 554 c = getc(f1);
543 d = getc(f2); 555 d = getc(f2);
@@ -545,8 +557,9 @@ static void check(FILE * f1, FILE * f2)
545 * GNU diff ignores a missing newline 557 * GNU diff ignores a missing newline
546 * in one file if bflag || wflag. 558 * in one file if bflag || wflag.
547 */ 559 */
548 if (((option_mask32 & FLAG_b) || (option_mask32 & FLAG_w)) && 560 if ((option_mask32 & (FLAG_b | FLAG_w))
549 ((c == EOF && d == '\n') || (c == '\n' && d == EOF))) { 561 && ((c == EOF && d == '\n') || (c == '\n' && d == EOF))
562 ) {
550 break; 563 break;
551 } 564 }
552 ctold++; 565 ctold++;
@@ -556,12 +569,14 @@ static void check(FILE * f1, FILE * f2)
556 if (c == '\n') 569 if (c == '\n')
557 break; 570 break;
558 ctold++; 571 ctold++;
559 } while (isspace(c = getc(f1))); 572 c = getc(f1);
573 } while (isspace(c));
560 do { 574 do {
561 if (d == '\n') 575 if (d == '\n')
562 break; 576 break;
563 ctnew++; 577 ctnew++;
564 } while (isspace(d = getc(f2))); 578 d = getc(f2);
579 } while (isspace(d));
565 } else if (option_mask32 & FLAG_w) { 580 } else if (option_mask32 & FLAG_w) {
566 while (isspace(c) && c != '\n') { 581 while (isspace(c) && c != '\n') {
567 c = getc(f1); 582 c = getc(f1);
@@ -594,6 +609,7 @@ static void check(FILE * f1, FILE * f2)
594 J[i] = 0; 609 J[i] = 0;
595 if (c != '\n' && c != EOF) 610 if (c != '\n' && c != EOF)
596 ctold += skipline(f1); 611 ctold += skipline(f1);
612// BUG? Should be "if (d != '\n' && d != EOF)" ?
597 if (d != '\n' && c != EOF) 613 if (d != '\n' && c != EOF)
598 ctnew += skipline(f2); 614 ctnew += skipline(f2);
599 break; 615 break;
@@ -628,9 +644,11 @@ static void sort(struct line *a, int n)
628 aim = &ai[m]; 644 aim = &ai[m];
629 if (aim < ai) 645 if (aim < ai)
630 break; /* wraparound */ 646 break; /* wraparound */
631 if (aim->value > ai[0].value || 647 if (aim->value > ai[0].value
632 (aim->value == ai[0].value && aim->serial > ai[0].serial)) 648 || (aim->value == ai[0].value && aim->serial > ai[0].serial)
649 ) {
633 break; 650 break;
651 }
634 w.value = ai[0].value; 652 w.value = ai[0].value;
635 ai[0].value = aim->value; 653 ai[0].value = aim->value;
636 aim->value = w.value; 654 aim->value = w.value;
@@ -654,7 +672,7 @@ static void uni_range(int a, int b)
654} 672}
655 673
656 674
657static void fetch(long *f, int a, int b, FILE * lb, int ch) 675static void fetch(long *f, int a, int b, FILE *lb, int ch)
658{ 676{
659 int i, j, c, lastc, col, nc; 677 int i, j, c, lastc, col, nc;
660 678
@@ -688,31 +706,31 @@ static void fetch(long *f, int a, int b, FILE * lb, int ch)
688} 706}
689 707
690 708
691static int asciifile(FILE * f)
692{
693#if ENABLE_FEATURE_DIFF_BINARY 709#if ENABLE_FEATURE_DIFF_BINARY
710static int asciifile(FILE *f)
711{
694 int i, cnt; 712 int i, cnt;
695#endif
696 713
697 if ((option_mask32 & FLAG_a) || f == NULL) 714 if (option_mask32 & FLAG_a)
698 return 1; 715 return 1;
699
700#if ENABLE_FEATURE_DIFF_BINARY
701 rewind(f); 716 rewind(f);
702 cnt = fread(g_read_buf, 1, COMMON_BUFSIZE, f); 717 cnt = fread(g_read_buf, 1, COMMON_BUFSIZE, f);
703 for (i = 0; i < cnt; i++) { 718 for (i = 0; i < cnt; i++) {
704 if (!isprint(g_read_buf[i]) 719 if (!isprint(g_read_buf[i])
705 && !isspace(g_read_buf[i])) { 720 && !isspace(g_read_buf[i])
721 ) {
706 return 0; 722 return 0;
707 } 723 }
708 } 724 }
709#endif
710 return 1; 725 return 1;
711} 726}
727#else
728#define asciifile(f) 1
729#endif
712 730
713 731
714/* dump accumulated "unified" diff changes */ 732/* dump accumulated "unified" diff changes */
715static void dump_unified_vec(FILE * f1, FILE * f2) 733static void dump_unified_vec(FILE *f1, FILE *f2)
716{ 734{
717 struct context_vec *cvp = context_vec_start; 735 struct context_vec *cvp = context_vec_start;
718 int lowa, upb, lowc, upd; 736 int lowa, upb, lowc, upd;
@@ -756,6 +774,7 @@ static void dump_unified_vec(FILE * f1, FILE * f2)
756#if 0 774#if 0
757 switch (ch) { 775 switch (ch) {
758 case 'c': 776 case 'c':
777// fetch() seeks!
759 fetch(ixold, lowa, a - 1, f1, ' '); 778 fetch(ixold, lowa, a - 1, f1, ' ');
760 fetch(ixold, a, b, f1, '-'); 779 fetch(ixold, a, b, f1, '-');
761 fetch(ixnew, c, d, f2, '+'); 780 fetch(ixnew, c, d, f2, '+');
@@ -808,8 +827,8 @@ static void print_header(const char *file1, const char *file2)
808 * lines appended (beginning at b). If c is greater than d then there are 827 * lines appended (beginning at b). If c is greater than d then there are
809 * lines missing from the to file. 828 * lines missing from the to file.
810 */ 829 */
811static void change(char *file1, FILE * f1, char *file2, FILE * f2, int a, 830static void change(char *file1, FILE *f1, char *file2, FILE *f2,
812 int b, int c, int d) 831 int a, int b, int c, int d)
813{ 832{
814 if ((a > b && c > d) || (option_mask32 & FLAG_q)) { 833 if ((a > b && c > d) || (option_mask32 & FLAG_q)) {
815 anychange = 1; 834 anychange = 1;
@@ -833,12 +852,14 @@ static void change(char *file1, FILE * f1, char *file2, FILE * f2, int a,
833 * Print the context/unidiff header first time through. 852 * Print the context/unidiff header first time through.
834 */ 853 */
835 print_header(file1, file2); 854 print_header(file1, file2);
836 } else if (a > context_vec_ptr->b + (2 * context) + 1 && 855 } else if (a > context_vec_ptr->b + (2 * context) + 1
837 c > context_vec_ptr->d + (2 * context) + 1) { 856 && c > context_vec_ptr->d + (2 * context) + 1
857 ) {
838 /* 858 /*
839 * If this change is more than 'context' lines from the 859 * If this change is more than 'context' lines from the
840 * previous change, dump the record and reset it. 860 * previous change, dump the record and reset it.
841 */ 861 */
862// dump_unified_vec() seeks!
842 dump_unified_vec(f1, f2); 863 dump_unified_vec(f1, f2);
843 } 864 }
844 context_vec_ptr++; 865 context_vec_ptr++;
@@ -850,7 +871,7 @@ static void change(char *file1, FILE * f1, char *file2, FILE * f2, int a,
850} 871}
851 872
852 873
853static void output(char *file1, FILE * f1, char *file2, FILE * f2) 874static void output(char *file1, FILE *f1, char *file2, FILE *f2)
854{ 875{
855 /* Note that j0 and j1 can't be used as they are defined in math.h. 876 /* Note that j0 and j1 can't be used as they are defined in math.h.
856 * This also allows the rather amusing variable 'j00'... */ 877 * This also allows the rather amusing variable 'j00'... */
@@ -870,12 +891,15 @@ static void output(char *file1, FILE * f1, char *file2, FILE * f2)
870 i1++; 891 i1++;
871 j01 = J[i1 + 1] - 1; 892 j01 = J[i1 + 1] - 1;
872 J[i1] = j01; 893 J[i1] = j01;
894// change() seeks!
873 change(file1, f1, file2, f2, i0, i1, j00, j01); 895 change(file1, f1, file2, f2, i0, i1, j00, j01);
874 } 896 }
875 if (m == 0) { 897 if (m == 0) {
898// change() seeks!
876 change(file1, f1, file2, f2, 1, 0, 1, len[1]); 899 change(file1, f1, file2, f2, 1, 0, 1, len[1]);
877 } 900 }
878 if (anychange != 0 && !(option_mask32 & FLAG_q)) { 901 if (anychange != 0 && !(option_mask32 & FLAG_q)) {
902// dump_unified_vec() seeks!
879 dump_unified_vec(f1, f2); 903 dump_unified_vec(f1, f2);
880 } 904 }
881} 905}
@@ -887,12 +911,12 @@ static void output(char *file1, FILE * f1, char *file2, FILE * f2)
887 * 911 *
888 * The major goal is to generate the match vector J. 912 * The major goal is to generate the match vector J.
889 * J[i] is the index of the line in file1 corresponding 913 * J[i] is the index of the line in file1 corresponding
890 * to line i file0. J[i] = 0 if there is no 914 * to line i in file0. J[i] = 0 if there is no
891 * such line in file1. 915 * such line in file1.
892 * 916 *
893 * Lines are hashed so as to work in core. All potential 917 * Lines are hashed so as to work in core. All potential
894 * matches are located by sorting the lines of each file 918 * matches are located by sorting the lines of each file
895 * on the hash (called ``value''). In particular, this 919 * on the hash (called "value"). In particular, this
896 * collects the equivalence classes in file1 together. 920 * collects the equivalence classes in file1 together.
897 * Subroutine equiv replaces the value of each line in 921 * Subroutine equiv replaces the value of each line in
898 * file0 by the index of the first element of its 922 * file0 by the index of the first element of its
@@ -908,7 +932,7 @@ static void output(char *file1, FILE * f1, char *file2, FILE * f2)
908 * The cleverness lies in routine stone. This marches 932 * The cleverness lies in routine stone. This marches
909 * through the lines of file0, developing a vector klist 933 * through the lines of file0, developing a vector klist
910 * of "k-candidates". At step i a k-candidate is a matched 934 * of "k-candidates". At step i a k-candidate is a matched
911 * pair of lines x,y (x in file0 y in file1) such that 935 * pair of lines x,y (x in file0, y in file1) such that
912 * there is a common subsequence of length k 936 * there is a common subsequence of length k
913 * between the first i lines of file0 and the first y 937 * between the first i lines of file0 and the first y
914 * lines of file1, but there is no such subsequence for 938 * lines of file1, but there is no such subsequence for
@@ -939,14 +963,13 @@ static void output(char *file1, FILE * f1, char *file2, FILE * f2)
939 * allocating what is needed and reusing what is not. 963 * allocating what is needed and reusing what is not.
940 * The core requirements for problems larger than somewhat 964 * The core requirements for problems larger than somewhat
941 * are (in words) 2*length(file0) + length(file1) + 965 * are (in words) 2*length(file0) + length(file1) +
942 * 3*(number of k-candidates installed), typically about 966 * 3*(number of k-candidates installed), typically about
943 * 6n words for files of length n. 967 * 6n words for files of length n.
944 */ 968 */
945static unsigned diffreg(char *ofile1, char *ofile2, int flags) 969static unsigned diffreg(char *file1, char *file2, int flags)
946{ 970{
947 char *file1 = ofile1; 971 FILE *f1;
948 char *file2 = ofile2; 972 FILE *f2;
949 FILE *f1 = stdin, *f2 = stdin;
950 unsigned rval; 973 unsigned rval;
951 int i; 974 int i;
952 975
@@ -956,19 +979,19 @@ static unsigned diffreg(char *ofile1, char *ofile2, int flags)
956 if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode)) 979 if (S_ISDIR(stb1.st_mode) != S_ISDIR(stb2.st_mode))
957 return (S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2); 980 return (S_ISDIR(stb1.st_mode) ? D_MISMATCH1 : D_MISMATCH2);
958 981
959 rval = D_SAME;
960
961 if (LONE_DASH(file1) && LONE_DASH(file2)) 982 if (LONE_DASH(file1) && LONE_DASH(file2))
962 goto closem; 983 return D_SAME;
984
985 rval = D_SAME;
963 986
964 if (flags & D_EMPTY1) 987 if (flags & D_EMPTY1)
965 f1 = xfopen(bb_dev_null, "r"); 988 f1 = xfopen(bb_dev_null, "r");
966 else if (NOT_LONE_DASH(file1)) 989 else
967 f1 = xfopen(file1, "r"); 990 f1 = xfopen_stdin(file1);
968 if (flags & D_EMPTY2) 991 if (flags & D_EMPTY2)
969 f2 = xfopen(bb_dev_null, "r"); 992 f2 = xfopen(bb_dev_null, "r");
970 else if (NOT_LONE_DASH(file2)) 993 else
971 f2 = xfopen(file2, "r"); 994 f2 = xfopen_stdin(file2);
972 995
973/* We can't diff non-seekable stream - we use rewind(), fseek(). 996/* We can't diff non-seekable stream - we use rewind(), fseek().
974 * This can be fixed (volunteers?). 997 * This can be fixed (volunteers?).
@@ -977,6 +1000,7 @@ static unsigned diffreg(char *ofile1, char *ofile2, int flags)
977 * Check in main won't catch "diffing fifos buried in subdirectories" 1000 * Check in main won't catch "diffing fifos buried in subdirectories"
978 * failure scenario - not very likely in real life... */ 1001 * failure scenario - not very likely in real life... */
979 1002
1003 /* Quick check whether they are different */
980 i = files_differ(f1, f2, flags); 1004 i = files_differ(f1, f2, flags);
981 if (i == 0) 1005 if (i == 0)
982 goto closem; 1006 goto closem;
@@ -992,6 +1016,7 @@ static unsigned diffreg(char *ofile1, char *ofile2, int flags)
992 goto closem; 1016 goto closem;
993 } 1017 }
994 1018
1019// Rewind inside!
995 prepare(0, f1 /*, stb1.st_size*/); 1020 prepare(0, f1 /*, stb1.st_size*/);
996 prepare(1, f2 /*, stb2.st_size*/); 1021 prepare(1, f2 /*, stb2.st_size*/);
997 prune(); 1022 prune();
@@ -1021,7 +1046,9 @@ static unsigned diffreg(char *ofile1, char *ofile2, int flags)
1021 1046
1022 ixold = xrealloc(ixold, (len[0] + 2) * sizeof(long)); 1047 ixold = xrealloc(ixold, (len[0] + 2) * sizeof(long));
1023 ixnew = xrealloc(ixnew, (len[1] + 2) * sizeof(long)); 1048 ixnew = xrealloc(ixnew, (len[1] + 2) * sizeof(long));
1049// Rewind inside!
1024 check(f1, f2); 1050 check(f1, f2);
1051// Rewind inside!
1025 output(file1, f1, file2, f2); 1052 output(file1, f1, file2, f2);
1026 1053
1027 closem: 1054 closem:
@@ -1032,10 +1059,6 @@ static unsigned diffreg(char *ofile1, char *ofile2, int flags)
1032 } 1059 }
1033 fclose_if_not_stdin(f1); 1060 fclose_if_not_stdin(f1);
1034 fclose_if_not_stdin(f2); 1061 fclose_if_not_stdin(f2);
1035 if (file1 != ofile1)
1036 free(file1);
1037 if (file2 != ofile2)
1038 free(file2);
1039 return rval; 1062 return rval;
1040} 1063}
1041 1064
@@ -1086,7 +1109,7 @@ static void do_diff(char *dir1, char *path1, char *dir2, char *path2)
1086 else 1109 else
1087 val = diffreg(fullpath1, fullpath2, flags); 1110 val = diffreg(fullpath1, fullpath2, flags);
1088 1111
1089 print_status(val, fullpath1, fullpath2, NULL); 1112 print_status(val, fullpath1, fullpath2 /*, NULL*/);
1090 ret: 1113 ret:
1091 free(fullpath1); 1114 free(fullpath1);
1092 free(fullpath2); 1115 free(fullpath2);
@@ -1097,7 +1120,8 @@ static void do_diff(char *dir1, char *path1, char *dir2, char *path2)
1097#if ENABLE_FEATURE_DIFF_DIR 1120#if ENABLE_FEATURE_DIFF_DIR
1098/* This function adds a filename to dl, the directory listing. */ 1121/* This function adds a filename to dl, the directory listing. */
1099static int add_to_dirlist(const char *filename, 1122static int add_to_dirlist(const char *filename,
1100 struct stat ATTRIBUTE_UNUSED * sb, void *userdata, 1123 struct stat ATTRIBUTE_UNUSED *sb,
1124 void *userdata,
1101 int depth ATTRIBUTE_UNUSED) 1125 int depth ATTRIBUTE_UNUSED)
1102{ 1126{
1103 /* +2: with space for eventual trailing NULL */ 1127 /* +2: with space for eventual trailing NULL */
@@ -1160,7 +1184,6 @@ static void diffdir(char *p1, char *p2)
1160 *dp2 = '\0'; 1184 *dp2 = '\0';
1161 1185
1162 /* Get directory listings for p1 and p2. */ 1186 /* Get directory listings for p1 and p2. */
1163
1164 dirlist1 = get_dir(p1); 1187 dirlist1 = get_dir(p1);
1165 dirlist2 = get_dir(p2); 1188 dirlist2 = get_dir(p2);
1166 1189
@@ -1190,13 +1213,13 @@ static void diffdir(char *p1, char *p2)
1190 if (option_mask32 & FLAG_N) 1213 if (option_mask32 & FLAG_N)
1191 do_diff(p1, dp1, p2, NULL); 1214 do_diff(p1, dp1, p2, NULL);
1192 else 1215 else
1193 print_only(p1, strlen(p1) + 1, dp1); 1216 print_only(p1, dp1);
1194 dirlist1++; 1217 dirlist1++;
1195 } else { 1218 } else {
1196 if (option_mask32 & FLAG_N) 1219 if (option_mask32 & FLAG_N)
1197 do_diff(p1, NULL, p2, dp2); 1220 do_diff(p1, NULL, p2, dp2);
1198 else 1221 else
1199 print_only(p2, strlen(p2) + 1, dp2); 1222 print_only(p2, dp2);
1200 dirlist2++; 1223 dirlist2++;
1201 } 1224 }
1202 } 1225 }
@@ -1237,7 +1260,6 @@ int diff_main(int argc ATTRIBUTE_UNUSED, char **argv)
1237 * Do sanity checks, fill in stb1 and stb2 and call the appropriate 1260 * Do sanity checks, fill in stb1 and stb2 and call the appropriate
1238 * driver routine. Both drivers use the contents of stb1 and stb2. 1261 * driver routine. Both drivers use the contents of stb1 and stb2.
1239 */ 1262 */
1240
1241 f1 = argv[0]; 1263 f1 = argv[0];
1242 f2 = argv[1]; 1264 f2 = argv[1];
1243 if (LONE_DASH(f1)) { 1265 if (LONE_DASH(f1)) {
@@ -1272,7 +1294,7 @@ int diff_main(int argc ATTRIBUTE_UNUSED, char **argv)
1272 * This can be fixed (volunteers?) */ 1294 * This can be fixed (volunteers?) */
1273 if (!S_ISREG(stb1.st_mode) || !S_ISREG(stb2.st_mode)) 1295 if (!S_ISREG(stb1.st_mode) || !S_ISREG(stb2.st_mode))
1274 bb_error_msg_and_die("can't diff non-seekable stream"); 1296 bb_error_msg_and_die("can't diff non-seekable stream");
1275 print_status(diffreg(f1, f2, 0), f1, f2, NULL); 1297 print_status(diffreg(f1, f2, 0), f1, f2 /*, NULL*/);
1276 } 1298 }
1277 return status; 1299 return status;
1278} 1300}