Don't include version.h.
[platform/upstream/coreutils.git] / src / join.c
1 /* join - join lines of two files on a common field
2    Copyright (C) 1991, 1995 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18    Written by Mike Haertel, mike@gnu.ai.mit.edu.  */
19
20 #include <config.h>
21
22 #ifdef __GNUC__
23 #define alloca __builtin_alloca
24 #else /* not __GNUC__ */
25 #if HAVE_ALLOCA_H
26 #include <alloca.h>
27 #else /* not HAVE_ALLOCA_H */
28 #ifdef _AIX
29  #pragma alloca
30 #else /* not _AIX */
31 char *alloca ();
32 #endif /* not _AIX */
33 #endif /* not HAVE_ALLOCA_H */
34 #endif /* not __GNUC__ */
35
36 /* Get isblank from GNU libc.  */
37 #define _GNU_SOURCE
38
39 #include <stdio.h>
40 #define NDEBUG
41 #include <assert.h>
42 #include <sys/types.h>
43 #include <getopt.h>
44
45 #if HAVE_LIMITS_H
46 # include <limits.h>
47 #endif
48
49 #ifndef UINT_MAX
50 # define UINT_MAX ((unsigned int) ~(unsigned int) 0)
51 #endif
52
53 #ifndef INT_MAX
54 # define INT_MAX ((int) (UINT_MAX >> 1))
55 #endif
56
57 #if _LIBC || STDC_HEADERS
58 # define TOLOWER(c) tolower (c)
59 #else
60 # define TOLOWER(c) (ISUPPER (c) ? tolower (c) : (c))
61 #endif
62
63 #include "system.h"
64 #include "long-options.h"
65 #include "xstrtol.h"
66 #include "error.h"
67
68 #define join system_join
69
70 char *xmalloc ();
71 char *xrealloc ();
72
73 /* Undefine, to avoid warning about redefinition on some systems.  */
74 #undef min
75 #undef max
76 #define min(A, B) ((A) < (B) ? (A) : (B))
77 #define max(A, B) ((A) > (B) ? (A) : (B))
78
79 /* An element of the list identifying which fields to print for each
80    output line.  */
81 struct outlist
82   {
83     /* File number: 0, 1, or 2.  0 means use the join field.
84        1 means use the first file argument, 2 the second.  */
85     int file;
86
87     /* Field index (zero-based), specified only when FILE is 1 or 2.  */
88     int field;
89
90     struct outlist *next;
91   };
92
93 /* A field of a line.  */
94 struct field
95   {
96     const char *beg;            /* First character in field.  */
97     size_t len;                 /* The length of the field.  */
98   };
99
100 /* A line read from an input file.  Newlines are not stored.  */
101 struct line
102   {
103     char *beg;                  /* First character in line.  */
104     char *lim;                  /* Character after last character in line.  */
105     int nfields;                /* Number of elements in `fields'.  */
106     int nfields_allocated;      /* Number of elements in `fields'.  */
107     struct field *fields;
108   };
109
110 /* One or more consecutive lines read from a file that all have the
111    same join field value.  */
112 struct seq
113   {
114     int count;                  /* Elements used in `lines'.  */
115     int alloc;                  /* Elements allocated in `lines'.  */
116     struct line *lines;
117   };
118
119 /* The name this program was run with.  */
120 char *program_name;
121
122 /* If nonzero, print unpairable lines in file 1 or 2.  */
123 static int print_unpairables_1, print_unpairables_2;
124
125 /* If nonzero, print pairable lines.  */
126 static int print_pairables;
127
128 /* Empty output field filler.  */
129 static char *empty_filler;
130
131 /* Field to join on.  */
132 static int join_field_1, join_field_2;
133
134 /* List of fields to print.  */
135 static struct outlist outlist_head;
136
137 /* Last element in `outlist', where a new element can be added.  */
138 static struct outlist *outlist_end = &outlist_head;
139
140 /* Tab character separating fields; if this is NUL fields are separated
141    by any nonempty string of white space, otherwise by exactly one
142    tab character.  */
143 static char tab;
144
145 /* When using getopt_long_only, no long option can start with
146    a character that is a short option.  */
147 static struct option const longopts[] =
148 {
149   {"ignore-case", no_argument, NULL, 'i'},
150   {"j", required_argument, NULL, 'j'},
151   {"j1", required_argument, NULL, '1'},
152   {"j2", required_argument, NULL, '2'},
153   {NULL, 0, NULL, 0}
154 };
155
156 /* Used to print non-joining lines */
157 static struct line uni_blank;
158
159 /* If nonzero, ignore case when comparing join fields.  */
160 static int ignore_case;
161
162 static void
163 usage (int status)
164 {
165   if (status != 0)
166     fprintf (stderr, _("Try `%s --help' for more information.\n"),
167              program_name);
168   else
169     {
170       printf (_("\
171 Usage: %s [OPTION]... FILE1 FILE2\n\
172 "),
173               program_name);
174       printf (_("\
175 For each pair of input lines with identical join fields, write a line to\n\
176 standard output.  The default join field is the first, delimited\n\
177 by whitespace.  When FILE1 or FILE2 (not both) is -, read standard input.\n\
178 \n\
179   -a SIDE          print unpairable lines coming from file SIDE\n\
180   -e EMPTY         replace missing input fields with EMPTY\n\
181   -i, --ignore-case ignore differences in case when comparing fields\n\
182   -j FIELD         (Obsolescent) equivalent to `-1 FIELD -2 FIELD'\n\
183   -j1 FIELD        (Obsolescent) equivalent to `-1 FIELD'\n\
184   -j2 FIELD        (Obsolescent) equivalent to `-2 FIELD'\n\
185   -1 FIELD         join on this FIELD of file 1\n\
186   -2 FIELD         join on this FIELD of file 2\n\
187   -o FORMAT        obey FORMAT while constructing output line\n\
188   -t CHAR          use CHAR as input and output field separator\n\
189   -v SIDE          like -a SIDE, but suppress joined output lines\n\
190   --help           display this help and exit\n\
191   --version        output version information and exit\n\
192 \n\
193 Unless -t CHAR is given, leading blanks separate fields and are ignored,\n\
194 else fields are separated by CHAR.  Any FIELD is a field number counted\n\
195 from 1.  FORMAT is one or more comma or blank separated specifications,\n\
196 each being `SIDE.FIELD' or `0'.  Default FORMAT outputs the join field,\n\
197 the remaining fields from FILE1, the remaining fields from FILE2, all\n\
198 separated by CHAR.\n\
199 "));
200     }
201   exit (status);
202 }
203
204 /* Like memcmp, but ignore differences in case.  */
205
206 static int
207 memcasecmp (const void *vs1, const void *vs2, size_t n)
208 {
209   unsigned int i;
210   unsigned char *s1 = (unsigned char *) vs1;
211   unsigned char *s2 = (unsigned char *) vs2;
212   for (i = 0; i < n; i++)
213     {
214       unsigned char u1 = *s1++;
215       unsigned char u2 = *s2++;
216       if (TOLOWER (u1) != TOLOWER (u2))
217         return TOLOWER (u1) - TOLOWER (u2);
218     }
219   return 0;
220 }
221
222 static void
223 ADD_FIELD (struct line *line, const char *field, size_t len)
224 {
225   if (line->nfields >= line->nfields_allocated)
226     {
227       line->nfields_allocated = (3 * line->nfields_allocated) / 2 + 1;
228       line->fields = (struct field *) xrealloc ((char *) line->fields,
229                                                 (line->nfields_allocated
230                                                  * sizeof (struct field)));
231     }
232   line->fields[line->nfields].beg = field;
233   line->fields[line->nfields].len = len;
234   ++(line->nfields);
235 }
236
237 /* Fill in the `fields' structure in LINE.  */
238
239 static void
240 xfields (struct line *line)
241 {
242   int i;
243   register char *ptr, *lim;
244
245   ptr = line->beg;
246   lim = line->lim;
247
248   if (!tab)
249     {
250       /* Skip leading blanks before the first field.  */
251       while (ptr < lim && ISSPACE (*ptr))
252         ++ptr;
253     }
254
255   for (i = 0; ptr < lim; ++i)
256     {
257       if (tab)
258         {
259           char *beg;
260
261           beg = ptr;
262           while (ptr < lim && *ptr != tab)
263             ++ptr;
264           ADD_FIELD (line, beg, ptr - beg);
265           if (ptr < lim)
266             ++ptr;
267         }
268       else
269         {
270           char *beg;
271
272           beg = ptr;
273           while (ptr < lim && !ISSPACE (*ptr))
274             ++ptr;
275           ADD_FIELD (line, beg, ptr - beg);
276           while (ptr < lim && ISSPACE (*ptr))
277             ++ptr;
278         }
279     }
280
281   if (ptr > line->beg && ((tab && ISSPACE (ptr[-1])) || ptr[-1] == tab))
282     {
283       /* Add one more (empty) field because the last character of the
284          line was a delimiter.  */
285       ADD_FIELD (line, NULL, 0);
286     }
287 }
288
289 /* Read a line from FP into LINE and split it into fields.
290    Return 0 if EOF, 1 otherwise.  */
291
292 static int
293 get_line (FILE *fp, struct line *line)
294 {
295   static int linesize = 80;
296   int c, i;
297   char *ptr;
298
299   if (feof (fp))
300     return 0;
301
302   ptr = xmalloc (linesize);
303
304   for (i = 0; (c = getc (fp)) != EOF && c != '\n'; ++i)
305     {
306       if (i == linesize)
307         {
308           linesize *= 2;
309           ptr = xrealloc (ptr, linesize);
310         }
311       ptr[i] = c;
312     }
313
314   if (c == EOF && i == 0)
315     {
316       free (ptr);
317       return 0;
318     }
319
320   line->beg = ptr;
321   line->lim = line->beg + i;
322   line->nfields_allocated = 0;
323   line->nfields = 0;
324   line->fields = NULL;
325   xfields (line);
326   return 1;
327 }
328
329 static void
330 freeline (struct line *line)
331 {
332   free ((char *) line->fields);
333   free (line->beg);
334   line->beg = NULL;
335 }
336
337 static void
338 initseq (struct seq *seq)
339 {
340   seq->count = 0;
341   seq->alloc = 1;
342   seq->lines = (struct line *) xmalloc (seq->alloc * sizeof (struct line));
343 }
344
345 /* Read a line from FP and add it to SEQ.  Return 0 if EOF, 1 otherwise.  */
346
347 static int
348 getseq (FILE *fp, struct seq *seq)
349 {
350   if (seq->count == seq->alloc)
351     {
352       seq->alloc *= 2;
353       seq->lines = (struct line *)
354         xrealloc ((char *) seq->lines, seq->alloc * sizeof (struct line));
355     }
356
357   if (get_line (fp, &seq->lines[seq->count]))
358     {
359       ++seq->count;
360       return 1;
361     }
362   return 0;
363 }
364
365 static void
366 delseq (struct seq *seq)
367 {
368   int i;
369   for (i = 0; i < seq->count; i++)
370     if (seq->lines[i].beg)
371       freeline (&seq->lines[i]);
372   free ((char *) seq->lines);
373 }
374
375 /* Return <0 if the join field in LINE1 compares less than the one in LINE2;
376    >0 if it compares greater; 0 if it compares equal.  */
377
378 static int
379 keycmp (struct line *line1, struct line *line2)
380 {
381   const char *beg1, *beg2;      /* Start of field to compare in each file.  */
382   int len1, len2;               /* Length of fields to compare.  */
383   int diff;
384
385   if (join_field_1 < line1->nfields)
386     {
387       beg1 = line1->fields[join_field_1].beg;
388       len1 = line1->fields[join_field_1].len;
389     }
390   else
391     {
392       beg1 = NULL;
393       len1 = 0;
394     }
395
396   if (join_field_2 < line2->nfields)
397     {
398       beg2 = line2->fields[join_field_2].beg;
399       len2 = line2->fields[join_field_2].len;
400     }
401   else
402     {
403       beg2 = NULL;
404       len2 = 0;
405     }
406
407   if (len1 == 0)
408     return len2 == 0 ? 0 : -1;
409   if (len2 == 0)
410     return 1;
411
412   /* Use an if-statement here rather than a function variable to
413      avoid portability hassles of getting a non-conflicting declaration
414      of memcmp.  */
415   if (ignore_case)
416     diff = memcasecmp (beg1, beg2, min (len1, len2));
417   else
418     diff = memcmp (beg1, beg2, min (len1, len2));
419
420   if (diff)
421     return diff;
422   return len1 - len2;
423 }
424
425 /* Print field N of LINE if it exists and is nonempty, otherwise
426    `empty_filler' if it is nonempty.  */
427
428 static void
429 prfield (int n, struct line *line)
430 {
431   int len;
432
433   if (n < line->nfields)
434     {
435       len = line->fields[n].len;
436       if (len)
437         fwrite (line->fields[n].beg, 1, len, stdout);
438       else if (empty_filler)
439         fputs (empty_filler, stdout);
440     }
441   else if (empty_filler)
442     fputs (empty_filler, stdout);
443 }
444
445 /* Print the join of LINE1 and LINE2.  */
446
447 static void
448 prjoin (struct line *line1, struct line *line2)
449 {
450   const struct outlist *outlist;
451
452   outlist = outlist_head.next;
453   if (outlist)
454     {
455       const struct outlist *o;
456
457       o = outlist;
458       while (1)
459         {
460           int field;
461           struct line *line;
462
463           if (o->file == 0)
464             {
465               if (line1 == &uni_blank)
466                 {
467                   line = line2;
468                   field = join_field_2;
469                 }
470               else
471                 {
472                   line = line1;
473                   field = join_field_1;
474                 }
475             }
476           else
477             {
478               line = (o->file == 1 ? line1 : line2);
479               field = o->field;
480             }
481           prfield (field, line);
482           o = o->next;
483           if (o == NULL)
484             break;
485           putchar (tab ? tab : ' ');
486         }
487       putchar ('\n');
488     }
489   else
490     {
491       int i;
492
493       if (line1 == &uni_blank)
494         {
495           struct line *t;
496           t = line1;
497           line1 = line2;
498           line2 = t;
499         }
500       prfield (join_field_1, line1);
501       for (i = 0; i < join_field_1 && i < line1->nfields; ++i)
502         {
503           putchar (tab ? tab : ' ');
504           prfield (i, line1);
505         }
506       for (i = join_field_1 + 1; i < line1->nfields; ++i)
507         {
508           putchar (tab ? tab : ' ');
509           prfield (i, line1);
510         }
511
512       for (i = 0; i < join_field_2 && i < line2->nfields; ++i)
513         {
514           putchar (tab ? tab : ' ');
515           prfield (i, line2);
516         }
517       for (i = join_field_2 + 1; i < line2->nfields; ++i)
518         {
519           putchar (tab ? tab : ' ');
520           prfield (i, line2);
521         }
522       putchar ('\n');
523     }
524 }
525
526 /* Print the join of the files in FP1 and FP2.  */
527
528 static void
529 join (FILE *fp1, FILE *fp2)
530 {
531   struct seq seq1, seq2;
532   struct line line;
533   int diff, i, j, eof1, eof2;
534
535   /* Read the first line of each file.  */
536   initseq (&seq1);
537   getseq (fp1, &seq1);
538   initseq (&seq2);
539   getseq (fp2, &seq2);
540
541   while (seq1.count && seq2.count)
542     {
543       diff = keycmp (&seq1.lines[0], &seq2.lines[0]);
544       if (diff < 0)
545         {
546           if (print_unpairables_1)
547             prjoin (&seq1.lines[0], &uni_blank);
548           freeline (&seq1.lines[0]);
549           seq1.count = 0;
550           getseq (fp1, &seq1);
551           continue;
552         }
553       if (diff > 0)
554         {
555           if (print_unpairables_2)
556             prjoin (&uni_blank, &seq2.lines[0]);
557           freeline (&seq2.lines[0]);
558           seq2.count = 0;
559           getseq (fp2, &seq2);
560           continue;
561         }
562
563       /* Keep reading lines from file1 as long as they continue to
564          match the current line from file2.  */
565       eof1 = 0;
566       do
567         if (!getseq (fp1, &seq1))
568           {
569             eof1 = 1;
570             ++seq1.count;
571             break;
572           }
573       while (!keycmp (&seq1.lines[seq1.count - 1], &seq2.lines[0]));
574
575       /* Keep reading lines from file2 as long as they continue to
576          match the current line from file1.  */
577       eof2 = 0;
578       do
579         if (!getseq (fp2, &seq2))
580           {
581             eof2 = 1;
582             ++seq2.count;
583             break;
584           }
585       while (!keycmp (&seq1.lines[0], &seq2.lines[seq2.count - 1]));
586
587       if (print_pairables)
588         {
589           for (i = 0; i < seq1.count - 1; ++i)
590             for (j = 0; j < seq2.count - 1; ++j)
591               prjoin (&seq1.lines[i], &seq2.lines[j]);
592         }
593
594       for (i = 0; i < seq1.count - 1; ++i)
595         freeline (&seq1.lines[i]);
596       if (!eof1)
597         {
598           seq1.lines[0] = seq1.lines[seq1.count - 1];
599           seq1.count = 1;
600         }
601       else
602         seq1.count = 0;
603
604       for (i = 0; i < seq2.count - 1; ++i)
605         freeline (&seq2.lines[i]);
606       if (!eof2)
607         {
608           seq2.lines[0] = seq2.lines[seq2.count - 1];
609           seq2.count = 1;
610         }
611       else
612         seq2.count = 0;
613     }
614
615   if (print_unpairables_1 && seq1.count)
616     {
617       prjoin (&seq1.lines[0], &uni_blank);
618       freeline (&seq1.lines[0]);
619       while (get_line (fp1, &line))
620         {
621           prjoin (&line, &uni_blank);
622           freeline (&line);
623         }
624     }
625
626   if (print_unpairables_2 && seq2.count)
627     {
628       prjoin (&uni_blank, &seq2.lines[0]);
629       freeline (&seq2.lines[0]);
630       while (get_line (fp2, &line))
631         {
632           prjoin (&uni_blank, &line);
633           freeline (&line);
634         }
635     }
636
637   delseq (&seq1);
638   delseq (&seq2);
639 }
640
641 /* Add a field spec for field FIELD of file FILE to `outlist'.  */
642
643 static void
644 add_field (int file, int field)
645 {
646   struct outlist *o;
647
648   assert (file == 0 || file == 1 || file == 2);
649   assert (field >= 0);
650
651   o = (struct outlist *) xmalloc (sizeof (struct outlist));
652   o->file = file;
653   o->field = field;
654   o->next = NULL;
655
656   /* Add to the end of the list so the fields are in the right order.  */
657   outlist_end->next = o;
658   outlist_end = o;
659 }
660
661 /* Convert a single field specifier string, S, to a *FILE_INDEX, *FIELD_INDEX
662    pair.  In S, the field index string is 1-based; *FIELD_INDEX is zero-based.
663    If S is valid, return zero.  Otherwise, give a diagnostic, don't update
664    *FILE_INDEX or *FIELD_INDEX, and return nonzero.  */
665
666 static int
667 decode_field_spec (const char *s, int *file_index, int *field_index)
668 {
669   int valid = 0;
670
671   /* The first character must be 0, 1, or 2.  */
672   switch (s[0])
673     {
674     case '0':
675       if (s[1] == '\0')
676         {
677           *file_index = 0;
678           /* Leave *field_index undefined.  */
679           valid = 1;
680         }
681       else
682         {
683           /* `0' must be all alone -- no `.FIELD'.  */
684           error (0, 0, _("invalid field specifier: `%s'"), s);
685         }
686       break;
687
688     case '1':
689     case '2':
690       if (s[1] == '.' && s[2] != '\0')
691         {
692           strtol_error s_err;
693           long int tmp_long;
694
695           s_err = xstrtol (s + 2, NULL, 10, &tmp_long, NULL);
696           if (s_err != LONGINT_OK || tmp_long <= 0 || tmp_long > INT_MAX)
697             {
698               error (0, 0, _("invalid field number: `%s'"), s + 2);
699             }
700           else
701             {
702               *file_index = s[0] - '0';
703               /* Convert to a zero-based index.  */
704               *field_index = (int) tmp_long - 1;
705               valid = 1;
706             }
707         }
708       break;
709
710     default:
711       error (0, 0, _("invalid file number in field spec: `%s'"), s);
712       break;
713     }
714   return !valid;
715 }
716
717 /* Add the comma or blank separated field spec(s) in STR to `outlist'.
718    Return nonzero to indicate failure.  */
719
720 static int
721 add_field_list (const char *c_str)
722 {
723   char *p, *str;
724
725   /* Make a writable copy of c_str.  */
726   str = (char *) alloca (strlen (c_str) + 1);
727   strcpy (str, c_str);
728
729   p = str;
730   do
731     {
732       int invalid;
733       int file_index, field_index;
734       char *spec_item = p;
735
736       p = strpbrk (p, ", \t");
737       if (p)
738         *p++ = 0;
739       invalid = decode_field_spec (spec_item, &file_index, &field_index);
740       if (invalid)
741         return 1;
742       add_field (file_index, field_index);
743       uni_blank.nfields = max (uni_blank.nfields, field_index);
744     }
745   while (p);
746   return 0;
747 }
748
749 /* Create a blank line with COUNT fields separated by tabs.  */
750
751 void
752 make_blank (struct line *blank, int count)
753 {
754   int i;
755   blank->nfields = count;
756   blank->beg = xmalloc (blank->nfields + 1);
757   blank->fields = (struct field *) xmalloc (sizeof (struct field) * count);
758   for (i = 0; i < blank->nfields; i++)
759     {
760       blank->beg[i] = '\t';
761       blank->fields[i].beg = &blank->beg[i];
762       blank->fields[i].len = 0;
763     }
764   blank->beg[i] = '\0';
765   blank->lim = &blank->beg[i];
766 }
767
768 void
769 main (int argc, char **argv)
770 {
771   char *names[2];
772   FILE *fp1, *fp2;
773   int optc, prev_optc = 0, nfiles;
774
775   program_name = argv[0];
776   setlocale (LC_ALL, "");
777   bindtextdomain (PACKAGE, LOCALEDIR);
778   textdomain (PACKAGE);
779
780   /* Initialize this before parsing options.  In parsing options,
781      it may be increased.  */
782   uni_blank.nfields = 1;
783
784   parse_long_options (argc, argv, "join", PACKAGE_VERSION, usage);
785
786   nfiles = 0;
787   print_pairables = 1;
788
789   while ((optc = getopt_long_only (argc, argv, "-a:e:i1:2:o:t:v:", longopts,
790                                    (int *) 0)) != EOF)
791     {
792       long int val;
793
794       switch (optc)
795         {
796         case 0:
797           break;
798
799         case 'v':
800             print_pairables = 0;
801             /* Fall through.  */
802
803         case 'a':
804           if (xstrtol (optarg, NULL, 10, &val, NULL) != LONGINT_OK
805               || (val != 1 && val != 2))
806             error (2, 0, _("invalid field number: `%s'"), optarg);
807           if (val == 1)
808             print_unpairables_1 = 1;
809           else
810             print_unpairables_2 = 1;
811           break;
812
813         case 'e':
814           empty_filler = optarg;
815           break;
816
817         case 'i':
818           ignore_case = 1;
819           break;
820
821         case '1':
822           if (xstrtol (optarg, NULL, 10, &val, NULL) != LONGINT_OK
823               || val <= 0 || val > INT_MAX)
824             {
825               error (2, 0, _("invalid field number for file 1: `%s'"), optarg);
826             }
827           join_field_1 = (int) val - 1;
828           break;
829
830         case '2':
831           if (xstrtol (optarg, NULL, 10, &val, NULL) != LONGINT_OK
832               || val <= 0 || val > INT_MAX)
833             error (2, 0, _("invalid field number for file 2: `%s'"), optarg);
834           join_field_2 = (int) val - 1;
835           break;
836
837         case 'j':
838           if (xstrtol (optarg, NULL, 10, &val, NULL) != LONGINT_OK
839               || val <= 0 || val > INT_MAX)
840             error (2, 0, _("invalid field number: `%s'"), optarg);
841           join_field_1 = join_field_2 = (int) val - 1;
842           break;
843
844         case 'o':
845           if (add_field_list (optarg))
846             exit (1);
847           break;
848
849         case 't':
850           tab = *optarg;
851           break;
852
853         case 1:         /* Non-option argument.  */
854           if (prev_optc == 'o' && optind <= argc - 2)
855             {
856               if (add_field_list (optarg))
857                 exit (1);
858
859               /* Might be continuation of args to -o.  */
860               continue;         /* Don't change `prev_optc'.  */
861             }
862
863           if (nfiles > 1)
864             {
865               error (0, 0, _("too many non-option arguments"));
866               usage (1);
867             }
868           names[nfiles++] = optarg;
869           break;
870
871         case '?':
872           usage (1);
873         }
874       prev_optc = optc;
875     }
876
877   /* Now that we've seen the options, we can construct the blank line
878      structure.  */
879   make_blank (&uni_blank, uni_blank.nfields);
880
881   if (nfiles != 2)
882     {
883       error (0, 0, _("too few non-option arguments"));
884       usage (1);
885     }
886
887   fp1 = strcmp (names[0], "-") ? fopen (names[0], "r") : stdin;
888   if (!fp1)
889     error (1, errno, "%s", names[0]);
890   fp2 = strcmp (names[1], "-") ? fopen (names[1], "r") : stdin;
891   if (!fp2)
892     error (1, errno, "%s", names[1]);
893   if (fp1 == fp2)
894     error (1, errno, _("both files cannot be standard input"));
895   join (fp1, fp2);
896
897   if (fp1 != stdin && fclose (fp1) == EOF)
898     error (1, errno, "%s", names[0]);
899   if (fp2 != stdin && fclose (fp2) == EOF)
900     error (1, errno, "%s", names[1]);
901   if ((fp1 == stdin || fp2 == stdin) && fclose (stdin) == EOF)
902     error (1, errno, "-");
903   if (ferror (stdout) || fclose (stdout) == EOF)
904     error (1, errno, _("write error"));
905
906   exit (0);
907 }