| @@ -507,1427 +507,1427 @@ diff3_run (argc, argv, out, callbacks_ar | | | @@ -507,1427 +507,1427 @@ diff3_run (argc, argv, out, callbacks_ar |
507 | if (opened_file) | | 507 | if (opened_file) |
508 | if (fclose (outfile) != 0) | | 508 | if (fclose (outfile) != 0) |
509 | perror_with_name ("close error on output file"); | | 509 | perror_with_name ("close error on output file"); |
510 | | | 510 | |
511 | return conflicts_found; | | 511 | return conflicts_found; |
512 | } | | 512 | } |
513 | | | 513 | |
514 | static int | | 514 | static int |
515 | try_help (reason) | | 515 | try_help (reason) |
516 | char const *reason; | | 516 | char const *reason; |
517 | { | | 517 | { |
518 | if (reason) | | 518 | if (reason) |
519 | diff_error ("%s", reason, 0); | | 519 | diff_error ("%s", reason, 0); |
520 | diff_error ("Try `%s --help' for more information.", diff_program_name, 0); | | 520 | diff_error ("Try `%s --help' for more information.", diff_program_name, 0); |
521 | return 2; | | 521 | return 2; |
522 | } | | 522 | } |
523 | | | 523 | |
524 | static void | | 524 | static void |
525 | check_output (stream) | | 525 | check_output (stream) |
526 | FILE *stream; | | 526 | FILE *stream; |
527 | { | | 527 | { |
528 | if (ferror (stream) || fflush (stream) != 0) | | 528 | if (ferror (stream) || fflush (stream) != 0) |
529 | diff3_fatal ("write error"); | | 529 | diff3_fatal ("write error"); |
530 | } | | 530 | } |
531 | | | 531 | |
532 | /* | | 532 | /* |
533 | * Explain, patiently and kindly, how to use this program. | | 533 | * Explain, patiently and kindly, how to use this program. |
534 | */ | | 534 | */ |
535 | static void | | 535 | static void |
536 | usage () | | 536 | usage () |
537 | { | | 537 | { |
538 | if (callbacks && callbacks->write_stdout) | | 538 | if (callbacks && callbacks->write_stdout) |
539 | { | | 539 | { |
540 | (*callbacks->write_stdout) ("Usage: "); | | 540 | (*callbacks->write_stdout) ("Usage: "); |
541 | (*callbacks->write_stdout) (diff_program_name); | | 541 | (*callbacks->write_stdout) (diff_program_name); |
542 | (*callbacks->write_stdout) (" [OPTION]... MYFILE OLDFILE YOURFILE\n\n"); | | 542 | (*callbacks->write_stdout) (" [OPTION]... MYFILE OLDFILE YOURFILE\n\n"); |
543 | | | 543 | |
544 | (*callbacks->write_stdout) ("\ | | 544 | (*callbacks->write_stdout) ("\ |
545 | -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\ | | 545 | -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\ |
546 | -E --show-overlap Output unmerged changes, bracketing conflicts.\n\ | | 546 | -E --show-overlap Output unmerged changes, bracketing conflicts.\n\ |
547 | -A --show-all Output all changes, bracketing conflicts.\n\ | | 547 | -A --show-all Output all changes, bracketing conflicts.\n\ |
548 | -x --overlap-only Output overlapping changes.\n\ | | 548 | -x --overlap-only Output overlapping changes.\n\ |
549 | -X Output overlapping changes, bracketing them.\n\ | | 549 | -X Output overlapping changes, bracketing them.\n\ |
550 | -3 --easy-only Output unmerged nonoverlapping changes.\n\n"); | | 550 | -3 --easy-only Output unmerged nonoverlapping changes.\n\n"); |
551 | (*callbacks->write_stdout) ("\ | | 551 | (*callbacks->write_stdout) ("\ |
552 | -m --merge Output merged file instead of ed script (default -A).\n\ | | 552 | -m --merge Output merged file instead of ed script (default -A).\n\ |
553 | -L LABEL --label=LABEL Use LABEL instead of file name.\n\ | | 553 | -L LABEL --label=LABEL Use LABEL instead of file name.\n\ |
554 | -i Append `w' and `q' commands to ed scripts.\n\ | | 554 | -i Append `w' and `q' commands to ed scripts.\n\ |
555 | -a --text Treat all files as text.\n\ | | 555 | -a --text Treat all files as text.\n\ |
556 | -T --initial-tab Make tabs line up by prepending a tab.\n\n"); | | 556 | -T --initial-tab Make tabs line up by prepending a tab.\n\n"); |
557 | (*callbacks->write_stdout) ("\ | | 557 | (*callbacks->write_stdout) ("\ |
558 | -v --version Output version info.\n\ | | 558 | -v --version Output version info.\n\ |
559 | --help Output this help.\n\n"); | | 559 | --help Output this help.\n\n"); |
560 | (*callbacks->write_stdout) ("If a FILE is `-', read standard input.\n"); | | 560 | (*callbacks->write_stdout) ("If a FILE is `-', read standard input.\n"); |
561 | } | | 561 | } |
562 | else | | 562 | else |
563 | { | | 563 | { |
564 | printf ("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n\n", diff_program_name); | | 564 | printf ("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n\n", diff_program_name); |
565 | | | 565 | |
566 | printf ("%s", "\ | | 566 | printf ("%s", "\ |
567 | -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\ | | 567 | -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\ |
568 | -E --show-overlap Output unmerged changes, bracketing conflicts.\n\ | | 568 | -E --show-overlap Output unmerged changes, bracketing conflicts.\n\ |
569 | -A --show-all Output all changes, bracketing conflicts.\n\ | | 569 | -A --show-all Output all changes, bracketing conflicts.\n\ |
570 | -x --overlap-only Output overlapping changes.\n\ | | 570 | -x --overlap-only Output overlapping changes.\n\ |
571 | -X Output overlapping changes, bracketing them.\n\ | | 571 | -X Output overlapping changes, bracketing them.\n\ |
572 | -3 --easy-only Output unmerged nonoverlapping changes.\n\n"); | | 572 | -3 --easy-only Output unmerged nonoverlapping changes.\n\n"); |
573 | printf ("%s", "\ | | 573 | printf ("%s", "\ |
574 | -m --merge Output merged file instead of ed script (default -A).\n\ | | 574 | -m --merge Output merged file instead of ed script (default -A).\n\ |
575 | -L LABEL --label=LABEL Use LABEL instead of file name.\n\ | | 575 | -L LABEL --label=LABEL Use LABEL instead of file name.\n\ |
576 | -i Append `w' and `q' commands to ed scripts.\n\ | | 576 | -i Append `w' and `q' commands to ed scripts.\n\ |
577 | -a --text Treat all files as text.\n\ | | 577 | -a --text Treat all files as text.\n\ |
578 | -T --initial-tab Make tabs line up by prepending a tab.\n\n"); | | 578 | -T --initial-tab Make tabs line up by prepending a tab.\n\n"); |
579 | printf ("%s", "\ | | 579 | printf ("%s", "\ |
580 | -v --version Output version info.\n\ | | 580 | -v --version Output version info.\n\ |
581 | --help Output this help.\n\n"); | | 581 | --help Output this help.\n\n"); |
582 | printf ("If a FILE is `-', read standard input.\n"); | | 582 | printf ("If a FILE is `-', read standard input.\n"); |
583 | } | | 583 | } |
584 | } | | 584 | } |
585 | | | 585 | |
586 | /* | | 586 | /* |
587 | * Routines that combine the two diffs together into one. The | | 587 | * Routines that combine the two diffs together into one. The |
588 | * algorithm used follows: | | 588 | * algorithm used follows: |
589 | * | | 589 | * |
590 | * File2 is shared in common between the two diffs. | | 590 | * File2 is shared in common between the two diffs. |
591 | * Diff02 is the diff between 0 and 2. | | 591 | * Diff02 is the diff between 0 and 2. |
592 | * Diff12 is the diff between 1 and 2. | | 592 | * Diff12 is the diff between 1 and 2. |
593 | * | | 593 | * |
594 | * 1) Find the range for the first block in File2. | | 594 | * 1) Find the range for the first block in File2. |
595 | * a) Take the lowest of the two ranges (in File2) in the two | | 595 | * a) Take the lowest of the two ranges (in File2) in the two |
596 | * current blocks (one from each diff) as being the low | | 596 | * current blocks (one from each diff) as being the low |
597 | * water mark. Assign the upper end of this block as | | 597 | * water mark. Assign the upper end of this block as |
598 | * being the high water mark and move the current block up | | 598 | * being the high water mark and move the current block up |
599 | * one. Mark the block just moved over as to be used. | | 599 | * one. Mark the block just moved over as to be used. |
600 | * b) Check the next block in the diff that the high water | | 600 | * b) Check the next block in the diff that the high water |
601 | * mark is *not* from. | | 601 | * mark is *not* from. |
602 | * | | 602 | * |
603 | * *If* the high water mark is above | | 603 | * *If* the high water mark is above |
604 | * the low end of the range in that block, | | 604 | * the low end of the range in that block, |
605 | * | | 605 | * |
606 | * mark that block as to be used and move the current | | 606 | * mark that block as to be used and move the current |
607 | * block up. Set the high water mark to the max of | | 607 | * block up. Set the high water mark to the max of |
608 | * the high end of this block and the current. Repeat b. | | 608 | * the high end of this block and the current. Repeat b. |
609 | * | | 609 | * |
610 | * 2) Find the corresponding ranges in File0 (from the blocks | | 610 | * 2) Find the corresponding ranges in File0 (from the blocks |
611 | * in diff02; line per line outside of diffs) and in File1. | | 611 | * in diff02; line per line outside of diffs) and in File1. |
612 | * Create a diff3_block, reserving space as indicated by the ranges. | | 612 | * Create a diff3_block, reserving space as indicated by the ranges. |
613 | * | | 613 | * |
614 | * 3) Copy all of the pointers for file2 in. At least for now, | | 614 | * 3) Copy all of the pointers for file2 in. At least for now, |
615 | * do memcmp's between corresponding strings in the two diffs. | | 615 | * do memcmp's between corresponding strings in the two diffs. |
616 | * | | 616 | * |
617 | * 4) Copy all of the pointers for file0 and 1 in. Get what you | | 617 | * 4) Copy all of the pointers for file0 and 1 in. Get what you |
618 | * need from file2 (when there isn't a diff block, it's | | 618 | * need from file2 (when there isn't a diff block, it's |
619 | * identical to file2 within the range between diff blocks). | | 619 | * identical to file2 within the range between diff blocks). |
620 | * | | 620 | * |
621 | * 5) If the diff blocks you used came from only one of the two | | 621 | * 5) If the diff blocks you used came from only one of the two |
622 | * strings of diffs, then that file (i.e. the one other than | | 622 | * strings of diffs, then that file (i.e. the one other than |
623 | * the common file in that diff) is the odd person out. If you used | | 623 | * the common file in that diff) is the odd person out. If you used |
624 | * diff blocks from both sets, check to see if files 0 and 1 match: | | 624 | * diff blocks from both sets, check to see if files 0 and 1 match: |
625 | * | | 625 | * |
626 | * Same number of lines? If so, do a set of memcmp's (if a | | 626 | * Same number of lines? If so, do a set of memcmp's (if a |
627 | * memcmp matches; copy the pointer over; it'll be easier later | | 627 | * memcmp matches; copy the pointer over; it'll be easier later |
628 | * if you have to do any compares). If they match, 0 & 1 are | | 628 | * if you have to do any compares). If they match, 0 & 1 are |
629 | * the same. If not, all three different. | | 629 | * the same. If not, all three different. |
630 | * | | 630 | * |
631 | * Then you do it again, until you run out of blocks. | | 631 | * Then you do it again, until you run out of blocks. |
632 | * | | 632 | * |
633 | */ | | 633 | */ |
634 | | | 634 | |
635 | /* | | 635 | /* |
636 | * This routine makes a three way diff (chain of diff3_block's) from two | | 636 | * This routine makes a three way diff (chain of diff3_block's) from two |
637 | * two way diffs (chains of diff_block's). It is assumed that each of | | 637 | * two way diffs (chains of diff_block's). It is assumed that each of |
638 | * the two diffs passed are onto the same file (i.e. that each of the | | 638 | * the two diffs passed are onto the same file (i.e. that each of the |
639 | * diffs were made "to" the same file). The three way diff pointer | | 639 | * diffs were made "to" the same file). The three way diff pointer |
640 | * returned will have numbering FILE0--the other file in diff02, | | 640 | * returned will have numbering FILE0--the other file in diff02, |
641 | * FILE1--the other file in diff12, and FILEC--the common file. | | 641 | * FILE1--the other file in diff12, and FILEC--the common file. |
642 | */ | | 642 | */ |
643 | static struct diff3_block * | | 643 | static struct diff3_block * |
644 | make_3way_diff (thread0, thread1) | | 644 | make_3way_diff (thread0, thread1) |
645 | struct diff_block *thread0, *thread1; | | 645 | struct diff_block *thread0, *thread1; |
646 | { | | 646 | { |
647 | /* | | 647 | /* |
648 | * This routine works on the two diffs passed to it as threads. | | 648 | * This routine works on the two diffs passed to it as threads. |
649 | * Thread number 0 is diff02, thread number 1 is diff12. The USING | | 649 | * Thread number 0 is diff02, thread number 1 is diff12. The USING |
650 | * array is set to the base of the list of blocks to be used to | | 650 | * array is set to the base of the list of blocks to be used to |
651 | * construct each block of the three way diff; if no blocks from a | | 651 | * construct each block of the three way diff; if no blocks from a |
652 | * particular thread are to be used, that element of the using array | | 652 | * particular thread are to be used, that element of the using array |
653 | * is set to 0. The elements LAST_USING array are set to the last | | 653 | * is set to 0. The elements LAST_USING array are set to the last |
654 | * elements on each of the using lists. | | 654 | * elements on each of the using lists. |
655 | * | | 655 | * |
656 | * The HIGH_WATER_MARK is set to the highest line number in the common file | | 656 | * The HIGH_WATER_MARK is set to the highest line number in the common file |
657 | * described in any of the diffs in either of the USING lists. The | | 657 | * described in any of the diffs in either of the USING lists. The |
658 | * HIGH_WATER_THREAD names the thread. Similarly the BASE_WATER_MARK | | 658 | * HIGH_WATER_THREAD names the thread. Similarly the BASE_WATER_MARK |
659 | * and BASE_WATER_THREAD describe the lowest line number in the common file | | 659 | * and BASE_WATER_THREAD describe the lowest line number in the common file |
660 | * described in any of the diffs in either of the USING lists. The | | 660 | * described in any of the diffs in either of the USING lists. The |
661 | * HIGH_WATER_DIFF is the diff from which the HIGH_WATER_MARK was | | 661 | * HIGH_WATER_DIFF is the diff from which the HIGH_WATER_MARK was |
662 | * taken. | | 662 | * taken. |
663 | * | | 663 | * |
664 | * The HIGH_WATER_DIFF should always be equal to LAST_USING | | 664 | * The HIGH_WATER_DIFF should always be equal to LAST_USING |
665 | * [HIGH_WATER_THREAD]. The OTHER_DIFF is the next diff to check for | | 665 | * [HIGH_WATER_THREAD]. The OTHER_DIFF is the next diff to check for |
666 | * higher water, and should always be equal to | | 666 | * higher water, and should always be equal to |
667 | * CURRENT[HIGH_WATER_THREAD ^ 0x1]. The OTHER_THREAD is the thread | | 667 | * CURRENT[HIGH_WATER_THREAD ^ 0x1]. The OTHER_THREAD is the thread |
668 | * in which the OTHER_DIFF is, and hence should always be equal to | | 668 | * in which the OTHER_DIFF is, and hence should always be equal to |
669 | * HIGH_WATER_THREAD ^ 0x1. | | 669 | * HIGH_WATER_THREAD ^ 0x1. |
670 | * | | 670 | * |
671 | * The variable LAST_DIFF is kept set to the last diff block produced | | 671 | * The variable LAST_DIFF is kept set to the last diff block produced |
672 | * by this routine, for line correspondence purposes between that diff | | 672 | * by this routine, for line correspondence purposes between that diff |
673 | * and the one currently being worked on. It is initialized to | | 673 | * and the one currently being worked on. It is initialized to |
674 | * ZERO_DIFF before any blocks have been created. | | 674 | * ZERO_DIFF before any blocks have been created. |
675 | */ | | 675 | */ |
676 | | | 676 | |
677 | struct diff_block | | 677 | struct diff_block |
678 | *using[2], | | 678 | *using[2], |
679 | *last_using[2], | | 679 | *last_using[2], |
680 | *current[2]; | | 680 | *current[2]; |
681 | | | 681 | |
682 | int | | 682 | int |
683 | high_water_mark; | | 683 | high_water_mark; |
684 | | | 684 | |
685 | int | | 685 | int |
686 | high_water_thread, | | 686 | high_water_thread, |
687 | base_water_thread, | | 687 | base_water_thread, |
688 | other_thread; | | 688 | other_thread; |
689 | | | 689 | |
690 | struct diff_block | | 690 | struct diff_block |
691 | *high_water_diff, | | 691 | *high_water_diff, |
692 | *other_diff; | | 692 | *other_diff; |
693 | | | 693 | |
694 | struct diff3_block | | 694 | struct diff3_block |
695 | *result, | | 695 | *result, |
696 | *tmpblock, | | 696 | *tmpblock, |
697 | **result_end; | | 697 | **result_end; |
698 | | | 698 | |
699 | struct diff3_block const *last_diff3; | | 699 | struct diff3_block const *last_diff3; |
700 | | | 700 | |
701 | static struct diff3_block const zero_diff3 = { 0 }; | | 701 | static struct diff3_block const zero_diff3 = { 0 }; |
702 | | | 702 | |
703 | /* Initialization */ | | 703 | /* Initialization */ |
704 | result = 0; | | 704 | result = 0; |
705 | result_end = &result; | | 705 | result_end = &result; |
706 | current[0] = thread0; current[1] = thread1; | | 706 | current[0] = thread0; current[1] = thread1; |
707 | last_diff3 = &zero_diff3; | | 707 | last_diff3 = &zero_diff3; |
708 | | | 708 | |
709 | /* Sniff up the threads until we reach the end */ | | 709 | /* Sniff up the threads until we reach the end */ |
710 | | | 710 | |
711 | while (current[0] || current[1]) | | 711 | while (current[0] || current[1]) |
712 | { | | 712 | { |
713 | using[0] = using[1] = last_using[0] = last_using[1] = 0; | | 713 | using[0] = using[1] = last_using[0] = last_using[1] = 0; |
714 | | | 714 | |
715 | /* Setup low and high water threads, diffs, and marks. */ | | 715 | /* Setup low and high water threads, diffs, and marks. */ |
716 | if (!current[0]) | | 716 | if (!current[0]) |
717 | base_water_thread = 1; | | 717 | base_water_thread = 1; |
718 | else if (!current[1]) | | 718 | else if (!current[1]) |
719 | base_water_thread = 0; | | 719 | base_water_thread = 0; |
720 | else | | 720 | else |
721 | base_water_thread = | | 721 | base_water_thread = |
722 | (D_LOWLINE (current[0], FC) > D_LOWLINE (current[1], FC)); | | 722 | (D_LOWLINE (current[0], FC) > D_LOWLINE (current[1], FC)); |
723 | | | 723 | |
724 | high_water_thread = base_water_thread; | | 724 | high_water_thread = base_water_thread; |
725 | | | 725 | |
726 | high_water_diff = current[high_water_thread]; | | 726 | high_water_diff = current[high_water_thread]; |
727 | | | 727 | |
728 | #if 0 | | 728 | #if 0 |
729 | /* low and high waters start off same diff */ | | 729 | /* low and high waters start off same diff */ |
730 | base_water_mark = D_LOWLINE (high_water_diff, FC); | | 730 | base_water_mark = D_LOWLINE (high_water_diff, FC); |
731 | #endif | | 731 | #endif |
732 | | | 732 | |
733 | high_water_mark = D_HIGHLINE (high_water_diff, FC); | | 733 | high_water_mark = D_HIGHLINE (high_water_diff, FC); |
734 | | | 734 | |
735 | /* Make the diff you just got info from into the using class */ | | 735 | /* Make the diff you just got info from into the using class */ |
736 | using[high_water_thread] | | 736 | using[high_water_thread] |
737 | = last_using[high_water_thread] | | 737 | = last_using[high_water_thread] |
738 | = high_water_diff; | | 738 | = high_water_diff; |
739 | current[high_water_thread] = high_water_diff->next; | | 739 | current[high_water_thread] = high_water_diff->next; |
740 | last_using[high_water_thread]->next = 0; | | 740 | last_using[high_water_thread]->next = 0; |
741 | | | 741 | |
742 | /* And mark the other diff */ | | 742 | /* And mark the other diff */ |
743 | other_thread = high_water_thread ^ 0x1; | | 743 | other_thread = high_water_thread ^ 0x1; |
744 | other_diff = current[other_thread]; | | 744 | other_diff = current[other_thread]; |
745 | | | 745 | |
746 | /* Shuffle up the ladder, checking the other diff to see if it | | 746 | /* Shuffle up the ladder, checking the other diff to see if it |
747 | needs to be incorporated. */ | | 747 | needs to be incorporated. */ |
748 | while (other_diff | | 748 | while (other_diff |
749 | && D_LOWLINE (other_diff, FC) <= high_water_mark + 1) | | 749 | && D_LOWLINE (other_diff, FC) <= high_water_mark + 1) |
750 | { | | 750 | { |
751 | | | 751 | |
752 | /* Incorporate this diff into the using list. Note that | | 752 | /* Incorporate this diff into the using list. Note that |
753 | this doesn't take it off the current list */ | | 753 | this doesn't take it off the current list */ |
754 | if (using[other_thread]) | | 754 | if (using[other_thread]) |
755 | last_using[other_thread]->next = other_diff; | | 755 | last_using[other_thread]->next = other_diff; |
756 | else | | 756 | else |
757 | using[other_thread] = other_diff; | | 757 | using[other_thread] = other_diff; |
758 | last_using[other_thread] = other_diff; | | 758 | last_using[other_thread] = other_diff; |
759 | | | 759 | |
760 | /* Take it off the current list. Note that this following | | 760 | /* Take it off the current list. Note that this following |
761 | code assumes that other_diff enters it equal to | | 761 | code assumes that other_diff enters it equal to |
762 | current[high_water_thread ^ 0x1] */ | | 762 | current[high_water_thread ^ 0x1] */ |
763 | current[other_thread] = current[other_thread]->next; | | 763 | current[other_thread] = current[other_thread]->next; |
764 | other_diff->next = 0; | | 764 | other_diff->next = 0; |
765 | | | 765 | |
766 | /* Set the high_water stuff | | 766 | /* Set the high_water stuff |
767 | If this comparison is equal, then this is the last pass | | 767 | If this comparison is equal, then this is the last pass |
768 | through this loop; since diff blocks within a given | | 768 | through this loop; since diff blocks within a given |
769 | thread cannot overlap, the high_water_mark will be | | 769 | thread cannot overlap, the high_water_mark will be |
770 | *below* the range_start of either of the next diffs. */ | | 770 | *below* the range_start of either of the next diffs. */ |
771 | | | 771 | |
772 | if (high_water_mark < D_HIGHLINE (other_diff, FC)) | | 772 | if (high_water_mark < D_HIGHLINE (other_diff, FC)) |
773 | { | | 773 | { |
774 | high_water_thread ^= 1; | | 774 | high_water_thread ^= 1; |
775 | high_water_diff = other_diff; | | 775 | high_water_diff = other_diff; |
776 | high_water_mark = D_HIGHLINE (other_diff, FC); | | 776 | high_water_mark = D_HIGHLINE (other_diff, FC); |
777 | } | | 777 | } |
778 | | | 778 | |
779 | /* Set the other diff */ | | 779 | /* Set the other diff */ |
780 | other_thread = high_water_thread ^ 0x1; | | 780 | other_thread = high_water_thread ^ 0x1; |
781 | other_diff = current[other_thread]; | | 781 | other_diff = current[other_thread]; |
782 | } | | 782 | } |
783 | | | 783 | |
784 | /* The using lists contain a list of all of the blocks to be | | 784 | /* The using lists contain a list of all of the blocks to be |
785 | included in this diff3_block. Create it. */ | | 785 | included in this diff3_block. Create it. */ |
786 | | | 786 | |
787 | tmpblock = using_to_diff3_block (using, last_using, | | 787 | tmpblock = using_to_diff3_block (using, last_using, |
788 | base_water_thread, high_water_thread, | | 788 | base_water_thread, high_water_thread, |
789 | last_diff3); | | 789 | last_diff3); |
790 | free_diff_blocks(using[0]); | | 790 | free_diff_blocks(using[0]); |
791 | free_diff_blocks(using[1]); | | 791 | free_diff_blocks(using[1]); |
792 | | | 792 | |
793 | if (!tmpblock) | | 793 | if (!tmpblock) |
794 | diff3_fatal ("internal error: screwup in format of diff blocks"); | | 794 | diff3_fatal ("internal error: screwup in format of diff blocks"); |
795 | | | 795 | |
796 | /* Put it on the list. */ | | 796 | /* Put it on the list. */ |
797 | *result_end = tmpblock; | | 797 | *result_end = tmpblock; |
798 | result_end = &tmpblock->next; | | 798 | result_end = &tmpblock->next; |
799 | | | 799 | |
800 | /* Set up corresponding lines correctly. */ | | 800 | /* Set up corresponding lines correctly. */ |
801 | last_diff3 = tmpblock; | | 801 | last_diff3 = tmpblock; |
802 | } | | 802 | } |
803 | return result; | | 803 | return result; |
804 | } | | 804 | } |
805 | | | 805 | |
806 | /* | | 806 | /* |
807 | * using_to_diff3_block: | | 807 | * using_to_diff3_block: |
808 | * This routine takes two lists of blocks (from two separate diff | | 808 | * This routine takes two lists of blocks (from two separate diff |
809 | * threads) and puts them together into one diff3 block. | | 809 | * threads) and puts them together into one diff3 block. |
810 | * It then returns a pointer to this diff3 block or 0 for failure. | | 810 | * It then returns a pointer to this diff3 block or 0 for failure. |
811 | * | | 811 | * |
812 | * All arguments besides using are for the convenience of the routine; | | 812 | * All arguments besides using are for the convenience of the routine; |
813 | * they could be derived from the using array. | | 813 | * they could be derived from the using array. |
814 | * LAST_USING is a pair of pointers to the last blocks in the using | | 814 | * LAST_USING is a pair of pointers to the last blocks in the using |
815 | * structure. | | 815 | * structure. |
816 | * LOW_THREAD and HIGH_THREAD tell which threads contain the lowest | | 816 | * LOW_THREAD and HIGH_THREAD tell which threads contain the lowest |
817 | * and highest line numbers for File0. | | 817 | * and highest line numbers for File0. |
818 | * last_diff3 contains the last diff produced in the calling routine. | | 818 | * last_diff3 contains the last diff produced in the calling routine. |
819 | * This is used for lines mappings which would still be identical to | | 819 | * This is used for lines mappings which would still be identical to |
820 | * the state that diff ended in. | | 820 | * the state that diff ended in. |
821 | * | | 821 | * |
822 | * A distinction should be made in this routine between the two diffs | | 822 | * A distinction should be made in this routine between the two diffs |
823 | * that are part of a normal two diff block, and the three diffs that | | 823 | * that are part of a normal two diff block, and the three diffs that |
824 | * are part of a diff3_block. | | 824 | * are part of a diff3_block. |
825 | */ | | 825 | */ |
826 | static struct diff3_block * | | 826 | static struct diff3_block * |
827 | using_to_diff3_block (using, last_using, low_thread, high_thread, last_diff3) | | 827 | using_to_diff3_block (using, last_using, low_thread, high_thread, last_diff3) |
828 | struct diff_block | | 828 | struct diff_block |
829 | *using[2], | | 829 | *using[2], |
830 | *last_using[2]; | | 830 | *last_using[2]; |
831 | int low_thread, high_thread; | | 831 | int low_thread, high_thread; |
832 | struct diff3_block const *last_diff3; | | 832 | struct diff3_block const *last_diff3; |
833 | { | | 833 | { |
834 | int low[2], high[2]; | | 834 | int low[2], high[2]; |
835 | struct diff3_block *result; | | 835 | struct diff3_block *result; |
836 | struct diff_block *ptr; | | 836 | struct diff_block *ptr; |
837 | int d, i; | | 837 | int d, i; |
838 | | | 838 | |
839 | /* Find the range in the common file. */ | | 839 | /* Find the range in the common file. */ |
840 | int lowc = D_LOWLINE (using[low_thread], FC); | | 840 | int lowc = D_LOWLINE (using[low_thread], FC); |
841 | int highc = D_HIGHLINE (last_using[high_thread], FC); | | 841 | int highc = D_HIGHLINE (last_using[high_thread], FC); |
842 | | | 842 | |
843 | /* Find the ranges in the other files. | | 843 | /* Find the ranges in the other files. |
844 | If using[d] is null, that means that the file to which that diff | | 844 | If using[d] is null, that means that the file to which that diff |
845 | refers is equivalent to the common file over this range. */ | | 845 | refers is equivalent to the common file over this range. */ |
846 | | | 846 | |
847 | for (d = 0; d < 2; d++) | | 847 | for (d = 0; d < 2; d++) |
848 | if (using[d]) | | 848 | if (using[d]) |
849 | { | | 849 | { |
850 | low[d] = D_LOW_MAPLINE (using[d], FC, FO, lowc); | | 850 | low[d] = D_LOW_MAPLINE (using[d], FC, FO, lowc); |
851 | high[d] = D_HIGH_MAPLINE (last_using[d], FC, FO, highc); | | 851 | high[d] = D_HIGH_MAPLINE (last_using[d], FC, FO, highc); |
852 | } | | 852 | } |
853 | else | | 853 | else |
854 | { | | 854 | { |
855 | low[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, lowc); | | 855 | low[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, lowc); |
856 | high[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, highc); | | 856 | high[d] = D_HIGH_MAPLINE (last_diff3, FILEC, FILE0 + d, highc); |
857 | } | | 857 | } |
858 | | | 858 | |
859 | /* Create a block with the appropriate sizes */ | | 859 | /* Create a block with the appropriate sizes */ |
860 | result = create_diff3_block (low[0], high[0], low[1], high[1], lowc, highc); | | 860 | result = create_diff3_block (low[0], high[0], low[1], high[1], lowc, highc); |
861 | | | 861 | |
862 | /* Copy information for the common file. | | 862 | /* Copy information for the common file. |
863 | Return with a zero if any of the compares failed. */ | | 863 | Return with a zero if any of the compares failed. */ |
864 | | | 864 | |
865 | for (d = 0; d < 2; d++) | | 865 | for (d = 0; d < 2; d++) |
866 | for (ptr = using[d]; ptr; ptr = D_NEXT (ptr)) | | 866 | for (ptr = using[d]; ptr; ptr = D_NEXT (ptr)) |
867 | { | | 867 | { |
868 | int result_offset = D_LOWLINE (ptr, FC) - lowc; | | 868 | int result_offset = D_LOWLINE (ptr, FC) - lowc; |
869 | | | 869 | |
870 | if (!copy_stringlist (D_LINEARRAY (ptr, FC), | | 870 | if (!copy_stringlist (D_LINEARRAY (ptr, FC), |
871 | D_LENARRAY (ptr, FC), | | 871 | D_LENARRAY (ptr, FC), |
872 | D_LINEARRAY (result, FILEC) + result_offset, | | 872 | D_LINEARRAY (result, FILEC) + result_offset, |
873 | D_LENARRAY (result, FILEC) + result_offset, | | 873 | D_LENARRAY (result, FILEC) + result_offset, |
874 | D_NUMLINES (ptr, FC))) | | 874 | D_NUMLINES (ptr, FC))) |
875 | return 0; | | 875 | return 0; |
876 | } | | 876 | } |
877 | | | 877 | |
878 | /* Copy information for file d. First deal with anything that might be | | 878 | /* Copy information for file d. First deal with anything that might be |
879 | before the first diff. */ | | 879 | before the first diff. */ |
880 | | | 880 | |
881 | for (d = 0; d < 2; d++) | | 881 | for (d = 0; d < 2; d++) |
882 | { | | 882 | { |
883 | struct diff_block *u = using[d]; | | 883 | struct diff_block *u = using[d]; |
884 | int lo = low[d], hi = high[d]; | | 884 | int lo = low[d], hi = high[d]; |
885 | | | 885 | |
886 | for (i = 0; | | 886 | for (i = 0; |
887 | i + lo < (u ? D_LOWLINE (u, FO) : hi + 1); | | 887 | i + lo < (u ? D_LOWLINE (u, FO) : hi + 1); |
888 | i++) | | 888 | i++) |
889 | { | | 889 | { |
890 | D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, i); | | 890 | D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, i); |
891 | D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, i); | | 891 | D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, i); |
892 | } | | 892 | } |
893 | | | 893 | |
894 | for (ptr = u; ptr; ptr = D_NEXT (ptr)) | | 894 | for (ptr = u; ptr; ptr = D_NEXT (ptr)) |
895 | { | | 895 | { |
896 | int result_offset = D_LOWLINE (ptr, FO) - lo; | | 896 | int result_offset = D_LOWLINE (ptr, FO) - lo; |
897 | int linec; | | 897 | int linec; |
898 | | | 898 | |
899 | if (!copy_stringlist (D_LINEARRAY (ptr, FO), | | 899 | if (!copy_stringlist (D_LINEARRAY (ptr, FO), |
900 | D_LENARRAY (ptr, FO), | | 900 | D_LENARRAY (ptr, FO), |
901 | D_LINEARRAY (result, FILE0 + d) + result_offset, | | 901 | D_LINEARRAY (result, FILE0 + d) + result_offset, |
902 | D_LENARRAY (result, FILE0 + d) + result_offset, | | 902 | D_LENARRAY (result, FILE0 + d) + result_offset, |
903 | D_NUMLINES (ptr, FO))) | | 903 | D_NUMLINES (ptr, FO))) |
904 | return 0; | | 904 | return 0; |
905 | | | 905 | |
906 | /* Catch the lines between here and the next diff */ | | 906 | /* Catch the lines between here and the next diff */ |
907 | linec = D_HIGHLINE (ptr, FC) + 1 - lowc; | | 907 | linec = D_HIGHLINE (ptr, FC) + 1 - lowc; |
908 | for (i = D_HIGHLINE (ptr, FO) + 1 - lo; | | 908 | for (i = D_HIGHLINE (ptr, FO) + 1 - lo; |
909 | i < (D_NEXT (ptr) ? D_LOWLINE (D_NEXT (ptr), FO) : hi + 1) - lo; | | 909 | i < (D_NEXT (ptr) ? D_LOWLINE (D_NEXT (ptr), FO) : hi + 1) - lo; |
910 | i++) | | 910 | i++) |
911 | { | | 911 | { |
912 | D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, linec); | | 912 | D_RELNUM (result, FILE0 + d, i) = D_RELNUM (result, FILEC, linec); |
913 | D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, linec); | | 913 | D_RELLEN (result, FILE0 + d, i) = D_RELLEN (result, FILEC, linec); |
914 | linec++; | | 914 | linec++; |
915 | } | | 915 | } |
916 | } | | 916 | } |
917 | } | | 917 | } |
918 | | | 918 | |
919 | /* Set correspond */ | | 919 | /* Set correspond */ |
920 | if (!using[0]) | | 920 | if (!using[0]) |
921 | D3_TYPE (result) = DIFF_2ND; | | 921 | D3_TYPE (result) = DIFF_2ND; |
922 | else if (!using[1]) | | 922 | else if (!using[1]) |
923 | D3_TYPE (result) = DIFF_1ST; | | 923 | D3_TYPE (result) = DIFF_1ST; |
924 | else | | 924 | else |
925 | { | | 925 | { |
926 | int nl0 = D_NUMLINES (result, FILE0); | | 926 | int nl0 = D_NUMLINES (result, FILE0); |
927 | int nl1 = D_NUMLINES (result, FILE1); | | 927 | int nl1 = D_NUMLINES (result, FILE1); |
928 | | | 928 | |
929 | if (nl0 != nl1 | | 929 | if (nl0 != nl1 |
930 | || !compare_line_list (D_LINEARRAY (result, FILE0), | | 930 | || !compare_line_list (D_LINEARRAY (result, FILE0), |
931 | D_LENARRAY (result, FILE0), | | 931 | D_LENARRAY (result, FILE0), |
932 | D_LINEARRAY (result, FILE1), | | 932 | D_LINEARRAY (result, FILE1), |
933 | D_LENARRAY (result, FILE1), | | 933 | D_LENARRAY (result, FILE1), |
934 | nl0)) | | 934 | nl0)) |
935 | D3_TYPE (result) = DIFF_ALL; | | 935 | D3_TYPE (result) = DIFF_ALL; |
936 | else | | 936 | else |
937 | D3_TYPE (result) = DIFF_3RD; | | 937 | D3_TYPE (result) = DIFF_3RD; |
938 | } | | 938 | } |
939 | | | 939 | |
940 | return result; | | 940 | return result; |
941 | } | | 941 | } |
942 | | | 942 | |
943 | /* | | 943 | /* |
944 | * This routine copies pointers from a list of strings to a different list | | 944 | * This routine copies pointers from a list of strings to a different list |
945 | * of strings. If a spot in the second list is already filled, it | | 945 | * of strings. If a spot in the second list is already filled, it |
946 | * makes sure that it is filled with the same string; if not it | | 946 | * makes sure that it is filled with the same string; if not it |
947 | * returns 0, the copy incomplete. | | 947 | * returns 0, the copy incomplete. |
948 | * Upon successful completion of the copy, it returns 1. | | 948 | * Upon successful completion of the copy, it returns 1. |
949 | */ | | 949 | */ |
950 | static int | | 950 | static int |
951 | copy_stringlist (fromptrs, fromlengths, toptrs, tolengths, copynum) | | 951 | copy_stringlist (fromptrs, fromlengths, toptrs, tolengths, copynum) |
952 | char * const fromptrs[]; | | 952 | char * const fromptrs[]; |
953 | char *toptrs[]; | | 953 | char *toptrs[]; |
954 | size_t const fromlengths[]; | | 954 | size_t const fromlengths[]; |
955 | size_t tolengths[]; | | 955 | size_t tolengths[]; |
956 | int copynum; | | 956 | int copynum; |
957 | { | | 957 | { |
958 | register char * const *f = fromptrs; | | 958 | register char * const *f = fromptrs; |
959 | register char **t = toptrs; | | 959 | register char **t = toptrs; |
960 | register size_t const *fl = fromlengths; | | 960 | register size_t const *fl = fromlengths; |
961 | register size_t *tl = tolengths; | | 961 | register size_t *tl = tolengths; |
962 | | | 962 | |
963 | while (copynum--) | | 963 | while (copynum--) |
964 | { | | 964 | { |
965 | if (*t) | | 965 | if (*t) |
966 | { if (*fl != *tl || memcmp (*f, *t, *fl)) return 0; } | | 966 | { if (*fl != *tl || memcmp (*f, *t, *fl)) return 0; } |
967 | else | | 967 | else |
968 | { *t = *f ; *tl = *fl; } | | 968 | { *t = *f ; *tl = *fl; } |
969 | | | 969 | |
970 | t++; f++; tl++; fl++; | | 970 | t++; f++; tl++; fl++; |
971 | } | | 971 | } |
972 | return 1; | | 972 | return 1; |
973 | } | | 973 | } |
974 | | | 974 | |
975 | /* | | 975 | /* |
976 | * Create a diff3_block, with ranges as specified in the arguments. | | 976 | * Create a diff3_block, with ranges as specified in the arguments. |
977 | * Allocate the arrays for the various pointers (and zero them) based | | 977 | * Allocate the arrays for the various pointers (and zero them) based |
978 | * on the arguments passed. Return the block as a result. | | 978 | * on the arguments passed. Return the block as a result. |
979 | */ | | 979 | */ |
980 | static struct diff3_block * | | 980 | static struct diff3_block * |
981 | create_diff3_block (low0, high0, low1, high1, low2, high2) | | 981 | create_diff3_block (low0, high0, low1, high1, low2, high2) |
982 | register int low0, high0, low1, high1, low2, high2; | | 982 | register int low0, high0, low1, high1, low2, high2; |
983 | { | | 983 | { |
984 | struct diff3_block *result = ALLOCATE (1, struct diff3_block); | | 984 | struct diff3_block *result = ALLOCATE (1, struct diff3_block); |
985 | int numlines; | | 985 | int numlines; |
986 | | | 986 | |
987 | D3_TYPE (result) = ERROR; | | 987 | D3_TYPE (result) = ERROR; |
988 | D_NEXT (result) = 0; | | 988 | D_NEXT (result) = 0; |
989 | | | 989 | |
990 | /* Assign ranges */ | | 990 | /* Assign ranges */ |
991 | D_LOWLINE (result, FILE0) = low0; | | 991 | D_LOWLINE (result, FILE0) = low0; |
992 | D_HIGHLINE (result, FILE0) = high0; | | 992 | D_HIGHLINE (result, FILE0) = high0; |
993 | D_LOWLINE (result, FILE1) = low1; | | 993 | D_LOWLINE (result, FILE1) = low1; |
994 | D_HIGHLINE (result, FILE1) = high1; | | 994 | D_HIGHLINE (result, FILE1) = high1; |
995 | D_LOWLINE (result, FILE2) = low2; | | 995 | D_LOWLINE (result, FILE2) = low2; |
996 | D_HIGHLINE (result, FILE2) = high2; | | 996 | D_HIGHLINE (result, FILE2) = high2; |
997 | | | 997 | |
998 | /* Allocate and zero space */ | | 998 | /* Allocate and zero space */ |
999 | numlines = D_NUMLINES (result, FILE0); | | 999 | numlines = D_NUMLINES (result, FILE0); |
1000 | if (numlines) | | 1000 | if (numlines) |
1001 | { | | 1001 | { |
1002 | D_LINEARRAY (result, FILE0) = ALLOCATE (numlines, char *); | | 1002 | D_LINEARRAY (result, FILE0) = ALLOCATE (numlines, char *); |
1003 | D_LENARRAY (result, FILE0) = ALLOCATE (numlines, size_t); | | 1003 | D_LENARRAY (result, FILE0) = ALLOCATE (numlines, size_t); |
1004 | bzero (D_LINEARRAY (result, FILE0), (numlines * sizeof (char *))); | | 1004 | bzero (D_LINEARRAY (result, FILE0), (numlines * sizeof (char *))); |
1005 | bzero (D_LENARRAY (result, FILE0), (numlines * sizeof (size_t))); | | 1005 | bzero (D_LENARRAY (result, FILE0), (numlines * sizeof (size_t))); |
1006 | } | | 1006 | } |
1007 | else | | 1007 | else |
1008 | { | | 1008 | { |
1009 | D_LINEARRAY (result, FILE0) = 0; | | 1009 | D_LINEARRAY (result, FILE0) = 0; |
1010 | D_LENARRAY (result, FILE0) = 0; | | 1010 | D_LENARRAY (result, FILE0) = 0; |
1011 | } | | 1011 | } |
1012 | | | 1012 | |
1013 | numlines = D_NUMLINES (result, FILE1); | | 1013 | numlines = D_NUMLINES (result, FILE1); |
1014 | if (numlines) | | 1014 | if (numlines) |
1015 | { | | 1015 | { |
1016 | D_LINEARRAY (result, FILE1) = ALLOCATE (numlines, char *); | | 1016 | D_LINEARRAY (result, FILE1) = ALLOCATE (numlines, char *); |
1017 | D_LENARRAY (result, FILE1) = ALLOCATE (numlines, size_t); | | 1017 | D_LENARRAY (result, FILE1) = ALLOCATE (numlines, size_t); |
1018 | bzero (D_LINEARRAY (result, FILE1), (numlines * sizeof (char *))); | | 1018 | bzero (D_LINEARRAY (result, FILE1), (numlines * sizeof (char *))); |
1019 | bzero (D_LENARRAY (result, FILE1), (numlines * sizeof (size_t))); | | 1019 | bzero (D_LENARRAY (result, FILE1), (numlines * sizeof (size_t))); |
1020 | } | | 1020 | } |
1021 | else | | 1021 | else |
1022 | { | | 1022 | { |
1023 | D_LINEARRAY (result, FILE1) = 0; | | 1023 | D_LINEARRAY (result, FILE1) = 0; |
1024 | D_LENARRAY (result, FILE1) = 0; | | 1024 | D_LENARRAY (result, FILE1) = 0; |
1025 | } | | 1025 | } |
1026 | | | 1026 | |
1027 | numlines = D_NUMLINES (result, FILE2); | | 1027 | numlines = D_NUMLINES (result, FILE2); |
1028 | if (numlines) | | 1028 | if (numlines) |
1029 | { | | 1029 | { |
1030 | D_LINEARRAY (result, FILE2) = ALLOCATE (numlines, char *); | | 1030 | D_LINEARRAY (result, FILE2) = ALLOCATE (numlines, char *); |
1031 | D_LENARRAY (result, FILE2) = ALLOCATE (numlines, size_t); | | 1031 | D_LENARRAY (result, FILE2) = ALLOCATE (numlines, size_t); |
1032 | bzero (D_LINEARRAY (result, FILE2), (numlines * sizeof (char *))); | | 1032 | bzero (D_LINEARRAY (result, FILE2), (numlines * sizeof (char *))); |
1033 | bzero (D_LENARRAY (result, FILE2), (numlines * sizeof (size_t))); | | 1033 | bzero (D_LENARRAY (result, FILE2), (numlines * sizeof (size_t))); |
1034 | } | | 1034 | } |
1035 | else | | 1035 | else |
1036 | { | | 1036 | { |
1037 | D_LINEARRAY (result, FILE2) = 0; | | 1037 | D_LINEARRAY (result, FILE2) = 0; |
1038 | D_LENARRAY (result, FILE2) = 0; | | 1038 | D_LENARRAY (result, FILE2) = 0; |
1039 | } | | 1039 | } |
1040 | | | 1040 | |
1041 | /* Return */ | | 1041 | /* Return */ |
1042 | return result; | | 1042 | return result; |
1043 | } | | 1043 | } |
1044 | | | 1044 | |
1045 | /* | | 1045 | /* |
1046 | * Compare two lists of lines of text. | | 1046 | * Compare two lists of lines of text. |
1047 | * Return 1 if they are equivalent, 0 if not. | | 1047 | * Return 1 if they are equivalent, 0 if not. |
1048 | */ | | 1048 | */ |
1049 | static int | | 1049 | static int |
1050 | compare_line_list (list1, lengths1, list2, lengths2, nl) | | 1050 | compare_line_list (list1, lengths1, list2, lengths2, nl) |
1051 | char * const list1[], * const list2[]; | | 1051 | char * const list1[], * const list2[]; |
1052 | size_t const lengths1[], lengths2[]; | | 1052 | size_t const lengths1[], lengths2[]; |
1053 | int nl; | | 1053 | int nl; |
1054 | { | | 1054 | { |
1055 | char | | 1055 | char |
1056 | * const *l1 = list1, | | 1056 | * const *l1 = list1, |
1057 | * const *l2 = list2; | | 1057 | * const *l2 = list2; |
1058 | size_t const | | 1058 | size_t const |
1059 | *lgths1 = lengths1, | | 1059 | *lgths1 = lengths1, |
1060 | *lgths2 = lengths2; | | 1060 | *lgths2 = lengths2; |
1061 | | | 1061 | |
1062 | while (nl--) | | 1062 | while (nl--) |
1063 | if (!*l1 || !*l2 || *lgths1 != *lgths2++ | | 1063 | if (!*l1 || !*l2 || *lgths1 != *lgths2++ |
1064 | || memcmp (*l1++, *l2++, *lgths1++)) | | 1064 | || memcmp (*l1++, *l2++, *lgths1++)) |
1065 | return 0; | | 1065 | return 0; |
1066 | return 1; | | 1066 | return 1; |
1067 | } | | 1067 | } |
1068 | | | 1068 | |
1069 | /* | | 1069 | /* |
1070 | * Routines to input and parse two way diffs. | | 1070 | * Routines to input and parse two way diffs. |
1071 | */ | | 1071 | */ |
1072 | | | 1072 | |
1073 | extern char **environ; | | 1073 | extern char **environ; |
1074 | | | 1074 | |
1075 | static struct diff_block * | | 1075 | static struct diff_block * |
1076 | process_diff (filea, fileb, last_block, diff_contents) | | 1076 | process_diff (filea, fileb, last_block, diff_contents) |
1077 | char const *filea, *fileb; | | 1077 | char const *filea, *fileb; |
1078 | struct diff_block **last_block; | | 1078 | struct diff_block **last_block; |
1079 | char **diff_contents; | | 1079 | char **diff_contents; |
1080 | { | | 1080 | { |
1081 | char *diff_limit; | | 1081 | char *diff_limit; |
1082 | char *scan_diff; | | 1082 | char *scan_diff; |
1083 | enum diff_type dt; | | 1083 | enum diff_type dt; |
1084 | int i; | | 1084 | int i; |
1085 | struct diff_block *block_list, **block_list_end, *bptr; | | 1085 | struct diff_block *block_list, **block_list_end, *bptr; |
1086 | | | 1086 | |
1087 | diff_limit = read_diff (filea, fileb, diff_contents); | | 1087 | diff_limit = read_diff (filea, fileb, diff_contents); |
1088 | scan_diff = *diff_contents; | | 1088 | scan_diff = *diff_contents; |
1089 | block_list_end = &block_list; | | 1089 | block_list_end = &block_list; |
1090 | bptr = 0; /* Pacify `gcc -W'. */ | | 1090 | bptr = 0; /* Pacify `gcc -W'. */ |
1091 | | | 1091 | |
1092 | while (scan_diff < diff_limit) | | 1092 | while (scan_diff < diff_limit) |
1093 | { | | 1093 | { |
1094 | bptr = ALLOCATE (1, struct diff_block); | | 1094 | bptr = ALLOCATE (1, struct diff_block); |
1095 | bptr->lines[0] = bptr->lines[1] = 0; | | 1095 | bptr->lines[0] = bptr->lines[1] = 0; |
1096 | bptr->lengths[0] = bptr->lengths[1] = 0; | | 1096 | bptr->lengths[0] = bptr->lengths[1] = 0; |
1097 | | | 1097 | |
1098 | dt = process_diff_control (&scan_diff, bptr); | | 1098 | dt = process_diff_control (&scan_diff, bptr); |
1099 | if (dt == ERROR || *scan_diff != '\n') | | 1099 | if (dt == ERROR || *scan_diff != '\n') |
1100 | { | | 1100 | { |
1101 | char *serr; | | 1101 | char *serr; |
1102 | | | 1102 | |
1103 | for (serr = scan_diff; *serr != '\n'; serr++) | | 1103 | for (serr = scan_diff; *serr != '\n'; serr++) |
1104 | ; | | 1104 | ; |
1105 | *serr = '\0'; | | 1105 | *serr = '\0'; |
1106 | diff_error ("diff error: %s", scan_diff, 0); | | 1106 | diff_error ("diff error: %s", scan_diff, 0); |
1107 | *serr = '\n'; | | 1107 | *serr = '\n'; |
1108 | DIFF3_ABORT (2); | | 1108 | DIFF3_ABORT (2); |
1109 | } | | 1109 | } |
1110 | scan_diff++; | | 1110 | scan_diff++; |
1111 | | | 1111 | |
1112 | /* Force appropriate ranges to be null, if necessary */ | | 1112 | /* Force appropriate ranges to be null, if necessary */ |
1113 | switch (dt) | | 1113 | switch (dt) |
1114 | { | | 1114 | { |
1115 | case ADD: | | 1115 | case ADD: |
1116 | bptr->ranges[0][0]++; | | 1116 | bptr->ranges[0][0]++; |
1117 | break; | | 1117 | break; |
1118 | case DELETE: | | 1118 | case DELETE: |
1119 | bptr->ranges[1][0]++; | | 1119 | bptr->ranges[1][0]++; |
1120 | break; | | 1120 | break; |
1121 | case CHANGE: | | 1121 | case CHANGE: |
1122 | break; | | 1122 | break; |
1123 | default: | | 1123 | default: |
1124 | diff3_fatal ("internal error: invalid diff type in process_diff"); | | 1124 | diff3_fatal ("internal error: invalid diff type in process_diff"); |
1125 | break; | | 1125 | break; |
1126 | } | | 1126 | } |
1127 | | | 1127 | |
1128 | /* Allocate space for the pointers for the lines from filea, and | | 1128 | /* Allocate space for the pointers for the lines from filea, and |
1129 | parcel them out among these pointers */ | | 1129 | parcel them out among these pointers */ |
1130 | if (dt != ADD) | | 1130 | if (dt != ADD) |
1131 | { | | 1131 | { |
1132 | int numlines = D_NUMLINES (bptr, 0); | | 1132 | int numlines = D_NUMLINES (bptr, 0); |
1133 | bptr->lines[0] = ALLOCATE (numlines, char *); | | 1133 | bptr->lines[0] = ALLOCATE (numlines, char *); |
1134 | bptr->lengths[0] = ALLOCATE (numlines, size_t); | | 1134 | bptr->lengths[0] = ALLOCATE (numlines, size_t); |
1135 | for (i = 0; i < numlines; i++) | | 1135 | for (i = 0; i < numlines; i++) |
1136 | scan_diff = scan_diff_line (scan_diff, | | 1136 | scan_diff = scan_diff_line (scan_diff, |
1137 | &(bptr->lines[0][i]), | | 1137 | &(bptr->lines[0][i]), |
1138 | &(bptr->lengths[0][i]), | | 1138 | &(bptr->lengths[0][i]), |
1139 | diff_limit, | | 1139 | diff_limit, |
1140 | '<'); | | 1140 | '<'); |
1141 | } | | 1141 | } |
1142 | | | 1142 | |
1143 | /* Get past the separator for changes */ | | 1143 | /* Get past the separator for changes */ |
1144 | if (dt == CHANGE) | | 1144 | if (dt == CHANGE) |
1145 | { | | 1145 | { |
1146 | if (strncmp (scan_diff, "---\n", 4)) | | 1146 | if (strncmp (scan_diff, "---\n", 4)) |
1147 | diff3_fatal ("invalid diff format; invalid change separator"); | | 1147 | diff3_fatal ("invalid diff format; invalid change separator"); |
1148 | scan_diff += 4; | | 1148 | scan_diff += 4; |
1149 | } | | 1149 | } |
1150 | | | 1150 | |
1151 | /* Allocate space for the pointers for the lines from fileb, and | | 1151 | /* Allocate space for the pointers for the lines from fileb, and |
1152 | parcel them out among these pointers */ | | 1152 | parcel them out among these pointers */ |
1153 | if (dt != DELETE) | | 1153 | if (dt != DELETE) |
1154 | { | | 1154 | { |
1155 | int numlines = D_NUMLINES (bptr, 1); | | 1155 | int numlines = D_NUMLINES (bptr, 1); |
1156 | bptr->lines[1] = ALLOCATE (numlines, char *); | | 1156 | bptr->lines[1] = ALLOCATE (numlines, char *); |
1157 | bptr->lengths[1] = ALLOCATE (numlines, size_t); | | 1157 | bptr->lengths[1] = ALLOCATE (numlines, size_t); |
1158 | for (i = 0; i < numlines; i++) | | 1158 | for (i = 0; i < numlines; i++) |
1159 | scan_diff = scan_diff_line (scan_diff, | | 1159 | scan_diff = scan_diff_line (scan_diff, |
1160 | &(bptr->lines[1][i]), | | 1160 | &(bptr->lines[1][i]), |
1161 | &(bptr->lengths[1][i]), | | 1161 | &(bptr->lengths[1][i]), |
1162 | diff_limit, | | 1162 | diff_limit, |
1163 | '>'); | | 1163 | '>'); |
1164 | } | | 1164 | } |
1165 | | | 1165 | |
1166 | /* Place this block on the blocklist. */ | | 1166 | /* Place this block on the blocklist. */ |
1167 | *block_list_end = bptr; | | 1167 | *block_list_end = bptr; |
1168 | block_list_end = &bptr->next; | | 1168 | block_list_end = &bptr->next; |
1169 | } | | 1169 | } |
1170 | | | 1170 | |
1171 | *block_list_end = 0; | | 1171 | *block_list_end = 0; |
1172 | *last_block = bptr; | | 1172 | *last_block = bptr; |
1173 | return block_list; | | 1173 | return block_list; |
1174 | } | | 1174 | } |
1175 | | | 1175 | |
1176 | /* | | 1176 | /* |
1177 | * This routine will parse a normal format diff control string. It | | 1177 | * This routine will parse a normal format diff control string. It |
1178 | * returns the type of the diff (ERROR if the format is bad). All of | | 1178 | * returns the type of the diff (ERROR if the format is bad). All of |
1179 | * the other important information is filled into to the structure | | 1179 | * the other important information is filled into to the structure |
1180 | * pointed to by db, and the string pointer (whose location is passed | | 1180 | * pointed to by db, and the string pointer (whose location is passed |
1181 | * to this routine) is updated to point beyond the end of the string | | 1181 | * to this routine) is updated to point beyond the end of the string |
1182 | * parsed. Note that only the ranges in the diff_block will be set by | | 1182 | * parsed. Note that only the ranges in the diff_block will be set by |
1183 | * this routine. | | 1183 | * this routine. |
1184 | * | | 1184 | * |
1185 | * If some specific pair of numbers has been reduced to a single | | 1185 | * If some specific pair of numbers has been reduced to a single |
1186 | * number, then both corresponding numbers in the diff block are set | | 1186 | * number, then both corresponding numbers in the diff block are set |
1187 | * to that number. In general these numbers are interpetted as ranges | | 1187 | * to that number. In general these numbers are interpetted as ranges |
1188 | * inclusive, unless being used by the ADD or DELETE commands. It is | | 1188 | * inclusive, unless being used by the ADD or DELETE commands. It is |
1189 | * assumed that these will be special cased in a superior routine. | | 1189 | * assumed that these will be special cased in a superior routine. |
1190 | */ | | 1190 | */ |
1191 | | | 1191 | |
1192 | static enum diff_type | | 1192 | static enum diff_type |
1193 | process_diff_control (string, db) | | 1193 | process_diff_control (string, db) |
1194 | char **string; | | 1194 | char **string; |
1195 | struct diff_block *db; | | 1195 | struct diff_block *db; |
1196 | { | | 1196 | { |
1197 | char *s = *string; | | 1197 | char *s = *string; |
1198 | int holdnum; | | 1198 | int holdnum; |
1199 | enum diff_type type; | | 1199 | enum diff_type type; |
1200 | | | 1200 | |
1201 | /* These macros are defined here because they can use variables | | 1201 | /* These macros are defined here because they can use variables |
1202 | defined in this function. Don't try this at home kids, we're | | 1202 | defined in this function. Don't try this at home kids, we're |
1203 | trained professionals! | | 1203 | trained professionals! |
1204 | | | 1204 | |
1205 | Also note that SKIPWHITE only recognizes tabs and spaces, and | | 1205 | Also note that SKIPWHITE only recognizes tabs and spaces, and |
1206 | that READNUM can only read positive, integral numbers */ | | 1206 | that READNUM can only read positive, integral numbers */ |
1207 | | | 1207 | |
1208 | #define SKIPWHITE(s) { while (*s == ' ' || *s == '\t') s++; } | | 1208 | #define SKIPWHITE(s) { while (*s == ' ' || *s == '\t') s++; } |
1209 | #define READNUM(s, num) \ | | 1209 | #define READNUM(s, num) \ |
1210 | { unsigned char c = *s; if (!ISDIGIT (c)) return ERROR; holdnum = 0; \ | | 1210 | { unsigned char c = *s; if (!ISDIGIT (c)) return ERROR; holdnum = 0; \ |
1211 | do { holdnum = (c - '0' + holdnum * 10); } \ | | 1211 | do { holdnum = (c - '0' + holdnum * 10); } \ |
1212 | while (ISDIGIT (c = *++s)); (num) = holdnum; } | | 1212 | while (ISDIGIT (c = *++s)); (num) = holdnum; } |
1213 | | | 1213 | |
1214 | /* Read first set of digits */ | | 1214 | /* Read first set of digits */ |
1215 | SKIPWHITE (s); | | 1215 | SKIPWHITE (s); |
1216 | READNUM (s, db->ranges[0][START]); | | 1216 | READNUM (s, db->ranges[0][START]); |
1217 | | | 1217 | |
1218 | /* Was that the only digit? */ | | 1218 | /* Was that the only digit? */ |
1219 | SKIPWHITE (s); | | 1219 | SKIPWHITE (s); |
1220 | if (*s == ',') | | 1220 | if (*s == ',') |
1221 | { | | 1221 | { |
1222 | /* Get the next digit */ | | 1222 | /* Get the next digit */ |
1223 | s++; | | 1223 | s++; |
1224 | READNUM (s, db->ranges[0][END]); | | 1224 | READNUM (s, db->ranges[0][END]); |
1225 | } | | 1225 | } |
1226 | else | | 1226 | else |
1227 | db->ranges[0][END] = db->ranges[0][START]; | | 1227 | db->ranges[0][END] = db->ranges[0][START]; |
1228 | | | 1228 | |
1229 | /* Get the letter */ | | 1229 | /* Get the letter */ |
1230 | SKIPWHITE (s); | | 1230 | SKIPWHITE (s); |
1231 | switch (*s) | | 1231 | switch (*s) |
1232 | { | | 1232 | { |
1233 | case 'a': | | 1233 | case 'a': |
1234 | type = ADD; | | 1234 | type = ADD; |
1235 | break; | | 1235 | break; |
1236 | case 'c': | | 1236 | case 'c': |
1237 | type = CHANGE; | | 1237 | type = CHANGE; |
1238 | break; | | 1238 | break; |
1239 | case 'd': | | 1239 | case 'd': |
1240 | type = DELETE; | | 1240 | type = DELETE; |
1241 | break; | | 1241 | break; |
1242 | default: | | 1242 | default: |
1243 | return ERROR; /* Bad format */ | | 1243 | return ERROR; /* Bad format */ |
1244 | } | | 1244 | } |
1245 | s++; /* Past letter */ | | 1245 | s++; /* Past letter */ |
1246 | | | 1246 | |
1247 | /* Read second set of digits */ | | 1247 | /* Read second set of digits */ |
1248 | SKIPWHITE (s); | | 1248 | SKIPWHITE (s); |
1249 | READNUM (s, db->ranges[1][START]); | | 1249 | READNUM (s, db->ranges[1][START]); |
1250 | | | 1250 | |
1251 | /* Was that the only digit? */ | | 1251 | /* Was that the only digit? */ |
1252 | SKIPWHITE (s); | | 1252 | SKIPWHITE (s); |
1253 | if (*s == ',') | | 1253 | if (*s == ',') |
1254 | { | | 1254 | { |
1255 | /* Get the next digit */ | | 1255 | /* Get the next digit */ |
1256 | s++; | | 1256 | s++; |
1257 | READNUM (s, db->ranges[1][END]); | | 1257 | READNUM (s, db->ranges[1][END]); |
1258 | SKIPWHITE (s); /* To move to end */ | | 1258 | SKIPWHITE (s); /* To move to end */ |
1259 | } | | 1259 | } |
1260 | else | | 1260 | else |
1261 | db->ranges[1][END] = db->ranges[1][START]; | | 1261 | db->ranges[1][END] = db->ranges[1][START]; |
1262 | | | 1262 | |
1263 | *string = s; | | 1263 | *string = s; |
1264 | return type; | | 1264 | return type; |
1265 | } | | 1265 | } |
1266 | | | 1266 | |
1267 | static char * | | 1267 | static char * |
1268 | read_diff (filea, fileb, output_placement) | | 1268 | read_diff (filea, fileb, output_placement) |
1269 | char const *filea, *fileb; | | 1269 | char const *filea, *fileb; |
1270 | char **output_placement; | | 1270 | char **output_placement; |
1271 | { | | 1271 | { |
1272 | char *diff_result; | | 1272 | char *diff_result; |
1273 | size_t bytes, current_chunk_size, total; | | 1273 | size_t bytes, current_chunk_size, total; |
1274 | int fd, wstatus; | | 1274 | int fd, wstatus; |
1275 | struct stat pipestat; | | 1275 | struct stat pipestat; |
1276 | FILE *outfile_hold; | | 1276 | FILE *outfile_hold; |
1277 | const struct diff_callbacks *callbacks_hold; | | 1277 | const struct diff_callbacks *callbacks_hold; |
1278 | struct diff_callbacks my_callbacks; | | 1278 | struct diff_callbacks my_callbacks; |
1279 | struct diff_callbacks *my_callbacks_arg; | | 1279 | struct diff_callbacks *my_callbacks_arg; |
1280 | | | 1280 | |
1281 | /* 302 / 1000 is log10(2.0) rounded up. Subtract 1 for the sign bit; | | 1281 | /* 302 / 1000 is log10(2.0) rounded up. Subtract 1 for the sign bit; |
1282 | add 1 for integer division truncation; add 1 more for a minus sign. */ | | 1282 | add 1 for integer division truncation; add 1 more for a minus sign. */ |
1283 | #define INT_STRLEN_BOUND(type) ((sizeof(type)*CHAR_BIT - 1) * 302 / 1000 + 2) | | 1283 | #define INT_STRLEN_BOUND(type) ((sizeof(type)*CHAR_BIT - 1) * 302 / 1000 + 2) |
1284 | | | 1284 | |
1285 | char const *argv[7]; | | 1285 | char const *argv[7]; |
1286 | char horizon_arg[17 + INT_STRLEN_BOUND (int)]; | | 1286 | char horizon_arg[17 + INT_STRLEN_BOUND (int)]; |
1287 | char const **ap; | | 1287 | char const **ap; |
1288 | char *diffout; | | 1288 | char *diffout; |
1289 | | | 1289 | |
1290 | ap = argv; | | 1290 | ap = argv; |
1291 | *ap++ = "diff"; | | 1291 | *ap++ = "diff"; |
1292 | if (always_text) | | 1292 | if (always_text) |
1293 | *ap++ = "-a"; | | 1293 | *ap++ = "-a"; |
1294 | sprintf (horizon_arg, "--horizon-lines=%d", horizon_lines); | | 1294 | sprintf (horizon_arg, "--horizon-lines=%d", horizon_lines); |
1295 | *ap++ = horizon_arg; | | 1295 | *ap++ = horizon_arg; |
1296 | *ap++ = "--"; | | 1296 | *ap++ = "--"; |
1297 | *ap++ = filea; | | 1297 | *ap++ = filea; |
1298 | *ap++ = fileb; | | 1298 | *ap++ = fileb; |
1299 | *ap = 0; | | 1299 | *ap = 0; |
1300 | | | 1300 | |
1301 | diffout = cvs_temp_name (); | | 1301 | diffout = cvs_temp_name (); |
1302 | | | 1302 | |
1303 | outfile_hold = outfile; | | 1303 | outfile_hold = outfile; |
1304 | callbacks_hold = callbacks; | | 1304 | callbacks_hold = callbacks; |
1305 | | | 1305 | |
1306 | /* We want to call diff_run preserving any stdout and stderr | | 1306 | /* We want to call diff_run preserving any stdout and stderr |
1307 | callbacks, but discarding any callbacks to handle file output, | | 1307 | callbacks, but discarding any callbacks to handle file output, |
1308 | since we want the file output to go to our temporary file. | | 1308 | since we want the file output to go to our temporary file. |
1309 | FIXME: We should use callbacks to just read it into a memory | | 1309 | FIXME: We should use callbacks to just read it into a memory |
1310 | buffer; that's we do with the temporary file just below anyhow. */ | | 1310 | buffer; that's we do with the temporary file just below anyhow. */ |
1311 | if (callbacks == NULL) | | 1311 | if (callbacks == NULL) |
1312 | my_callbacks_arg = NULL; | | 1312 | my_callbacks_arg = NULL; |
1313 | else | | 1313 | else |
1314 | { | | 1314 | { |
1315 | my_callbacks = *callbacks; | | 1315 | my_callbacks = *callbacks; |
1316 | my_callbacks.write_output = NULL; | | 1316 | my_callbacks.write_output = NULL; |
1317 | my_callbacks.flush_output = NULL; | | 1317 | my_callbacks.flush_output = NULL; |
1318 | my_callbacks_arg = &my_callbacks; | | 1318 | my_callbacks_arg = &my_callbacks; |
1319 | } | | 1319 | } |
1320 | | | 1320 | |
1321 | wstatus = diff_run (ap - argv, (char **) argv, diffout, my_callbacks_arg); | | 1321 | wstatus = diff_run (ap - argv, (char **) argv, diffout, my_callbacks_arg); |
1322 | | | 1322 | |
1323 | outfile = outfile_hold; | | 1323 | outfile = outfile_hold; |
1324 | callbacks = callbacks_hold; | | 1324 | callbacks = callbacks_hold; |
1325 | | | 1325 | |
1326 | if (wstatus == 2) | | 1326 | if (wstatus == 2) |
1327 | diff3_fatal ("subsidiary diff failed"); | | 1327 | diff3_fatal ("subsidiary diff failed"); |
1328 | | | 1328 | |
1329 | if (-1 == (fd = open (diffout, O_RDONLY))) | | 1329 | if (-1 == (fd = open (diffout, O_RDONLY))) |
1330 | diff3_fatal ("could not open temporary diff file"); | | 1330 | diff3_fatal ("could not open temporary diff file"); |
1331 | | | 1331 | |
1332 | current_chunk_size = 8 * 1024; | | 1332 | current_chunk_size = 8 * 1024; |
1333 | if (fstat (fd, &pipestat) == 0) | | 1333 | if (fstat (fd, &pipestat) == 0) |
1334 | current_chunk_size = max (current_chunk_size, STAT_BLOCKSIZE (pipestat)); | | 1334 | current_chunk_size = max (current_chunk_size, STAT_BLOCKSIZE (pipestat)); |
1335 | | | 1335 | |
1336 | diff_result = xmalloc (current_chunk_size); | | 1336 | diff_result = xmalloc (current_chunk_size); |
1337 | total = 0; | | 1337 | total = 0; |
1338 | do { | | 1338 | do { |
1339 | bytes = myread (fd, | | 1339 | bytes = myread (fd, |
1340 | diff_result + total, | | 1340 | diff_result + total, |
1341 | current_chunk_size - total); | | 1341 | current_chunk_size - total); |
1342 | total += bytes; | | 1342 | total += bytes; |
1343 | if (total == current_chunk_size) | | 1343 | if (total == current_chunk_size) |
1344 | { | | 1344 | { |
1345 | if (current_chunk_size < 2 * current_chunk_size) | | 1345 | if (current_chunk_size < 2 * current_chunk_size) |
1346 | current_chunk_size = 2 * current_chunk_size; | | 1346 | current_chunk_size = 2 * current_chunk_size; |
1347 | else if (current_chunk_size < (size_t) -1) | | 1347 | else if (current_chunk_size < (size_t) -1) |
1348 | current_chunk_size = (size_t) -1; | | 1348 | current_chunk_size = (size_t) -1; |
1349 | else | | 1349 | else |
1350 | diff3_fatal ("files are too large to fit into memory"); | | 1350 | diff3_fatal ("files are too large to fit into memory"); |
1351 | diff_result = xrealloc (diff_result, (current_chunk_size *= 2)); | | 1351 | diff_result = xrealloc (diff_result, (current_chunk_size *= 2)); |
1352 | } | | 1352 | } |
1353 | } while (bytes); | | 1353 | } while (bytes); |
1354 | | | 1354 | |
1355 | if (total != 0 && diff_result[total-1] != '\n') | | 1355 | if (total != 0 && diff_result[total-1] != '\n') |
1356 | diff3_fatal ("invalid diff format; incomplete last line"); | | 1356 | diff3_fatal ("invalid diff format; incomplete last line"); |
1357 | | | 1357 | |
1358 | *output_placement = diff_result; | | 1358 | *output_placement = diff_result; |
1359 | | | 1359 | |
1360 | if (close (fd) != 0) | | 1360 | if (close (fd) != 0) |
1361 | diff3_perror_with_exit ("pipe close"); | | 1361 | diff3_perror_with_exit ("pipe close"); |
1362 | unlink (diffout); | | 1362 | unlink (diffout); |
1363 | free( diffout ); | | 1363 | free( diffout ); |
1364 | | | 1364 | |
1365 | return diff_result + total; | | 1365 | return diff_result + total; |
1366 | } | | 1366 | } |
1367 | | | 1367 | |
1368 | | | 1368 | |
1369 | /* | | 1369 | /* |
1370 | * Scan a regular diff line (consisting of > or <, followed by a | | 1370 | * Scan a regular diff line (consisting of > or <, followed by a |
1371 | * space, followed by text (including nulls) up to a newline. | | 1371 | * space, followed by text (including nulls) up to a newline. |
1372 | * | | 1372 | * |
1373 | * This next routine began life as a macro and many parameters in it | | 1373 | * This next routine began life as a macro and many parameters in it |
1374 | * are used as call-by-reference values. | | 1374 | * are used as call-by-reference values. |
1375 | */ | | 1375 | */ |
1376 | static char * | | 1376 | static char * |
1377 | scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar) | | 1377 | scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar) |
1378 | char *scan_ptr, **set_start; | | 1378 | char *scan_ptr, **set_start; |
1379 | size_t *set_length; | | 1379 | size_t *set_length; |
1380 | char *limit; | | 1380 | char *limit; |
1381 | int leadingchar; | | 1381 | int leadingchar; |
1382 | { | | 1382 | { |
1383 | char *line_ptr; | | 1383 | char *line_ptr; |
1384 | | | 1384 | |
1385 | if (!(scan_ptr[0] == leadingchar | | 1385 | if (!(scan_ptr[0] == leadingchar |
1386 | && scan_ptr[1] == ' ')) | | 1386 | && scan_ptr[1] == ' ')) |
1387 | diff3_fatal ("invalid diff format; incorrect leading line chars"); | | 1387 | diff3_fatal ("invalid diff format; incorrect leading line chars"); |
1388 | | | 1388 | |
1389 | *set_start = line_ptr = scan_ptr + 2; | | 1389 | *set_start = line_ptr = scan_ptr + 2; |
1390 | while (*line_ptr++ != '\n') | | 1390 | while (*line_ptr++ != '\n') |
1391 | ; | | 1391 | ; |
1392 | | | 1392 | |
1393 | /* Include newline if the original line ended in a newline, | | 1393 | /* Include newline if the original line ended in a newline, |
1394 | or if an edit script is being generated. | | 1394 | or if an edit script is being generated. |
1395 | Copy any missing newline message to stderr if an edit script is being | | 1395 | Copy any missing newline message to stderr if an edit script is being |
1396 | generated, because edit scripts cannot handle missing newlines. | | 1396 | generated, because edit scripts cannot handle missing newlines. |
1397 | Return the beginning of the next line. */ | | 1397 | Return the beginning of the next line. */ |
1398 | *set_length = line_ptr - *set_start; | | 1398 | *set_length = line_ptr - *set_start; |
1399 | if (line_ptr < limit && *line_ptr == '\\') | | 1399 | if (line_ptr < limit && *line_ptr == '\\') |
1400 | { | | 1400 | { |
1401 | if (! edscript) | | 1401 | if (! edscript) |
1402 | { | | 1402 | { |
1403 | --*set_length; | | 1403 | --*set_length; |
1404 | line_ptr++; | | 1404 | line_ptr++; |
1405 | while (*line_ptr++ != '\n') | | 1405 | while (*line_ptr++ != '\n') |
1406 | ; | | 1406 | ; |
1407 | } | | 1407 | } |
1408 | else | | 1408 | else |
1409 | { | | 1409 | { |
1410 | char *serr; | | 1410 | char *serr; |
1411 | | | 1411 | |
1412 | line_ptr++; | | 1412 | line_ptr++; |
1413 | serr = line_ptr; | | 1413 | serr = line_ptr; |
1414 | while (*line_ptr++ != '\n') | | 1414 | while (*line_ptr++ != '\n') |
1415 | ; | | 1415 | ; |
1416 | line_ptr[-1] = '\0'; | | 1416 | line_ptr[-1] = '\0'; |
1417 | diff_error ("%s", serr, 0); | | 1417 | diff_error ("%s", serr, 0); |
1418 | line_ptr[-1] = '\n'; | | 1418 | line_ptr[-1] = '\n'; |
1419 | } | | 1419 | } |
1420 | } | | 1420 | } |
1421 | | | 1421 | |
1422 | return line_ptr; | | 1422 | return line_ptr; |
1423 | } | | 1423 | } |
1424 | | | 1424 | |
1425 | /* | | 1425 | /* |
1426 | * This routine outputs a three way diff passed as a list of | | 1426 | * This routine outputs a three way diff passed as a list of |
1427 | * diff3_block's. | | 1427 | * diff3_block's. |
1428 | * The argument MAPPING is indexed by external file number (in the | | 1428 | * The argument MAPPING is indexed by external file number (in the |
1429 | * argument list) and contains the internal file number (from the | | 1429 | * argument list) and contains the internal file number (from the |
1430 | * diff passed). This is important because the user expects his | | 1430 | * diff passed). This is important because the user expects his |
1431 | * outputs in terms of the argument list number, and the diff passed | | 1431 | * outputs in terms of the argument list number, and the diff passed |
1432 | * may have been done slightly differently (if the last argument | | 1432 | * may have been done slightly differently (if the last argument |
1433 | * was "-", for example). | | 1433 | * was "-", for example). |
1434 | * REV_MAPPING is the inverse of MAPPING. | | 1434 | * REV_MAPPING is the inverse of MAPPING. |
1435 | */ | | 1435 | */ |
1436 | static void | | 1436 | static void |
1437 | output_diff3 (diff, mapping, rev_mapping) | | 1437 | output_diff3 (diff, mapping, rev_mapping) |
1438 | struct diff3_block *diff; | | 1438 | struct diff3_block *diff; |
1439 | int const mapping[3], rev_mapping[3]; | | 1439 | int const mapping[3], rev_mapping[3]; |
1440 | { | | 1440 | { |
1441 | int i; | | 1441 | int i; |
1442 | int oddoneout; | | 1442 | int oddoneout; |
1443 | char *cp; | | 1443 | char *cp; |
1444 | struct diff3_block *ptr; | | 1444 | struct diff3_block *ptr; |
1445 | int line; | | 1445 | int line; |
1446 | size_t length; | | 1446 | size_t length; |
1447 | int dontprint; | | 1447 | int dontprint; |
1448 | static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */ | | 1448 | static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */ |
1449 | char const *line_prefix = tab_align_flag ? "\t" : " "; | | 1449 | char const *line_prefix = tab_align_flag ? "\t" : " "; |
1450 | | | 1450 | |
1451 | for (ptr = diff; ptr; ptr = D_NEXT (ptr)) | | 1451 | for (ptr = diff; ptr; ptr = D_NEXT (ptr)) |
1452 | { | | 1452 | { |
1453 | char x[2]; | | 1453 | char x[2]; |
1454 | | | 1454 | |
1455 | switch (ptr->correspond) | | 1455 | switch (ptr->correspond) |
1456 | { | | 1456 | { |
1457 | case DIFF_ALL: | | 1457 | case DIFF_ALL: |
1458 | x[0] = '\0'; | | 1458 | x[0] = '\0'; |
1459 | dontprint = 3; /* Print them all */ | | 1459 | dontprint = 3; /* Print them all */ |
1460 | oddoneout = 3; /* Nobody's odder than anyone else */ | | 1460 | oddoneout = 3; /* Nobody's odder than anyone else */ |
1461 | break; | | 1461 | break; |
1462 | case DIFF_1ST: | | 1462 | case DIFF_1ST: |
1463 | case DIFF_2ND: | | 1463 | case DIFF_2ND: |
1464 | case DIFF_3RD: | | 1464 | case DIFF_3RD: |
1465 | oddoneout = rev_mapping[(int) ptr->correspond - (int) DIFF_1ST]; | | 1465 | oddoneout = rev_mapping[(int) ptr->correspond - (int) DIFF_1ST]; |
1466 | | | 1466 | |
1467 | x[0] = oddoneout + '1'; | | 1467 | x[0] = oddoneout + '1'; |
1468 | x[1] = '\0'; | | 1468 | x[1] = '\0'; |
1469 | dontprint = oddoneout==0; | | 1469 | dontprint = oddoneout==0; |
1470 | break; | | 1470 | break; |
1471 | default: | | 1471 | default: |
1472 | diff3_fatal ("internal error: invalid diff type passed to output"); | | 1472 | diff3_fatal ("internal error: invalid diff type passed to output"); |
1473 | } | | 1473 | } |
1474 | printf_output ("====%s\n", x); | | 1474 | printf_output ("====%s\n", x); |
1475 | | | 1475 | |
1476 | /* Go 0, 2, 1 if the first and third outputs are equivalent. */ | | 1476 | /* Go 0, 2, 1 if the first and third outputs are equivalent. */ |
1477 | for (i = 0; i < 3; | | 1477 | for (i = 0; i < 3; |
1478 | i = (oddoneout == 1 ? skew_increment[i] : i + 1)) | | 1478 | i = (oddoneout == 1 ? skew_increment[i] : i + 1)) |
1479 | { | | 1479 | { |
1480 | int realfile = mapping[i]; | | 1480 | int realfile = mapping[i]; |
1481 | int | | 1481 | int |
1482 | lowt = D_LOWLINE (ptr, realfile), | | 1482 | lowt = D_LOWLINE (ptr, realfile), |
1483 | hight = D_HIGHLINE (ptr, realfile); | | 1483 | hight = D_HIGHLINE (ptr, realfile); |
1484 | | | 1484 | |
1485 | printf_output ("%d:", i + 1); | | 1485 | printf_output ("%d:", i + 1); |
1486 | switch (lowt - hight) | | 1486 | switch (lowt - hight) |
1487 | { | | 1487 | { |
1488 | case 1: | | 1488 | case 1: |
1489 | printf_output ("%da\n", lowt - 1); | | 1489 | printf_output ("%da\n", lowt - 1); |
1490 | break; | | 1490 | break; |
1491 | case 0: | | 1491 | case 0: |
1492 | printf_output ("%dc\n", lowt); | | 1492 | printf_output ("%dc\n", lowt); |
1493 | break; | | 1493 | break; |
1494 | default: | | 1494 | default: |
1495 | printf_output ("%d,%dc\n", lowt, hight); | | 1495 | printf_output ("%d,%dc\n", lowt, hight); |
1496 | break; | | 1496 | break; |
1497 | } | | 1497 | } |
1498 | | | 1498 | |
1499 | if (i == dontprint) continue; | | 1499 | if (i == dontprint) continue; |
1500 | | | 1500 | |
1501 | if (lowt <= hight) | | 1501 | if (lowt <= hight) |
1502 | { | | 1502 | { |
1503 | line = 0; | | 1503 | line = 0; |
1504 | do | | 1504 | do |
1505 | { | | 1505 | { |
1506 | printf_output (line_prefix); | | 1506 | printf_output ("%s", line_prefix); |
1507 | cp = D_RELNUM (ptr, realfile, line); | | 1507 | cp = D_RELNUM (ptr, realfile, line); |
1508 | length = D_RELLEN (ptr, realfile, line); | | 1508 | length = D_RELLEN (ptr, realfile, line); |
1509 | write_output (cp, length); | | 1509 | write_output (cp, length); |
1510 | } | | 1510 | } |
1511 | while (++line < hight - lowt + 1); | | 1511 | while (++line < hight - lowt + 1); |
1512 | if (cp[length - 1] != '\n') | | 1512 | if (cp[length - 1] != '\n') |
1513 | printf_output ("\n\\ No newline at end of file\n"); | | 1513 | printf_output ("\n\\ No newline at end of file\n"); |
1514 | } | | 1514 | } |
1515 | } | | 1515 | } |
1516 | } | | 1516 | } |
1517 | } | | 1517 | } |
1518 | | | 1518 | |
1519 | | | 1519 | |
1520 | /* | | 1520 | /* |
1521 | * Output the lines of B taken from FILENUM. | | 1521 | * Output the lines of B taken from FILENUM. |
1522 | * Double any initial '.'s; yield nonzero if any initial '.'s were doubled. | | 1522 | * Double any initial '.'s; yield nonzero if any initial '.'s were doubled. |
1523 | */ | | 1523 | */ |
1524 | static int | | 1524 | static int |
1525 | dotlines (b, filenum) | | 1525 | dotlines (b, filenum) |
1526 | struct diff3_block *b; | | 1526 | struct diff3_block *b; |
1527 | int filenum; | | 1527 | int filenum; |
1528 | { | | 1528 | { |
1529 | int i; | | 1529 | int i; |
1530 | int leading_dot = 0; | | 1530 | int leading_dot = 0; |
1531 | | | 1531 | |
1532 | for (i = 0; | | 1532 | for (i = 0; |
1533 | i < D_NUMLINES (b, filenum); | | 1533 | i < D_NUMLINES (b, filenum); |
1534 | i++) | | 1534 | i++) |
1535 | { | | 1535 | { |
1536 | char *line = D_RELNUM (b, filenum, i); | | 1536 | char *line = D_RELNUM (b, filenum, i); |
1537 | if (line[0] == '.') | | 1537 | if (line[0] == '.') |
1538 | { | | 1538 | { |
1539 | leading_dot = 1; | | 1539 | leading_dot = 1; |
1540 | write_output (".", 1); | | 1540 | write_output (".", 1); |
1541 | } | | 1541 | } |
1542 | write_output (line, D_RELLEN (b, filenum, i)); | | 1542 | write_output (line, D_RELLEN (b, filenum, i)); |
1543 | } | | 1543 | } |
1544 | | | 1544 | |
1545 | return leading_dot; | | 1545 | return leading_dot; |
1546 | } | | 1546 | } |
1547 | | | 1547 | |
1548 | /* | | 1548 | /* |
1549 | * Output to OUTPUTFILE a '.' line. If LEADING_DOT is nonzero, | | 1549 | * Output to OUTPUTFILE a '.' line. If LEADING_DOT is nonzero, |
1550 | * also output a command that removes initial '.'s | | 1550 | * also output a command that removes initial '.'s |
1551 | * starting with line START and continuing for NUM lines. | | 1551 | * starting with line START and continuing for NUM lines. |
1552 | */ | | 1552 | */ |
1553 | static void | | 1553 | static void |
1554 | undotlines (leading_dot, start, num) | | 1554 | undotlines (leading_dot, start, num) |
1555 | int leading_dot, start, num; | | 1555 | int leading_dot, start, num; |
1556 | { | | 1556 | { |
1557 | write_output (".\n", 2); | | 1557 | write_output (".\n", 2); |
1558 | if (leading_dot) | | 1558 | if (leading_dot) |
1559 | { | | 1559 | { |
1560 | if (num == 1) | | 1560 | if (num == 1) |
1561 | printf_output ("%ds/^\\.//\n", start); | | 1561 | printf_output ("%ds/^\\.//\n", start); |
1562 | else | | 1562 | else |
1563 | printf_output ("%d,%ds/^\\.//\n", start, start + num - 1); | | 1563 | printf_output ("%d,%ds/^\\.//\n", start, start + num - 1); |
1564 | } | | 1564 | } |
1565 | } | | 1565 | } |
1566 | | | 1566 | |
1567 | /* | | 1567 | /* |
1568 | * This routine outputs a diff3 set of blocks as an ed script. This | | 1568 | * This routine outputs a diff3 set of blocks as an ed script. This |
1569 | * script applies the changes between file's 2 & 3 to file 1. It | | 1569 | * script applies the changes between file's 2 & 3 to file 1. It |
1570 | * takes the precise format of the ed script to be output from global | | 1570 | * takes the precise format of the ed script to be output from global |
1571 | * variables set during options processing. Note that it does | | 1571 | * variables set during options processing. Note that it does |
1572 | * destructive things to the set of diff3 blocks it is passed; it | | 1572 | * destructive things to the set of diff3 blocks it is passed; it |
1573 | * reverses their order (this gets around the problems involved with | | 1573 | * reverses their order (this gets around the problems involved with |
1574 | * changing line numbers in an ed script). | | 1574 | * changing line numbers in an ed script). |
1575 | * | | 1575 | * |
1576 | * Note that this routine has the same problem of mapping as the last | | 1576 | * Note that this routine has the same problem of mapping as the last |
1577 | * one did; the variable MAPPING maps from file number according to | | 1577 | * one did; the variable MAPPING maps from file number according to |
1578 | * the argument list to file number according to the diff passed. All | | 1578 | * the argument list to file number according to the diff passed. All |
1579 | * files listed below are in terms of the argument list. | | 1579 | * files listed below are in terms of the argument list. |
1580 | * REV_MAPPING is the inverse of MAPPING. | | 1580 | * REV_MAPPING is the inverse of MAPPING. |
1581 | * | | 1581 | * |
1582 | * The arguments FILE0, FILE1 and FILE2 are the strings to print | | 1582 | * The arguments FILE0, FILE1 and FILE2 are the strings to print |
1583 | * as the names of the three files. These may be the actual names, | | 1583 | * as the names of the three files. These may be the actual names, |
1584 | * or may be the arguments specified with -L. | | 1584 | * or may be the arguments specified with -L. |
1585 | * | | 1585 | * |
1586 | * Returns 1 if conflicts were found. | | 1586 | * Returns 1 if conflicts were found. |
1587 | */ | | 1587 | */ |
1588 | | | 1588 | |
1589 | static int | | 1589 | static int |
1590 | output_diff3_edscript (diff, mapping, rev_mapping, file0, file1, file2) | | 1590 | output_diff3_edscript (diff, mapping, rev_mapping, file0, file1, file2) |
1591 | struct diff3_block *diff; | | 1591 | struct diff3_block *diff; |
1592 | int const mapping[3], rev_mapping[3]; | | 1592 | int const mapping[3], rev_mapping[3]; |
1593 | char const *file0, *file1, *file2; | | 1593 | char const *file0, *file1, *file2; |
1594 | { | | 1594 | { |
1595 | int leading_dot; | | 1595 | int leading_dot; |
1596 | int conflicts_found = 0, conflict; | | 1596 | int conflicts_found = 0, conflict; |
1597 | struct diff3_block *b; | | 1597 | struct diff3_block *b; |
1598 | | | 1598 | |
1599 | for (b = reverse_diff3_blocklist (diff); b; b = b->next) | | 1599 | for (b = reverse_diff3_blocklist (diff); b; b = b->next) |
1600 | { | | 1600 | { |
1601 | /* Must do mapping correctly. */ | | 1601 | /* Must do mapping correctly. */ |
1602 | enum diff_type type | | 1602 | enum diff_type type |
1603 | = ((b->correspond == DIFF_ALL) ? | | 1603 | = ((b->correspond == DIFF_ALL) ? |
1604 | DIFF_ALL : | | 1604 | DIFF_ALL : |
1605 | ((enum diff_type) | | 1605 | ((enum diff_type) |
1606 | (((int) DIFF_1ST) | | 1606 | (((int) DIFF_1ST) |
1607 | + rev_mapping[(int) b->correspond - (int) DIFF_1ST]))); | | 1607 | + rev_mapping[(int) b->correspond - (int) DIFF_1ST]))); |
1608 | | | 1608 | |
1609 | /* If we aren't supposed to do this output block, skip it. */ | | 1609 | /* If we aren't supposed to do this output block, skip it. */ |
1610 | switch (type) | | 1610 | switch (type) |
1611 | { | | 1611 | { |
1612 | default: continue; | | 1612 | default: continue; |
1613 | case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; | | 1613 | case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; |
1614 | case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; | | 1614 | case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; |
1615 | case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; | | 1615 | case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; |
1616 | } | | 1616 | } |
1617 | | | 1617 | |
1618 | if (conflict) | | 1618 | if (conflict) |
1619 | { | | 1619 | { |
1620 | conflicts_found = 1; | | 1620 | conflicts_found = 1; |
1621 | | | 1621 | |
1622 | | | 1622 | |
1623 | /* Mark end of conflict. */ | | 1623 | /* Mark end of conflict. */ |
1624 | | | 1624 | |
1625 | printf_output ("%da\n", D_HIGHLINE (b, mapping[FILE0])); | | 1625 | printf_output ("%da\n", D_HIGHLINE (b, mapping[FILE0])); |
1626 | leading_dot = 0; | | 1626 | leading_dot = 0; |
1627 | if (type == DIFF_ALL) | | 1627 | if (type == DIFF_ALL) |
1628 | { | | 1628 | { |
1629 | if (show_2nd) | | 1629 | if (show_2nd) |
1630 | { | | 1630 | { |
1631 | /* Append lines from FILE1. */ | | 1631 | /* Append lines from FILE1. */ |
1632 | printf_output ("||||||| %s\n", file1); | | 1632 | printf_output ("||||||| %s\n", file1); |
1633 | leading_dot = dotlines (b, mapping[FILE1]); | | 1633 | leading_dot = dotlines (b, mapping[FILE1]); |
1634 | } | | 1634 | } |
1635 | /* Append lines from FILE2. */ | | 1635 | /* Append lines from FILE2. */ |
1636 | printf_output ("=======\n"); | | 1636 | printf_output ("=======\n"); |
1637 | leading_dot |= dotlines (b, mapping[FILE2]); | | 1637 | leading_dot |= dotlines (b, mapping[FILE2]); |
1638 | } | | 1638 | } |
1639 | printf_output (">>>>>>> %s\n", file2); | | 1639 | printf_output (">>>>>>> %s\n", file2); |
1640 | undotlines (leading_dot, | | 1640 | undotlines (leading_dot, |
1641 | D_HIGHLINE (b, mapping[FILE0]) + 2, | | 1641 | D_HIGHLINE (b, mapping[FILE0]) + 2, |
1642 | (D_NUMLINES (b, mapping[FILE1]) | | 1642 | (D_NUMLINES (b, mapping[FILE1]) |
1643 | + D_NUMLINES (b, mapping[FILE2]) + 1)); | | 1643 | + D_NUMLINES (b, mapping[FILE2]) + 1)); |
1644 | | | 1644 | |
1645 | | | 1645 | |
1646 | /* Mark start of conflict. */ | | 1646 | /* Mark start of conflict. */ |
1647 | | | 1647 | |
1648 | printf_output ("%da\n<<<<<<< %s\n", | | 1648 | printf_output ("%da\n<<<<<<< %s\n", |
1649 | D_LOWLINE (b, mapping[FILE0]) - 1, | | 1649 | D_LOWLINE (b, mapping[FILE0]) - 1, |
1650 | type == DIFF_ALL ? file0 : file1); | | 1650 | type == DIFF_ALL ? file0 : file1); |
1651 | leading_dot = 0; | | 1651 | leading_dot = 0; |
1652 | if (type == DIFF_2ND) | | 1652 | if (type == DIFF_2ND) |
1653 | { | | 1653 | { |
1654 | /* Prepend lines from FILE1. */ | | 1654 | /* Prepend lines from FILE1. */ |
1655 | leading_dot = dotlines (b, mapping[FILE1]); | | 1655 | leading_dot = dotlines (b, mapping[FILE1]); |
1656 | printf_output ("=======\n"); | | 1656 | printf_output ("=======\n"); |
1657 | } | | 1657 | } |
1658 | undotlines (leading_dot, | | 1658 | undotlines (leading_dot, |
1659 | D_LOWLINE (b, mapping[FILE0]) + 1, | | 1659 | D_LOWLINE (b, mapping[FILE0]) + 1, |
1660 | D_NUMLINES (b, mapping[FILE1])); | | 1660 | D_NUMLINES (b, mapping[FILE1])); |
1661 | } | | 1661 | } |
1662 | else if (D_NUMLINES (b, mapping[FILE2]) == 0) | | 1662 | else if (D_NUMLINES (b, mapping[FILE2]) == 0) |
1663 | /* Write out a delete */ | | 1663 | /* Write out a delete */ |
1664 | { | | 1664 | { |
1665 | if (D_NUMLINES (b, mapping[FILE0]) == 1) | | 1665 | if (D_NUMLINES (b, mapping[FILE0]) == 1) |
1666 | printf_output ("%dd\n", D_LOWLINE (b, mapping[FILE0])); | | 1666 | printf_output ("%dd\n", D_LOWLINE (b, mapping[FILE0])); |
1667 | else | | 1667 | else |
1668 | printf_output ("%d,%dd\n", | | 1668 | printf_output ("%d,%dd\n", |
1669 | D_LOWLINE (b, mapping[FILE0]), | | 1669 | D_LOWLINE (b, mapping[FILE0]), |
1670 | D_HIGHLINE (b, mapping[FILE0])); | | 1670 | D_HIGHLINE (b, mapping[FILE0])); |
1671 | } | | 1671 | } |
1672 | else | | 1672 | else |
1673 | /* Write out an add or change */ | | 1673 | /* Write out an add or change */ |
1674 | { | | 1674 | { |
1675 | switch (D_NUMLINES (b, mapping[FILE0])) | | 1675 | switch (D_NUMLINES (b, mapping[FILE0])) |
1676 | { | | 1676 | { |
1677 | case 0: | | 1677 | case 0: |
1678 | printf_output ("%da\n", D_HIGHLINE (b, mapping[FILE0])); | | 1678 | printf_output ("%da\n", D_HIGHLINE (b, mapping[FILE0])); |
1679 | break; | | 1679 | break; |
1680 | case 1: | | 1680 | case 1: |
1681 | printf_output ("%dc\n", D_HIGHLINE (b, mapping[FILE0])); | | 1681 | printf_output ("%dc\n", D_HIGHLINE (b, mapping[FILE0])); |
1682 | break; | | 1682 | break; |
1683 | default: | | 1683 | default: |
1684 | printf_output ("%d,%dc\n", | | 1684 | printf_output ("%d,%dc\n", |
1685 | D_LOWLINE (b, mapping[FILE0]), | | 1685 | D_LOWLINE (b, mapping[FILE0]), |
1686 | D_HIGHLINE (b, mapping[FILE0])); | | 1686 | D_HIGHLINE (b, mapping[FILE0])); |
1687 | break; | | 1687 | break; |
1688 | } | | 1688 | } |
1689 | | | 1689 | |
1690 | undotlines (dotlines (b, mapping[FILE2]), | | 1690 | undotlines (dotlines (b, mapping[FILE2]), |
1691 | D_LOWLINE (b, mapping[FILE0]), | | 1691 | D_LOWLINE (b, mapping[FILE0]), |
1692 | D_NUMLINES (b, mapping[FILE2])); | | 1692 | D_NUMLINES (b, mapping[FILE2])); |
1693 | } | | 1693 | } |
1694 | } | | 1694 | } |
1695 | if (finalwrite) printf_output ("w\nq\n"); | | 1695 | if (finalwrite) printf_output ("w\nq\n"); |
1696 | return conflicts_found; | | 1696 | return conflicts_found; |
1697 | } | | 1697 | } |
1698 | | | 1698 | |
1699 | /* | | 1699 | /* |
1700 | * Read from INFILE and output to the standard output file a set of | | 1700 | * Read from INFILE and output to the standard output file a set of |
1701 | * diff3_ blocks DIFF as a merged file. This acts like 'ed file0 | | 1701 | * diff3_ blocks DIFF as a merged file. This acts like 'ed file0 |
1702 | * <[output_diff3_edscript]', except that it works even for binary | | 1702 | * <[output_diff3_edscript]', except that it works even for binary |
1703 | * data or incomplete lines. | | 1703 | * data or incomplete lines. |
1704 | * | | 1704 | * |
1705 | * As before, MAPPING maps from arg list file number to diff file number, | | 1705 | * As before, MAPPING maps from arg list file number to diff file number, |
1706 | * REV_MAPPING is its inverse, | | 1706 | * REV_MAPPING is its inverse, |
1707 | * and FILE0, FILE1, and FILE2 are the names of the files. | | 1707 | * and FILE0, FILE1, and FILE2 are the names of the files. |
1708 | * | | 1708 | * |
1709 | * Returns 1 if conflicts were found. | | 1709 | * Returns 1 if conflicts were found. |
1710 | */ | | 1710 | */ |
1711 | | | 1711 | |
1712 | static int | | 1712 | static int |
1713 | output_diff3_merge (infile, diff, mapping, rev_mapping, | | 1713 | output_diff3_merge (infile, diff, mapping, rev_mapping, |
1714 | file0, file1, file2) | | 1714 | file0, file1, file2) |
1715 | FILE *infile; | | 1715 | FILE *infile; |
1716 | struct diff3_block *diff; | | 1716 | struct diff3_block *diff; |
1717 | int const mapping[3], rev_mapping[3]; | | 1717 | int const mapping[3], rev_mapping[3]; |
1718 | char const *file0, *file1, *file2; | | 1718 | char const *file0, *file1, *file2; |
1719 | { | | 1719 | { |
1720 | int c, i; | | 1720 | int c, i; |
1721 | char cc; | | 1721 | char cc; |
1722 | int conflicts_found = 0, conflict; | | 1722 | int conflicts_found = 0, conflict; |
1723 | struct diff3_block *b; | | 1723 | struct diff3_block *b; |
1724 | int linesread = 0; | | 1724 | int linesread = 0; |
1725 | | | 1725 | |
1726 | for (b = diff; b; b = b->next) | | 1726 | for (b = diff; b; b = b->next) |
1727 | { | | 1727 | { |
1728 | /* Must do mapping correctly. */ | | 1728 | /* Must do mapping correctly. */ |
1729 | enum diff_type type | | 1729 | enum diff_type type |
1730 | = ((b->correspond == DIFF_ALL) ? | | 1730 | = ((b->correspond == DIFF_ALL) ? |
1731 | DIFF_ALL : | | 1731 | DIFF_ALL : |
1732 | ((enum diff_type) | | 1732 | ((enum diff_type) |
1733 | (((int) DIFF_1ST) | | 1733 | (((int) DIFF_1ST) |
1734 | + rev_mapping[(int) b->correspond - (int) DIFF_1ST]))); | | 1734 | + rev_mapping[(int) b->correspond - (int) DIFF_1ST]))); |
1735 | char const *format_2nd = "<<<<<<< %s\n"; | | 1735 | char const *format_2nd = "<<<<<<< %s\n"; |
1736 | | | 1736 | |
1737 | /* If we aren't supposed to do this output block, skip it. */ | | 1737 | /* If we aren't supposed to do this output block, skip it. */ |
1738 | switch (type) | | 1738 | switch (type) |
1739 | { | | 1739 | { |
1740 | default: continue; | | 1740 | default: continue; |
1741 | case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; | | 1741 | case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; |
1742 | case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; | | 1742 | case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; |
1743 | case DIFF_ALL: if (simple_only) continue; conflict = flagging; | | 1743 | case DIFF_ALL: if (simple_only) continue; conflict = flagging; |
1744 | format_2nd = "||||||| %s\n"; | | 1744 | format_2nd = "||||||| %s\n"; |
1745 | break; | | 1745 | break; |
1746 | } | | 1746 | } |
1747 | | | 1747 | |
1748 | /* Copy I lines from file 0. */ | | 1748 | /* Copy I lines from file 0. */ |
1749 | i = D_LOWLINE (b, FILE0) - linesread - 1; | | 1749 | i = D_LOWLINE (b, FILE0) - linesread - 1; |
1750 | linesread += i; | | 1750 | linesread += i; |
1751 | while (0 <= --i) | | 1751 | while (0 <= --i) |
1752 | do | | 1752 | do |
1753 | { | | 1753 | { |
1754 | c = getc (infile); | | 1754 | c = getc (infile); |
1755 | if (c == EOF) | | 1755 | if (c == EOF) |
1756 | { | | 1756 | { |
1757 | if (ferror (infile)) | | 1757 | if (ferror (infile)) |
1758 | diff3_perror_with_exit ("input file"); | | 1758 | diff3_perror_with_exit ("input file"); |
1759 | else if (feof (infile)) | | 1759 | else if (feof (infile)) |
1760 | diff3_fatal ("input file shrank"); | | 1760 | diff3_fatal ("input file shrank"); |
1761 | } | | 1761 | } |
1762 | cc = c; | | 1762 | cc = c; |
1763 | write_output (&cc, 1); | | 1763 | write_output (&cc, 1); |
1764 | } | | 1764 | } |
1765 | while (c != '\n'); | | 1765 | while (c != '\n'); |
1766 | | | 1766 | |
1767 | if (conflict) | | 1767 | if (conflict) |
1768 | { | | 1768 | { |
1769 | conflicts_found = 1; | | 1769 | conflicts_found = 1; |
1770 | | | 1770 | |
1771 | if (type == DIFF_ALL) | | 1771 | if (type == DIFF_ALL) |
1772 | { | | 1772 | { |
1773 | /* Put in lines from FILE0 with bracket. */ | | 1773 | /* Put in lines from FILE0 with bracket. */ |
1774 | printf_output ("<<<<<<< %s\n", file0); | | 1774 | printf_output ("<<<<<<< %s\n", file0); |
1775 | for (i = 0; | | 1775 | for (i = 0; |
1776 | i < D_NUMLINES (b, mapping[FILE0]); | | 1776 | i < D_NUMLINES (b, mapping[FILE0]); |
1777 | i++) | | 1777 | i++) |
1778 | write_output (D_RELNUM (b, mapping[FILE0], i), | | 1778 | write_output (D_RELNUM (b, mapping[FILE0], i), |
1779 | D_RELLEN (b, mapping[FILE0], i)); | | 1779 | D_RELLEN (b, mapping[FILE0], i)); |
1780 | } | | 1780 | } |
1781 | | | 1781 | |
1782 | if (show_2nd) | | 1782 | if (show_2nd) |
1783 | { | | 1783 | { |
1784 | /* Put in lines from FILE1 with bracket. */ | | 1784 | /* Put in lines from FILE1 with bracket. */ |
1785 | printf_output (format_2nd, file1); | | 1785 | printf_output (format_2nd, file1); |
1786 | for (i = 0; | | 1786 | for (i = 0; |
1787 | i < D_NUMLINES (b, mapping[FILE1]); | | 1787 | i < D_NUMLINES (b, mapping[FILE1]); |
1788 | i++) | | 1788 | i++) |
1789 | write_output (D_RELNUM (b, mapping[FILE1], i), | | 1789 | write_output (D_RELNUM (b, mapping[FILE1], i), |
1790 | D_RELLEN (b, mapping[FILE1], i)); | | 1790 | D_RELLEN (b, mapping[FILE1], i)); |
1791 | } | | 1791 | } |
1792 | | | 1792 | |
1793 | printf_output ("=======\n"); | | 1793 | printf_output ("=======\n"); |
1794 | } | | 1794 | } |
1795 | | | 1795 | |
1796 | /* Put in lines from FILE2. */ | | 1796 | /* Put in lines from FILE2. */ |
1797 | for (i = 0; | | 1797 | for (i = 0; |
1798 | i < D_NUMLINES (b, mapping[FILE2]); | | 1798 | i < D_NUMLINES (b, mapping[FILE2]); |
1799 | i++) | | 1799 | i++) |
1800 | write_output (D_RELNUM (b, mapping[FILE2], i), | | 1800 | write_output (D_RELNUM (b, mapping[FILE2], i), |
1801 | D_RELLEN (b, mapping[FILE2], i)); | | 1801 | D_RELLEN (b, mapping[FILE2], i)); |
1802 | | | 1802 | |
1803 | if (conflict) | | 1803 | if (conflict) |
1804 | printf_output (">>>>>>> %s\n", file2); | | 1804 | printf_output (">>>>>>> %s\n", file2); |
1805 | | | 1805 | |
1806 | /* Skip I lines in file 0. */ | | 1806 | /* Skip I lines in file 0. */ |
1807 | i = D_NUMLINES (b, FILE0); | | 1807 | i = D_NUMLINES (b, FILE0); |
1808 | linesread += i; | | 1808 | linesread += i; |
1809 | while (0 <= --i) | | 1809 | while (0 <= --i) |
1810 | while ((c = getc (infile)) != '\n') | | 1810 | while ((c = getc (infile)) != '\n') |
1811 | if (c == EOF) | | 1811 | if (c == EOF) |
1812 | { | | 1812 | { |
1813 | if (ferror (infile)) | | 1813 | if (ferror (infile)) |
1814 | diff3_perror_with_exit ("input file"); | | 1814 | diff3_perror_with_exit ("input file"); |
1815 | else if (feof (infile)) | | 1815 | else if (feof (infile)) |
1816 | { | | 1816 | { |
1817 | if (i || b->next) | | 1817 | if (i || b->next) |
1818 | diff3_fatal ("input file shrank"); | | 1818 | diff3_fatal ("input file shrank"); |
1819 | return conflicts_found; | | 1819 | return conflicts_found; |
1820 | } | | 1820 | } |
1821 | } | | 1821 | } |
1822 | } | | 1822 | } |
1823 | /* Copy rest of common file. */ | | 1823 | /* Copy rest of common file. */ |
1824 | while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile))) | | 1824 | while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile))) |
1825 | { | | 1825 | { |
1826 | cc = c; | | 1826 | cc = c; |
1827 | write_output (&cc, 1); | | 1827 | write_output (&cc, 1); |
1828 | } | | 1828 | } |
1829 | return conflicts_found; | | 1829 | return conflicts_found; |
1830 | } | | 1830 | } |
1831 | | | 1831 | |
1832 | /* | | 1832 | /* |
1833 | * Reverse the order of the list of diff3 blocks. | | 1833 | * Reverse the order of the list of diff3 blocks. |
1834 | */ | | 1834 | */ |
1835 | static struct diff3_block * | | 1835 | static struct diff3_block * |
1836 | reverse_diff3_blocklist (diff) | | 1836 | reverse_diff3_blocklist (diff) |
1837 | struct diff3_block *diff; | | 1837 | struct diff3_block *diff; |
1838 | { | | 1838 | { |
1839 | register struct diff3_block *tmp, *next, *prev; | | 1839 | register struct diff3_block *tmp, *next, *prev; |
1840 | | | 1840 | |
1841 | for (tmp = diff, prev = 0; tmp; tmp = next) | | 1841 | for (tmp = diff, prev = 0; tmp; tmp = next) |
1842 | { | | 1842 | { |
1843 | next = tmp->next; | | 1843 | next = tmp->next; |
1844 | tmp->next = prev; | | 1844 | tmp->next = prev; |
1845 | prev = tmp; | | 1845 | prev = tmp; |
1846 | } | | 1846 | } |
1847 | | | 1847 | |
1848 | return prev; | | 1848 | return prev; |
1849 | } | | 1849 | } |
1850 | | | 1850 | |
1851 | static size_t | | 1851 | static size_t |
1852 | myread (fd, ptr, size) | | 1852 | myread (fd, ptr, size) |
1853 | int fd; | | 1853 | int fd; |
1854 | char *ptr; | | 1854 | char *ptr; |
1855 | size_t size; | | 1855 | size_t size; |
1856 | { | | 1856 | { |
1857 | ssize_t result = read (fd, ptr, size); | | 1857 | ssize_t result = read (fd, ptr, size); |
1858 | if (result == -1) | | 1858 | if (result == -1) |
1859 | diff3_perror_with_exit ("read failed"); | | 1859 | diff3_perror_with_exit ("read failed"); |
1860 | return (size_t)result; | | 1860 | return (size_t)result; |
1861 | } | | 1861 | } |
1862 | | | 1862 | |
1863 | static void | | 1863 | static void |
1864 | diff3_fatal (string) | | 1864 | diff3_fatal (string) |
1865 | char const *string; | | 1865 | char const *string; |
1866 | { | | 1866 | { |
1867 | diff_error ("%s", string, 0); | | 1867 | diff_error ("%s", string, 0); |
1868 | DIFF3_ABORT (2); | | 1868 | DIFF3_ABORT (2); |
1869 | } | | 1869 | } |
1870 | | | 1870 | |
1871 | static void | | 1871 | static void |
1872 | diff3_perror_with_exit (string) | | 1872 | diff3_perror_with_exit (string) |
1873 | char const *string; | | 1873 | char const *string; |
1874 | { | | 1874 | { |
1875 | perror_with_name (string); | | 1875 | perror_with_name (string); |
1876 | DIFF3_ABORT (2); | | 1876 | DIFF3_ABORT (2); |
1877 | } | | 1877 | } |
1878 | | | 1878 | |
1879 | static void | | 1879 | static void |
1880 | initialize_main (argcp, argvp) | | 1880 | initialize_main (argcp, argvp) |
1881 | int *argcp; | | 1881 | int *argcp; |
1882 | char ***argvp; | | 1882 | char ***argvp; |
1883 | { | | 1883 | { |
1884 | always_text = 0; | | 1884 | always_text = 0; |
1885 | edscript = 0; | | 1885 | edscript = 0; |
1886 | flagging = 0; | | 1886 | flagging = 0; |
1887 | tab_align_flag = 0; | | 1887 | tab_align_flag = 0; |
1888 | simple_only = 0; | | 1888 | simple_only = 0; |
1889 | overlap_only = 0; | | 1889 | overlap_only = 0; |
1890 | show_2nd = 0; | | 1890 | show_2nd = 0; |
1891 | finalwrite = 0; | | 1891 | finalwrite = 0; |
1892 | merge = 0; | | 1892 | merge = 0; |
1893 | diff_program_name = (*argvp)[0]; | | 1893 | diff_program_name = (*argvp)[0]; |
1894 | outfile = NULL; | | 1894 | outfile = NULL; |
1895 | } | | 1895 | } |
1896 | | | 1896 | |
1897 | static void | | 1897 | static void |
1898 | free_diff_blocks(p) | | 1898 | free_diff_blocks(p) |
1899 | struct diff_block *p; | | 1899 | struct diff_block *p; |
1900 | { | | 1900 | { |
1901 | register struct diff_block *next; | | 1901 | register struct diff_block *next; |
1902 | | | 1902 | |
1903 | while (p) | | 1903 | while (p) |
1904 | { | | 1904 | { |
1905 | next = p->next; | | 1905 | next = p->next; |
1906 | if (p->lines[0]) free(p->lines[0]); | | 1906 | if (p->lines[0]) free(p->lines[0]); |
1907 | if (p->lines[1]) free(p->lines[1]); | | 1907 | if (p->lines[1]) free(p->lines[1]); |
1908 | if (p->lengths[0]) free(p->lengths[0]); | | 1908 | if (p->lengths[0]) free(p->lengths[0]); |
1909 | if (p->lengths[1]) free(p->lengths[1]); | | 1909 | if (p->lengths[1]) free(p->lengths[1]); |
1910 | free(p); | | 1910 | free(p); |
1911 | p = next; | | 1911 | p = next; |
1912 | } | | 1912 | } |
1913 | } | | 1913 | } |
1914 | | | 1914 | |
1915 | static void | | 1915 | static void |
1916 | free_diff3_blocks(p) | | 1916 | free_diff3_blocks(p) |
1917 | struct diff3_block *p; | | 1917 | struct diff3_block *p; |
1918 | { | | 1918 | { |
1919 | register struct diff3_block *next; | | 1919 | register struct diff3_block *next; |
1920 | | | 1920 | |
1921 | while (p) | | 1921 | while (p) |
1922 | { | | 1922 | { |
1923 | next = p->next; | | 1923 | next = p->next; |
1924 | if (p->lines[0]) free(p->lines[0]); | | 1924 | if (p->lines[0]) free(p->lines[0]); |
1925 | if (p->lines[1]) free(p->lines[1]); | | 1925 | if (p->lines[1]) free(p->lines[1]); |
1926 | if (p->lines[2]) free(p->lines[2]); | | 1926 | if (p->lines[2]) free(p->lines[2]); |
1927 | if (p->lengths[0]) free(p->lengths[0]); | | 1927 | if (p->lengths[0]) free(p->lengths[0]); |
1928 | if (p->lengths[1]) free(p->lengths[1]); | | 1928 | if (p->lengths[1]) free(p->lengths[1]); |
1929 | if (p->lengths[2]) free(p->lengths[2]); | | 1929 | if (p->lengths[2]) free(p->lengths[2]); |
1930 | free(p); | | 1930 | free(p); |
1931 | p = next; | | 1931 | p = next; |
1932 | } | | 1932 | } |
1933 | } | | 1933 | } |