diff options
Diffstat (limited to 'editors/diff.c')
-rw-r--r-- | editors/diff.c | 84 |
1 files changed, 49 insertions, 35 deletions
diff --git a/editors/diff.c b/editors/diff.c index e4d74abca..07594e8d8 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -227,10 +227,12 @@ struct cand { | |||
227 | 227 | ||
228 | static int search(const int *c, int k, int y, const struct cand *list) | 228 | static int search(const int *c, int k, int y, const struct cand *list) |
229 | { | 229 | { |
230 | int i, j; | ||
231 | |||
230 | if (list[c[k]].y < y) /* quick look for typical case */ | 232 | if (list[c[k]].y < y) /* quick look for typical case */ |
231 | return k + 1; | 233 | return k + 1; |
232 | 234 | ||
233 | for (int i = 0, j = k + 1;;) { | 235 | for (i = 0, j = k + 1;;) { |
234 | const int l = (i + j) >> 1; | 236 | const int l = (i + j) >> 1; |
235 | if (l > i) { | 237 | if (l > i) { |
236 | const int t = list[c[l]].y; | 238 | const int t = list[c[l]].y; |
@@ -265,11 +267,13 @@ static void stone(const int *a, int n, const int *b, int *J, int pref) | |||
265 | int clistlen = 100; | 267 | int clistlen = 100; |
266 | int k = 0; | 268 | int k = 0; |
267 | struct cand *clist = xzalloc(clistlen * sizeof(clist[0])); | 269 | struct cand *clist = xzalloc(clistlen * sizeof(clist[0])); |
270 | struct cand cand; | ||
271 | struct cand *q; | ||
268 | int *klist = xzalloc((n + 2) * sizeof(klist[0])); | 272 | int *klist = xzalloc((n + 2) * sizeof(klist[0])); |
269 | /*clist[0] = (struct cand){0}; - xzalloc did it */ | 273 | /*clist[0] = (struct cand){0}; - xzalloc did it */ |
270 | /*klist[0] = 0; */ | 274 | /*klist[0] = 0; */ |
271 | 275 | ||
272 | for (struct cand cand = {1}; cand.x <= n; cand.x++) { | 276 | for (cand.x = 1; cand.x <= n; cand.x++) { |
273 | int j = a[cand.x], oldl = 0; | 277 | int j = a[cand.x], oldl = 0; |
274 | unsigned numtries = 0; | 278 | unsigned numtries = 0; |
275 | if (j == 0) | 279 | if (j == 0) |
@@ -303,7 +307,7 @@ static void stone(const int *a, int n, const int *b, int *J, int pref) | |||
303 | } while ((cand.y = b[++j]) > 0 && numtries < bound); | 307 | } while ((cand.y = b[++j]) > 0 && numtries < bound); |
304 | } | 308 | } |
305 | /* Unravel */ | 309 | /* Unravel */ |
306 | for (struct cand *q = clist + klist[k]; q->y; q = clist + q->pred) | 310 | for (q = clist + klist[k]; q->y; q = clist + q->pred) |
307 | J[q->x + pref] = q->y + pref; | 311 | J[q->x + pref] = q->y + pref; |
308 | free(klist); | 312 | free(klist); |
309 | free(clist); | 313 | free(clist); |
@@ -348,10 +352,11 @@ static void equiv(struct line *a, int n, struct line *b, int m, int *c) | |||
348 | 352 | ||
349 | static void unsort(const struct line *f, int l, int *b) | 353 | static void unsort(const struct line *f, int l, int *b) |
350 | { | 354 | { |
355 | int i; | ||
351 | int *a = xmalloc((l + 1) * sizeof(a[0])); | 356 | int *a = xmalloc((l + 1) * sizeof(a[0])); |
352 | for (int i = 1; i <= l; i++) | 357 | for (i = 1; i <= l; i++) |
353 | a[f[i].serial] = f[i].value; | 358 | a[f[i].serial] = f[i].value; |
354 | for (int i = 1; i <= l; i++) | 359 | for (i = 1; i <= l; i++) |
355 | b[i] = a[i]; | 360 | b[i] = a[i]; |
356 | free(a); | 361 | free(a); |
357 | } | 362 | } |
@@ -370,12 +375,13 @@ static int line_compar(const void *a, const void *b) | |||
370 | 375 | ||
371 | static void fetch(FILE_and_pos_t *ft, const off_t *ix, int a, int b, int ch) | 376 | static void fetch(FILE_and_pos_t *ft, const off_t *ix, int a, int b, int ch) |
372 | { | 377 | { |
373 | for (int i = a; i <= b; i++) { | 378 | int i, j, col; |
379 | for (i = a; i <= b; i++) { | ||
374 | seek_ft(ft, ix[i - 1]); | 380 | seek_ft(ft, ix[i - 1]); |
375 | putchar(ch); | 381 | putchar(ch); |
376 | if (option_mask32 & FLAG(T)) | 382 | if (option_mask32 & FLAG(T)) |
377 | putchar('\t'); | 383 | putchar('\t'); |
378 | for (int j = 0, col = 0; j < ix[i] - ix[i - 1]; j++) { | 384 | for (j = 0, col = 0; j < ix[i] - ix[i - 1]; j++) { |
379 | int c = fgetc(ft->ft_fp); | 385 | int c = fgetc(ft->ft_fp); |
380 | if (c == EOF) { | 386 | if (c == EOF) { |
381 | printf("\n\\ No newline at end of file\n"); | 387 | printf("\n\\ No newline at end of file\n"); |
@@ -410,19 +416,20 @@ static NOINLINE int *create_J(FILE_and_pos_t ft[2], int nlen[2], off_t *ix[2]) | |||
410 | { | 416 | { |
411 | int *J, slen[2], *class, *member; | 417 | int *J, slen[2], *class, *member; |
412 | struct line *nfile[2], *sfile[2]; | 418 | struct line *nfile[2], *sfile[2]; |
413 | int pref = 0, suff = 0; | 419 | int pref = 0, suff = 0, i, j, delta; |
414 | 420 | ||
415 | /* Lines of both files are hashed, and in the process | 421 | /* Lines of both files are hashed, and in the process |
416 | * their offsets are stored in the array ix[fileno] | 422 | * their offsets are stored in the array ix[fileno] |
417 | * where fileno == 0 points to the old file, and | 423 | * where fileno == 0 points to the old file, and |
418 | * fileno == 1 points to the new one. | 424 | * fileno == 1 points to the new one. |
419 | */ | 425 | */ |
420 | for (int i = 0; i < 2; i++) { | 426 | for (i = 0; i < 2; i++) { |
421 | unsigned hash; | 427 | unsigned hash; |
422 | token_t tok; | 428 | token_t tok; |
423 | size_t sz = 100; | 429 | size_t sz = 100; |
424 | nfile[i] = xmalloc((sz + 3) * sizeof(nfile[i][0])); | 430 | nfile[i] = xmalloc((sz + 3) * sizeof(nfile[i][0])); |
425 | /* ft gets here without the correct position, cant use seek_ft */ | 431 | /* ft gets here without the correct position, cant use seek_ft */ |
432 | ft[i].ft_pos = 0; | ||
426 | fseeko(ft[i].ft_fp, 0, SEEK_SET); | 433 | fseeko(ft[i].ft_fp, 0, SEEK_SET); |
427 | 434 | ||
428 | nlen[i] = 0; | 435 | nlen[i] = 0; |
@@ -460,11 +467,11 @@ start: | |||
460 | nlen[i]--; | 467 | nlen[i]--; |
461 | /* Now we copy the line offsets into ix */ | 468 | /* Now we copy the line offsets into ix */ |
462 | ix[i] = xmalloc((nlen[i] + 2) * sizeof(ix[i][0])); | 469 | ix[i] = xmalloc((nlen[i] + 2) * sizeof(ix[i][0])); |
463 | for (int j = 0; j < nlen[i] + 1; j++) | 470 | for (j = 0; j < nlen[i] + 1; j++) |
464 | ix[i][j] = nfile[i][j].offset; | 471 | ix[i][j] = nfile[i][j].offset; |
465 | } | 472 | } |
466 | 473 | ||
467 | /* lenght of prefix and suffix is calculated */ | 474 | /* length of prefix and suffix is calculated */ |
468 | for (; pref < nlen[0] && pref < nlen[1] && | 475 | for (; pref < nlen[0] && pref < nlen[1] && |
469 | nfile[0][pref + 1].value == nfile[1][pref + 1].value; | 476 | nfile[0][pref + 1].value == nfile[1][pref + 1].value; |
470 | pref++); | 477 | pref++); |
@@ -475,10 +482,10 @@ start: | |||
475 | * the result being sorted and stored in sfile[fileno], | 482 | * the result being sorted and stored in sfile[fileno], |
476 | * and their sizes are stored in slen[fileno] | 483 | * and their sizes are stored in slen[fileno] |
477 | */ | 484 | */ |
478 | for (int j = 0; j < 2; j++) { | 485 | for (j = 0; j < 2; j++) { |
479 | sfile[j] = nfile[j] + pref; | 486 | sfile[j] = nfile[j] + pref; |
480 | slen[j] = nlen[j] - pref - suff; | 487 | slen[j] = nlen[j] - pref - suff; |
481 | for (int i = 0; i <= slen[j]; i++) | 488 | for (i = 0; i <= slen[j]; i++) |
482 | sfile[j][i].serial = i; | 489 | sfile[j][i].serial = i; |
483 | qsort(sfile[j] + 1, slen[j], sizeof(*sfile[j]), line_compar); | 490 | qsort(sfile[j] + 1, slen[j], sizeof(*sfile[j]), line_compar); |
484 | } | 491 | } |
@@ -494,7 +501,7 @@ start: | |||
494 | free(nfile[1]); | 501 | free(nfile[1]); |
495 | 502 | ||
496 | class = xmalloc((slen[0] + 1) * sizeof(class[0])); | 503 | class = xmalloc((slen[0] + 1) * sizeof(class[0])); |
497 | for (int i = 1; i <= slen[0]; i++) /* Unsorting */ | 504 | for (i = 1; i <= slen[0]; i++) /* Unsorting */ |
498 | class[sfile[0][i].serial] = sfile[0][i].value; | 505 | class[sfile[0][i].serial] = sfile[0][i].value; |
499 | free(nfile[0]); | 506 | free(nfile[0]); |
500 | #else | 507 | #else |
@@ -512,7 +519,7 @@ start: | |||
512 | * are initialized with 0 (no matches), so that function stone can | 519 | * are initialized with 0 (no matches), so that function stone can |
513 | * then assign them their right values | 520 | * then assign them their right values |
514 | */ | 521 | */ |
515 | for (int i = 0, delta = nlen[1] - nlen[0]; i <= nlen[0]; i++) | 522 | for (i = 0, delta = nlen[1] - nlen[0]; i <= nlen[0]; i++) |
516 | J[i] = i <= pref ? i : | 523 | J[i] = i <= pref ? i : |
517 | i > (nlen[0] - suff) ? (i + delta) : 0; | 524 | i > (nlen[0] - suff) ? (i + delta) : 0; |
518 | /* Here the magic is performed */ | 525 | /* Here the magic is performed */ |
@@ -526,14 +533,14 @@ start: | |||
526 | * which, due to limitations intrinsic to any hashing algorithm, | 533 | * which, due to limitations intrinsic to any hashing algorithm, |
527 | * are different but ended up confounded as the same | 534 | * are different but ended up confounded as the same |
528 | */ | 535 | */ |
529 | for (int i = 1; i <= nlen[0]; i++) { | 536 | for (i = 1; i <= nlen[0]; i++) { |
530 | if (!J[i]) | 537 | if (!J[i]) |
531 | continue; | 538 | continue; |
532 | 539 | ||
533 | seek_ft(&ft[0], ix[0][i - 1]); | 540 | seek_ft(&ft[0], ix[0][i - 1]); |
534 | seek_ft(&ft[1], ix[1][J[i] - 1]); | 541 | seek_ft(&ft[1], ix[1][J[i] - 1]); |
535 | 542 | ||
536 | for (int j = J[i]; i <= nlen[0] && J[i] == j; i++, j++) { | 543 | for (j = J[i]; i <= nlen[0] && J[i] == j; i++, j++) { |
537 | token_t tok0 = 0, tok1 = 0; | 544 | token_t tok0 = 0, tok1 = 0; |
538 | do { | 545 | do { |
539 | tok0 = read_token(&ft[0], tok0); | 546 | tok0 = read_token(&ft[0], tok0); |
@@ -555,13 +562,18 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
555 | { | 562 | { |
556 | int nlen[2]; | 563 | int nlen[2]; |
557 | off_t *ix[2]; | 564 | off_t *ix[2]; |
558 | FILE_and_pos_t ft[2] = { { fp[0] }, { fp[1] } }; | 565 | FILE_and_pos_t ft[2]; |
559 | int *J = create_J(ft, nlen, ix); | ||
560 | |||
561 | bool anychange = false; | ||
562 | typedef struct { int a, b; } vec_t[2]; | 566 | typedef struct { int a, b; } vec_t[2]; |
563 | vec_t *vec = NULL; | 567 | vec_t *vec = NULL; |
564 | int i = 1, idx = -1; | 568 | int i = 1, j, k, idx = -1; |
569 | bool anychange = false; | ||
570 | int *J; | ||
571 | |||
572 | ft[0].ft_fp = fp[0]; | ||
573 | ft[1].ft_fp = fp[1]; | ||
574 | /* note that ft[i].ft_pos is unintitalized, create_J() | ||
575 | * must not assume otherwise */ | ||
576 | J = create_J(ft, nlen, ix); | ||
565 | 577 | ||
566 | do { | 578 | do { |
567 | bool nonempty = false; | 579 | bool nonempty = false; |
@@ -596,8 +608,8 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
596 | break; | 608 | break; |
597 | } | 609 | } |
598 | 610 | ||
599 | for (int j = 0; j < 2; j++) | 611 | for (j = 0; j < 2; j++) |
600 | for (int k = v[j].a; k < v[j].b; k++) | 612 | for (k = v[j].a; k < v[j].b; k++) |
601 | nonempty |= (ix[j][k+1] - ix[j][k] != 1); | 613 | nonempty |= (ix[j][k+1] - ix[j][k] != 1); |
602 | 614 | ||
603 | vec = xrealloc_vector(vec, 6, ++idx); | 615 | vec = xrealloc_vector(vec, 6, ++idx); |
@@ -612,6 +624,7 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
612 | if (idx < 0 || ((option_mask32 & FLAG(B)) && !nonempty)) | 624 | if (idx < 0 || ((option_mask32 & FLAG(B)) && !nonempty)) |
613 | goto cont; | 625 | goto cont; |
614 | if (!(option_mask32 & FLAG(q))) { | 626 | if (!(option_mask32 & FLAG(q))) { |
627 | int lowa; | ||
615 | vec_t span, *cvp = vec; | 628 | vec_t span, *cvp = vec; |
616 | 629 | ||
617 | if (!anychange) { | 630 | if (!anychange) { |
@@ -621,7 +634,7 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
621 | } | 634 | } |
622 | 635 | ||
623 | printf("@@"); | 636 | printf("@@"); |
624 | for (int j = 0; j < 2; j++) { | 637 | for (j = 0; j < 2; j++) { |
625 | int a = span[j].a = MAX(1, (*cvp)[j].a - opt_U_context); | 638 | int a = span[j].a = MAX(1, (*cvp)[j].a - opt_U_context); |
626 | int b = span[j].b = MIN(nlen[j], vec[idx][j].b + opt_U_context); | 639 | int b = span[j].b = MIN(nlen[j], vec[idx][j].b + opt_U_context); |
627 | 640 | ||
@@ -635,12 +648,12 @@ static bool diff(FILE* fp[2], char *file[2]) | |||
635 | * Output changes in "unified" diff format--the old and new lines | 648 | * Output changes in "unified" diff format--the old and new lines |
636 | * are printed together. | 649 | * are printed together. |
637 | */ | 650 | */ |
638 | for (int lowa = span[0].a; ; lowa = (*cvp++)[0].b + 1) { | 651 | for (lowa = span[0].a; ; lowa = (*cvp++)[0].b + 1) { |
639 | bool end = cvp > &vec[idx]; | 652 | bool end = cvp > &vec[idx]; |
640 | fetch(&ft[0], ix[0], lowa, end ? span[0].b : (*cvp)[0].a - 1, ' '); | 653 | fetch(&ft[0], ix[0], lowa, end ? span[0].b : (*cvp)[0].a - 1, ' '); |
641 | if (end) | 654 | if (end) |
642 | break; | 655 | break; |
643 | for (int j = 0; j < 2; j++) | 656 | for (j = 0; j < 2; j++) |
644 | fetch(&ft[j], ix[j], (*cvp)[j].a, (*cvp)[j].b, j ? '+' : '-'); | 657 | fetch(&ft[j], ix[j], (*cvp)[j].a, (*cvp)[j].b, j ? '+' : '-'); |
645 | } | 658 | } |
646 | } | 659 | } |
@@ -660,9 +673,9 @@ static int diffreg(char *file[2]) | |||
660 | { | 673 | { |
661 | FILE *fp[2] = { stdin, stdin }; | 674 | FILE *fp[2] = { stdin, stdin }; |
662 | bool binary = false, differ = false; | 675 | bool binary = false, differ = false; |
663 | int status = STATUS_SAME; | 676 | int status = STATUS_SAME, i; |
664 | 677 | ||
665 | for (int i = 0; i < 2; i++) { | 678 | for (i = 0; i < 2; i++) { |
666 | int fd = open_or_warn_stdin(file[i]); | 679 | int fd = open_or_warn_stdin(file[i]); |
667 | if (fd == -1) | 680 | if (fd == -1) |
668 | goto out; | 681 | goto out; |
@@ -688,7 +701,7 @@ static int diffreg(char *file[2]) | |||
688 | const size_t sz = COMMON_BUFSIZE / 2; | 701 | const size_t sz = COMMON_BUFSIZE / 2; |
689 | char *const buf0 = bb_common_bufsiz1; | 702 | char *const buf0 = bb_common_bufsiz1; |
690 | char *const buf1 = buf0 + sz; | 703 | char *const buf1 = buf0 + sz; |
691 | int i, j; | 704 | int j, k; |
692 | i = fread(buf0, 1, sz, fp[0]); | 705 | i = fread(buf0, 1, sz, fp[0]); |
693 | j = fread(buf1, 1, sz, fp[1]); | 706 | j = fread(buf1, 1, sz, fp[1]); |
694 | if (i != j) { | 707 | if (i != j) { |
@@ -697,7 +710,7 @@ static int diffreg(char *file[2]) | |||
697 | } | 710 | } |
698 | if (i == 0) | 711 | if (i == 0) |
699 | break; | 712 | break; |
700 | for (int k = 0; k < i; k++) { | 713 | for (k = 0; k < i; k++) { |
701 | if (!buf0[k] || !buf1[k]) | 714 | if (!buf0[k] || !buf1[k]) |
702 | binary = true; | 715 | binary = true; |
703 | if (buf0[k] != buf1[k]) | 716 | if (buf0[k] != buf1[k]) |
@@ -771,9 +784,10 @@ static int FAST_FUNC skip_dir(const char *filename, | |||
771 | static void diffdir(char *p[2], const char *s_start) | 784 | static void diffdir(char *p[2], const char *s_start) |
772 | { | 785 | { |
773 | struct dlist list[2]; | 786 | struct dlist list[2]; |
787 | int i; | ||
774 | 788 | ||
775 | memset(&list, 0, sizeof(list)); | 789 | memset(&list, 0, sizeof(list)); |
776 | for (int i = 0; i < 2; i++) { | 790 | for (i = 0; i < 2; i++) { |
777 | /*list[i].s = list[i].e = 0; - memset did it */ | 791 | /*list[i].s = list[i].e = 0; - memset did it */ |
778 | /*list[i].dl = NULL; */ | 792 | /*list[i].dl = NULL; */ |
779 | 793 | ||
@@ -815,7 +829,7 @@ static void diffdir(char *p[2], const char *s_start) | |||
815 | else { | 829 | else { |
816 | char *fullpath[2], *path[2]; /* if -N */ | 830 | char *fullpath[2], *path[2]; /* if -N */ |
817 | 831 | ||
818 | for (int i = 0; i < 2; i++) { | 832 | for (i = 0; i < 2; i++) { |
819 | if (pos == 0 || i == k) { | 833 | if (pos == 0 || i == k) { |
820 | path[i] = fullpath[i] = concat_path_file(p[i], dp[i]); | 834 | path[i] = fullpath[i] = concat_path_file(p[i], dp[i]); |
821 | stat(fullpath[i], &stb[i]); | 835 | stat(fullpath[i], &stb[i]); |
@@ -883,7 +897,7 @@ static const char diff_longopts[] ALIGN1 = | |||
883 | int diff_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 897 | int diff_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
884 | int diff_main(int argc UNUSED_PARAM, char **argv) | 898 | int diff_main(int argc UNUSED_PARAM, char **argv) |
885 | { | 899 | { |
886 | int gotstdin = 0; | 900 | int gotstdin = 0, i; |
887 | char *file[2], *s_start = NULL; | 901 | char *file[2], *s_start = NULL; |
888 | llist_t *L_arg = NULL; | 902 | llist_t *L_arg = NULL; |
889 | 903 | ||
@@ -900,7 +914,7 @@ int diff_main(int argc UNUSED_PARAM, char **argv) | |||
900 | while (L_arg) | 914 | while (L_arg) |
901 | label[!!label[0]] = llist_pop(&L_arg); | 915 | label[!!label[0]] = llist_pop(&L_arg); |
902 | xfunc_error_retval = 2; | 916 | xfunc_error_retval = 2; |
903 | for (int i = 0; i < 2; i++) { | 917 | for (i = 0; i < 2; i++) { |
904 | file[i] = argv[i]; | 918 | file[i] = argv[i]; |
905 | /* Compat: "diff file name_which_doesnt_exist" exits with 2 */ | 919 | /* Compat: "diff file name_which_doesnt_exist" exits with 2 */ |
906 | if (LONE_DASH(file[i])) { | 920 | if (LONE_DASH(file[i])) { |