diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-24 14:44:20 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-24 14:44:20 +0000 |
commit | dc1cbf839dc68f6f3fdd4a7dd007b1763b7c8c3c (patch) | |
tree | 2998c76189b169fcd8d3cc1013ac68dd0fbcf14d | |
parent | c693840fe81e59a308e0c6e3d2bafae728d1caff (diff) | |
download | busybox-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.c | 230 |
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 | ||
70 | struct cand { | 71 | struct 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 | |||
93 | struct globals { | 97 | struct 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 | ||
160 | static 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)*/ |
165 | static 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 | ||
167 | static 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)*/ | ||
172 | static 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 | */ | ||
213 | static ALWAYS_INLINE int fiddle_sum(int sum, int t) | 227 | static 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 | */ | ||
220 | static int readhash(FILE *fp) | 231 | static 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 | */ |
276 | static int files_differ(FILE *f1, FILE *f2, int flags) | 289 | static 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 | ||
503 | static int skipline(FILE * f) | 516 | static 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 | */ |
519 | static void check(FILE * f1, FILE * f2) | 532 | static 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 | ||
657 | static void fetch(long *f, int a, int b, FILE * lb, int ch) | 675 | static 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 | ||
691 | static int asciifile(FILE * f) | ||
692 | { | ||
693 | #if ENABLE_FEATURE_DIFF_BINARY | 709 | #if ENABLE_FEATURE_DIFF_BINARY |
710 | static 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 */ |
715 | static void dump_unified_vec(FILE * f1, FILE * f2) | 733 | static 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 | */ |
811 | static void change(char *file1, FILE * f1, char *file2, FILE * f2, int a, | 830 | static 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 | ||
853 | static void output(char *file1, FILE * f1, char *file2, FILE * f2) | 874 | static 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 | */ |
945 | static unsigned diffreg(char *ofile1, char *ofile2, int flags) | 969 | static 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. */ |
1099 | static int add_to_dirlist(const char *filename, | 1122 | static 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 | } |