| 686 | /* Print the join of the files in FP1 and FP2. */ |
| 687 | |
| 688 | static void |
| 689 | join (FILE *fp1, FILE *fp2) |
| 690 | { |
| 691 | struct seq seq1, seq2; |
| 692 | int diff; |
| 693 | bool eof1, eof2; |
| 694 | |
| 695 | fadvise (fp1, FADVISE_SEQUENTIAL); |
| 696 | fadvise (fp2, FADVISE_SEQUENTIAL); |
| 697 | |
| 698 | /* Read the first line of each file. */ |
| 699 | initseq (&seq1); |
| 700 | getseq (fp1, &seq1, 1); |
| 701 | initseq (&seq2); |
| 702 | getseq (fp2, &seq2, 2); |
| 703 | |
| 704 | if (autoformat) |
| 705 | { |
| 706 | autocount_1 = seq1.count ? seq1.lines[0]->nfields : 0; |
| 707 | autocount_2 = seq2.count ? seq2.lines[0]->nfields : 0; |
| 708 | } |
| 709 | |
| 710 | if (join_header_lines && (seq1.count || seq2.count)) |
| 711 | { |
| 712 | struct line const *hline1 = seq1.count ? seq1.lines[0] : &uni_blank; |
| 713 | struct line const *hline2 = seq2.count ? seq2.lines[0] : &uni_blank; |
| 714 | prjoin (hline1, hline2); |
| 715 | prevline[0] = NULL; |
| 716 | prevline[1] = NULL; |
| 717 | if (seq1.count) |
| 718 | advance_seq (fp1, &seq1, true, 1); |
| 719 | if (seq2.count) |
| 720 | advance_seq (fp2, &seq2, true, 2); |
| 721 | } |
| 722 | |
| 723 | while (seq1.count && seq2.count) |
| 724 | { |
| 725 | diff = keycmp (seq1.lines[0], seq2.lines[0], |
| 726 | join_field_1, join_field_2); |
| 727 | if (diff < 0) |
| 728 | { |
| 729 | if (print_unpairables_1) |
| 730 | prjoin (seq1.lines[0], &uni_blank); |
| 731 | advance_seq (fp1, &seq1, true, 1); |
| 732 | seen_unpairable = true; |
| 733 | continue; |
| 734 | } |
| 735 | if (diff > 0) |
| 736 | { |
| 737 | if (print_unpairables_2) |
| 738 | prjoin (&uni_blank, seq2.lines[0]); |
| 739 | advance_seq (fp2, &seq2, true, 2); |
| 740 | seen_unpairable = true; |
| 741 | continue; |
| 742 | } |
| 743 | |
| 744 | /* Keep reading lines from file1 as long as they continue to |
| 745 | match the current line from file2. */ |