xref: /386bsd/usr/src/usr.bin/sort/sort.c (revision a2142627)
1 /* sort - sort lines of text (with all kinds of options).
2    Copyright (C) 1988, 1991 Free Software Foundation
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18    Written December 1988 by Mike Haertel.
19    The author may be reached (Email) at the address mike@ai.mit.edu,
20    or (US mail) as Mike Haertel c/o Free Software Foundation. */
21 
22 #define _GNU_SOURCE
23 #include <ctype.h>
24 #ifndef isblank
25 #define isblank(c) ((c) == ' ' || (c) == '\t')
26 #endif
27 #include <sys/types.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <fcntl.h>
36 #include <limits.h>
37 
38 static void usage ();
39 
40 #define min(a, b) ((a) < (b) ? (a) : (b))
41 #define UCHAR_LIM (UCHAR_MAX + 1)
42 #define UCHAR(c) ((unsigned char) (c))
43 
44 #ifdef isascii
45 #define ISALNUM(c) (isascii(c) && isalnum(c))
46 #define ISDIGIT(c) (isascii(c) && isdigit(c))
47 #define ISPRINT(c) (isascii(c) && isprint(c))
48 #define ISLOWER(c) (isascii(c) && islower(c))
49 #else
50 #define ISALNUM(c) isalnum(c)
51 #define ISDIGIT(c) isdigit(c)
52 #define ISPRINT(c) isprint(c)
53 #define ISLOWER(c) islower(c)
54 #endif
55 
56 /* The kind of blanks for '-b' to skip in various options. */
57 enum blanktype { bl_start, bl_end, bl_both };
58 
59 /* The name this program was run with. */
60 char *program_name;
61 
62 /* Table of digits. */
63 static int digits[UCHAR_LIM];
64 
65 /* Table of white space. */
66 static int blanks[UCHAR_LIM];
67 
68 /* Table of non-printing characters. */
69 static int nonprinting[UCHAR_LIM];
70 
71 /* Table of non-dictionary characters (not letters, digits, or blanks). */
72 static int nondictionary[UCHAR_LIM];
73 
74 /* Translation table folding lower case to upper. */
75 static char fold_toupper[UCHAR_LIM];
76 
77 /* Table mapping 3-letter month names to integers.
78    Alphabetic order allows binary search. */
79 static struct month
80 {
81   char *name;
82   int val;
83 } monthtab[] =
84 {
85   "APR", 4,
86   "AUG", 8,
87   "DEC", 12,
88   "FEB", 2,
89   "JAN", 1,
90   "JUL", 7,
91   "JUN", 6,
92   "MAR", 3,
93   "MAY", 5,
94   "NOV", 11,
95   "OCT", 10,
96   "SEP", 9
97 };
98 
99 /* During the merge phase, the number of files to merge at once. */
100 #define NMERGE 16
101 
102 /* Initial buffer size for in core sorting.  Will not grow unless a
103    line longer than this is seen. */
104 static int sortalloc =  524288;
105 
106 /* Initial buffer size for in core merge buffers.  Bear in mind that
107    up to NMERGE * mergealloc bytes may be allocated for merge buffers. */
108 static int mergealloc =  16384;
109 
110 /* Guess of average line length. */
111 static int linelength = 30;
112 
113 /* Maximum number of elements for the array(s) of struct line's, in bytes.  */
114 #define LINEALLOC 262144
115 
116 /* Prefix for temporary file names. */
117 static char *prefix;
118 
119 /* Flag to reverse the order of all comparisons. */
120 static int reverse;
121 
122 /* Flag for stable sort.  This turns off the last ditch bytewise
123    comparison of lines, and instead leaves lines in the same order
124    they were read if all keys compare equal.  */
125 static int stable;
126 
127 /* Tab character separating fields.  If NUL, then fields are separated
128    by the empty string between a non-whitespace character and a whitespace
129    character. */
130 static char tab;
131 
132 /* Flag to remove consecutive duplicate lines from the output.
133    Only the last of a sequence of equal lines will be output. */
134 static int unique;
135 
136 /* Nonzero if any of the input files are the standard input. */
137 static int have_read_stdin;
138 
139 /* Lines are held in core as counted strings. */
140 struct line
141 {
142   char *text;			/* Text of the line. */
143   int length;			/* Length not including final newline. */
144   char *keybeg;			/* Start of first key. */
145   char *keylim;			/* Limit of first key. */
146 };
147 
148 /* Arrays of lines. */
149 struct lines
150 {
151   struct line *lines;		/* Dynamically allocated array of lines. */
152   int used;			/* Number of slots used. */
153   int alloc;			/* Number of slots allocated. */
154   int limit;			/* Max number of slots to allocate.  */
155 };
156 
157 /* Input buffers. */
158 struct buffer
159 {
160   char *buf;			/* Dynamically allocated buffer. */
161   int used;			/* Number of bytes used. */
162   int alloc;			/* Number of bytes allocated. */
163   int left;			/* Number of bytes left after line parsing. */
164 };
165 
166 /* Lists of key field comparisons to be tried. */
167 static struct keyfield
168 {
169   int sword;			/* Zero-origin 'word' to start at. */
170   int schar;			/* Additional characters to skip. */
171   int skipsblanks;		/* Skip leading white space at start. */
172   int eword;			/* Zero-origin first word after field. */
173   int echar;			/* Additional characters in field. */
174   int skipeblanks;		/* Skip trailing white space at finish. */
175   int *ignore;			/* Boolean array of characters to ignore. */
176   char *translate;		/* Translation applied to characters. */
177   int numeric;			/* Flag for numeric comparison. */
178   int month;			/* Flag for comparison by month name. */
179   int reverse;			/* Reverse the sense of comparison. */
180   struct keyfield *next;	/* Next keyfield to try. */
181 } keyhead;
182 
183 /* The list of temporary files. */
184 static struct tempnode
185 {
186   char *name;
187   struct tempnode *next;
188 } temphead;
189 
190 /* Clean up any remaining temporary files. */
191 
192 static void
cleanup()193 cleanup ()
194 {
195   struct tempnode *node;
196 
197   for (node = temphead.next; node; node = node->next)
198     unlink (node->name);
199 }
200 
201 /* Allocate N bytes of memory dynamically, with error checking.  */
202 
203 char *
xmalloc(n)204 xmalloc (n)
205      unsigned n;
206 {
207   char *p;
208 
209   p = (char *)malloc (n);
210   if (p == 0)
211     {
212       error (0, 0, "virtual memory exhausted");
213       cleanup ();
214       exit (2);
215     }
216   return p;
217 }
218 
219 /* Change the size of an allocated block of memory P to N bytes,
220    with error checking.
221    If P is NULL, run xmalloc.
222    If N is 0, run free and return NULL.  */
223 
224 char *
xrealloc(p,n)225 xrealloc (p, n)
226      char *p;
227      unsigned n;
228 {
229   if (p == 0)
230     return xmalloc (n);
231   if (n == 0)
232     {
233       free (p);
234       return 0;
235     }
236   p = realloc (p, n);
237   if (p == 0)
238     {
239       error (0, 0, "virtual memory exhausted");
240       cleanup ();
241       exit (2);
242     }
243   return p;
244 }
245 
246 static FILE *
xfopen(file,how)247 xfopen (file, how)
248      char *file, *how;
249 {
250   FILE *fp = strcmp (file, "-") ? fopen (file, how) : stdin;
251 
252   if (fp == 0)
253     {
254       error (0, errno, "%s", file);
255       cleanup ();
256       exit (2);
257     }
258   if (fp == stdin)
259     have_read_stdin = 1;
260   return fp;
261 }
262 
263 static void
xfclose(fp)264 xfclose (fp)
265      FILE *fp;
266 {
267   fflush (fp);
268   if (fp != stdin && fp != stdout)
269     {
270       if (fclose (fp) != 0)
271 	{
272 	  error (0, errno, "error closing file");
273 	  cleanup ();
274 	  exit (2);
275 	}
276     }
277   else
278     /* Allow reading stdin from tty more than once. */
279     clearerr (fp);
280 }
281 
282 static void
xfwrite(buf,size,nelem,fp)283 xfwrite (buf, size, nelem, fp)
284      char *buf;
285      int size, nelem;
286      FILE *fp;
287 {
288   if (fwrite (buf, size, nelem, fp) != nelem)
289     {
290       error (0, errno, "write error");
291       cleanup ();
292       exit (2);
293     }
294 }
295 
296 /* Return a name for a temporary file. */
297 
298 static char *
tempname()299 tempname ()
300 {
301   static int seq;
302   int len = strlen (prefix);
303   char *name = xmalloc (len + 16);
304   struct tempnode *node =
305   (struct tempnode *) xmalloc (sizeof (struct tempnode));
306 
307   if (len && prefix[len - 1] != '/')
308     sprintf (name, "%s/sort%5.5d%5.5d", prefix, getpid (), ++seq);
309   else
310     sprintf (name, "%ssort%5.5d%5.5d", prefix, getpid (), ++seq);
311   node->name = name;
312   node->next = temphead.next;
313   temphead.next = node;
314   return name;
315 }
316 
317 /* Search through the list of temporary files for NAME;
318    remove it if it is found on the list. */
319 
320 static void
zaptemp(name)321 zaptemp (name)
322      char *name;
323 {
324   struct tempnode *node, *temp;
325 
326   for (node = &temphead; node->next; node = node->next)
327     if (!strcmp (name, node->next->name))
328       break;
329   if (node->next)
330     {
331       temp = node->next;
332       unlink (temp->name);
333       free (temp->name);
334       node->next = temp->next;
335       free ((char *) temp);
336     }
337 }
338 
339 /* Initialize the character class tables. */
340 
341 static void
inittables()342 inittables ()
343 {
344   int i;
345 
346   for (i = 0; i < UCHAR_LIM; ++i)
347     {
348       if (isblank (i))
349 	blanks[i] = 1;
350       if (ISDIGIT (i))
351 	digits[i] = 1;
352       if (!ISPRINT (i))
353 	nonprinting[i] = 1;
354       if (!ISALNUM (i) && !isblank (i))
355 	nondictionary[i] = 1;
356       if (ISLOWER (i))
357 	fold_toupper[i] = toupper (i);
358       else
359 	fold_toupper[i] = i;
360     }
361 }
362 
363 /* Initialize BUF, allocating ALLOC bytes initially. */
364 
365 static void
initbuf(buf,alloc)366 initbuf (buf, alloc)
367      struct buffer *buf;
368      int alloc;
369 {
370   buf->alloc = alloc;
371   buf->buf = xmalloc (buf->alloc);
372   buf->used = buf->left = 0;
373 }
374 
375 /* Fill BUF reading from FP, moving buf->left bytes from the end
376    of buf->buf to the beginning first.	If EOF is reached and the
377    file wasn't terminated by a newline, supply one.  Return a count
378    of bytes buffered. */
379 
380 static int
fillbuf(buf,fp)381 fillbuf (buf, fp)
382      struct buffer *buf;
383      FILE *fp;
384 {
385   int cc;
386 
387   bcopy (buf->buf + buf->used - buf->left, buf->buf, buf->left);
388   buf->used = buf->left;
389 
390   while (!feof (fp) && (buf->used == 0 || !memchr (buf->buf, '\n', buf->used)))
391     {
392       if (buf->used == buf->alloc)
393 	{
394 	  buf->alloc *= 2;
395 	  buf->buf = xrealloc (buf->buf, buf->alloc);
396 	}
397       cc = fread (buf->buf + buf->used, 1, buf->alloc - buf->used, fp);
398       if (ferror (fp))
399 	{
400 	  error (0, errno, "read error");
401 	  cleanup ();
402 	  exit (2);
403 	}
404       buf->used += cc;
405     }
406 
407   if (feof (fp) && buf->used && buf->buf[buf->used - 1] != '\n')
408     {
409       if (buf->used == buf->alloc)
410 	{
411 	  buf->alloc *= 2;
412 	  buf->buf = xrealloc (buf->buf, buf->alloc);
413 	}
414       buf->buf[buf->used++] = '\n';
415     }
416 
417   return buf->used;
418 }
419 
420 /* Initialize LINES, allocating space for ALLOC lines initially.
421    LIMIT is the maximum possible number of lines to allocate space
422    for, ever.  */
423 
424 static void
initlines(lines,alloc,limit)425 initlines (lines, alloc, limit)
426      struct lines *lines;
427      int alloc;
428      int limit;
429 {
430   lines->alloc = alloc;
431   lines->lines = (struct line *) xmalloc (lines->alloc * sizeof (struct line));
432   lines->used = 0;
433   lines->limit = limit;
434 }
435 
436 /* Return a pointer to the first character of the field specified
437    by KEY in LINE. */
438 
439 static char *
begfield(line,key)440 begfield (line, key)
441      struct line *line;
442      struct keyfield *key;
443 {
444   register char *ptr = line->text, *lim = ptr + line->length;
445   register int sword = key->sword, schar = key->schar;
446 
447   if (tab)
448     while (ptr < lim && sword--)
449       {
450 	while (ptr < lim && *ptr != tab)
451 	  ++ptr;
452 	if (ptr < lim)
453 	  ++ptr;
454       }
455   else
456     while (ptr < lim && sword--)
457       {
458 	while (ptr < lim && blanks[UCHAR (*ptr)])
459 	  ++ptr;
460 	while (ptr < lim && !blanks[UCHAR (*ptr)])
461 	  ++ptr;
462       }
463 
464   if (key->skipsblanks)
465     while (ptr < lim && blanks[UCHAR (*ptr)])
466       ++ptr;
467 
468   while (ptr < lim && schar--)
469     ++ptr;
470 
471   return ptr;
472 }
473 
474 /* Return the limit of (a pointer to the first character after) the field
475    in LINE specified by KEY. */
476 
477 static char *
limfield(line,key)478 limfield (line, key)
479      struct line *line;
480      struct keyfield *key;
481 {
482   register char *ptr = line->text, *lim = ptr + line->length;
483   register int eword = key->eword, echar = key->echar;
484 
485   if (tab)
486     while (ptr < lim && eword--)
487       {
488 	while (ptr < lim && *ptr != tab)
489 	  ++ptr;
490 	if (ptr < lim && (eword || key->skipeblanks))
491 	  ++ptr;
492       }
493   else
494     while (ptr < lim && eword--)
495       {
496 	while (ptr < lim && blanks[UCHAR (*ptr)])
497 	  ++ptr;
498 	while (ptr < lim && !blanks[UCHAR (*ptr)])
499 	  ++ptr;
500       }
501 
502   if (key->skipeblanks)
503     while (ptr < lim && blanks[UCHAR (*ptr)])
504       ++ptr;
505 
506   while (ptr < lim && echar--)
507     ++ptr;
508 
509   return ptr;
510 }
511 
512 /* Find the lines in BUF, storing pointers and lengths in LINES.
513    Also replace newlines with NULs. */
514 
515 static void
findlines(buf,lines)516 findlines (buf, lines)
517      struct buffer *buf;
518      struct lines *lines;
519 {
520   register char *beg = buf->buf, *lim = buf->buf + buf->used, *ptr;
521   struct keyfield *key = keyhead.next;
522 
523   lines->used = 0;
524 
525   while (beg < lim && (ptr = memchr (beg, '\n', lim - beg))
526 	 && lines->used < lines->limit)
527     {
528       /* There are various places in the code that rely on a NUL
529 	 being at the end of in-core lines; NULs inside the lines
530 	 will not cause trouble, though. */
531       *ptr = '\0';
532 
533       if (lines->used == lines->alloc)
534 	{
535 	  lines->alloc *= 2;
536 	  lines->lines = (struct line *)
537 	    xrealloc ((char *) lines->lines,
538 		      lines->alloc * sizeof (struct line));
539 	}
540 
541       lines->lines[lines->used].text = beg;
542       lines->lines[lines->used].length = ptr - beg;
543 
544       /* Precompute the position of the first key for efficiency. */
545       if (key)
546 	{
547 	  if (key->eword >= 0)
548 	    lines->lines[lines->used].keylim =
549 	      limfield (&lines->lines[lines->used], key);
550 	  else
551 	    lines->lines[lines->used].keylim = ptr;
552 
553 	  if (key->sword >= 0)
554 	    lines->lines[lines->used].keybeg =
555 	      begfield (&lines->lines[lines->used], key);
556 	  else
557 	    {
558 	      if (key->skipsblanks)
559 		while (blanks[UCHAR (*beg)])
560 		  ++beg;
561 	      lines->lines[lines->used].keybeg = beg;
562 	    }
563 	}
564 
565       ++lines->used;
566       beg = ptr + 1;
567     }
568 
569   buf->left = lim - beg;
570 }
571 
572 /* Compare strings A and B containing decimal fractions < 1.  Each string
573    should begin with a decimal point followed immediately by the digits
574    of the fraction.  Strings not of this form are considered to be zero. */
575 
576 static int
fraccompare(a,b)577 fraccompare (a, b)
578      register char *a, *b;
579 {
580   register tmpa = UCHAR (*a), tmpb = UCHAR (*b);
581 
582   if (tmpa == '.' && tmpb == '.')
583     {
584       do
585 	tmpa = UCHAR (*++a), tmpb = UCHAR (*++b);
586       while (tmpa == tmpb && digits[tmpa]);
587       if (digits[tmpa] && digits[tmpb])
588 	return tmpa - tmpb;
589       if (digits[tmpa])
590 	{
591 	  while (tmpa == '0')
592 	    tmpa = UCHAR (*++a);
593 	  if (digits[tmpa])
594 	    return 1;
595 	  return 0;
596 	}
597       if (digits[tmpb])
598 	{
599 	  while (tmpb == '0')
600 	    tmpb = UCHAR (*++b);
601 	  if (digits[tmpb])
602 	    return -1;
603 	  return 0;
604 	}
605       return 0;
606     }
607   else if (tmpa == '.')
608     {
609       do
610 	tmpa = UCHAR (*++a);
611       while (tmpa == '0');
612       if (digits[tmpa])
613 	return 1;
614       return 0;
615     }
616   else if (tmpb == '.')
617     {
618       do
619 	tmpb = UCHAR (*++b);
620       while (tmpb == '0');
621       if (digits[tmpb])
622 	return -1;
623       return 0;
624     }
625   return 0;
626 }
627 
628 /* Compare strings A and B as numbers without explicitly converting them to
629    machine numbers.  Comparatively slow for short strings, but asymptotically
630    hideously fast. */
631 
632 static int
numcompare(a,b)633 numcompare (a, b)
634      register char *a, *b;
635 {
636   register int tmpa, tmpb, loga, logb, tmp;
637 
638   tmpa = UCHAR (*a), tmpb = UCHAR (*b);
639 
640   if (tmpa == '-')
641     {
642       tmpa = UCHAR (*++a);
643       if (tmpb != '-')
644 	{
645 	  if (digits[tmpa] && digits[tmpb])
646 	    return -1;
647 	  return 0;
648 	}
649       tmpb = UCHAR (*++b);
650 
651       while (tmpa == '0')
652 	tmpa = UCHAR (*++a);
653       while (tmpb == '0')
654 	tmpb = UCHAR (*++b);
655 
656       while (tmpa == tmpb && digits[tmpa])
657 	tmpa = UCHAR (*++a), tmpb = UCHAR (*++b);
658 
659       if ((tmpa == '.' && !digits[tmpb]) || (tmpb == '.' && !digits[tmpa]))
660 	return -fraccompare (a, b);
661 
662       if (digits[tmpa])
663 	for (loga = 1; digits[UCHAR (*++a)]; ++loga)
664 	  ;
665       else
666 	loga = 0;
667 
668       if (digits[tmpb])
669 	for (logb = 1; digits[UCHAR (*++b)]; ++logb)
670 	  ;
671       else
672 	logb = 0;
673 
674       if (tmp = logb - loga)
675 	return tmp;
676 
677       if (!loga)
678 	return 0;
679 
680       return tmpb - tmpa;
681     }
682   else if (tmpb == '-')
683     {
684       if (digits[UCHAR (tmpa)] && digits[UCHAR (*++b)])
685 	return 1;
686       return 0;
687     }
688   else
689     {
690       while (tmpa == '0')
691 	tmpa = UCHAR (*++a);
692       while (tmpb == '0')
693 	tmpb = UCHAR (*++b);
694 
695       while (tmpa == tmpb && digits[tmpa])
696 	tmpa = UCHAR (*++a), tmpb = UCHAR (*++b);
697 
698       if ((tmpa == '.' && !digits[tmpb]) || (tmpb == '.' && !digits[tmpa]))
699 	return fraccompare (a, b);
700 
701       if (digits[tmpa])
702 	for (loga = 1; digits[UCHAR (*++a)]; ++loga)
703 	  ;
704       else
705 	loga = 0;
706 
707       if (digits[tmpb])
708 	for (logb = 1; digits[UCHAR (*++b)]; ++logb)
709 	  ;
710       else
711 	logb = 0;
712 
713       if (tmp = loga - logb)
714 	return tmp;
715 
716       if (!loga)
717 	return 0;
718 
719       return tmpa - tmpb;
720     }
721 }
722 
723 /* Return an integer <= 12 associated with month name S with length LEN,
724    0 if the name in S is not recognized. */
725 
726 static int
getmonth(s,len)727 getmonth (s, len)
728      char *s;
729      int len;
730 {
731   char month[4];
732   register int i, lo = 0, hi = 12;
733 
734   if (len < 3)
735     return 0;
736 
737   for (i = 0; i < 3; ++i)
738     month[i] = fold_toupper[UCHAR (s[i])];
739   month[3] = '\0';
740 
741   while (hi - lo > 1)
742     if (strcmp (month, monthtab[(lo + hi) / 2].name) < 0)
743       hi = (lo + hi) / 2;
744     else
745       lo = (lo + hi) / 2;
746   if (!strcmp (month, monthtab[lo].name))
747     return monthtab[lo].val;
748   return 0;
749 }
750 
751 /* Compare two lines A and B trying every key in sequence until there
752    are no more keys or a difference is found. */
753 
754 static int
keycompare(a,b)755 keycompare (a, b)
756      struct line *a, *b;
757 {
758   register char *texta, *textb, *lima, *limb, *translate;
759   register int *ignore;
760   struct keyfield *key;
761   int diff = 0, iter = 0, lena, lenb;
762 
763   for (key = keyhead.next; key; key = key->next, ++iter)
764     {
765       ignore = key->ignore;
766       translate = key->translate;
767 
768       /* Find the beginning and limit of each field. */
769       if (iter || a->keybeg == NULL || b->keybeg == NULL)
770 	{
771 	  if (key->eword >= 0)
772 	    lima = limfield (a, key), limb = limfield (b, key);
773 	  else
774 	    lima = a->text + a->length, limb = b->text + b->length;
775 
776 	  if (key->sword >= 0)
777 	    texta = begfield (a, key), textb = begfield (b, key);
778 	  else
779 	    {
780 	      texta = a->text, textb = b->text;
781 	      if (key->skipsblanks)
782 		{
783 		  while (texta < lima && blanks[UCHAR (*texta)])
784 		    ++texta;
785 		  while (textb < limb && blanks[UCHAR (*textb)])
786 		    ++textb;
787 		}
788 	    }
789 	}
790       else
791 	{
792 	  /* For the first iteration only, the key positions have
793 	     been precomputed for us. */
794 	  texta = a->keybeg, lima = a->keylim;
795 	  textb = b->keybeg, limb = b->keylim;
796 	}
797 
798       /* Find the lengths. */
799       lena = lima - texta, lenb = limb - textb;
800       if (lena < 0)
801 	lena = 0;
802       if (lenb < 0)
803 	lenb = 0;
804 
805       /* Actually compare the fields. */
806       if (key->numeric)
807 	{
808 	  if (*lima || *limb)
809 	    {
810 	      char savea = *lima, saveb = *limb;
811 
812 	      *lima = *limb = '\0';
813 	      diff = numcompare (texta, textb);
814 	      *lima = savea, *limb = saveb;
815 	    }
816 	  else
817 	    diff = numcompare (texta, textb);
818 
819 	  if (diff)
820 	    return key->reverse ? -diff : diff;
821 	  continue;
822 	}
823       else if (key->month)
824 	{
825 	  diff = getmonth (texta, lena) - getmonth (textb, lenb);
826 	  if (diff)
827 	    return key->reverse ? -diff : diff;
828 	  continue;
829 	}
830       else if (ignore && translate)
831 	while (texta < lima && textb < limb)
832 	  {
833 	    while (texta < lima && ignore[UCHAR (*texta)])
834 	      ++texta;
835 	    while (textb < limb && ignore[UCHAR (*textb)])
836 	      ++textb;
837 	    if (texta < lima && textb < limb &&
838 		translate[UCHAR (*texta++)] != translate[UCHAR (*textb++)])
839 	      {
840 		diff = translate[UCHAR (*--texta)] - translate[UCHAR (*--textb)];
841 		break;
842 	      }
843 	  }
844       else if (ignore)
845 	while (texta < lima && textb < limb)
846 	  {
847 	    while (texta < lima && ignore[UCHAR (*texta)])
848 	      ++texta;
849 	    while (textb < limb && ignore[UCHAR (*textb)])
850 	      ++textb;
851 	    if (texta < lima && textb < limb && *texta++ != *textb++)
852 	      {
853 		diff = *--texta - *--textb;
854 		break;
855 	      }
856 	  }
857       else if (translate)
858 	while (texta < lima && textb < limb)
859 	  {
860 	    if (translate[UCHAR (*texta++)] != translate[UCHAR (*textb++)])
861 	      {
862 		diff = translate[UCHAR (*--texta)] - translate[UCHAR (*--textb)];
863 		break;
864 	      }
865 	  }
866       else
867 	diff = memcmp (texta, textb, min (lena, lenb));
868 
869       if (diff)
870 	return key->reverse ? -diff : diff;
871       if (diff = lena - lenb)
872 	return key->reverse ? -diff : diff;
873     }
874 
875   return 0;
876 }
877 
878 /* Compare two lines A and B, returning negative, zero, or positive
879    depending on whether A compares less than, equal to, or greater than B. */
880 
881 static int
compare(a,b)882 compare (a, b)
883      register struct line *a, *b;
884 {
885   int diff, tmpa, tmpb, mini;
886 
887   if (keyhead.next)
888     {
889       diff = keycompare (a, b);
890       if (diff)
891 	return diff;
892       if (!unique && !stable)
893 	{
894 	  tmpa = a->length, tmpb = b->length;
895 	  diff = memcmp (a->text, b->text, min (tmpa, tmpb));
896 	  if (!diff)
897 	    diff = tmpa - tmpb;
898 	}
899     }
900   else
901     {
902       tmpa = a->length, tmpb = b->length;
903       mini = min (tmpa, tmpb);
904       if (mini == 0)
905 	diff = tmpa - tmpb;
906       else
907 	{
908 	  char *ap = a->text, *bp = b->text;
909 
910 	  diff = *ap - *bp;
911 	  if (diff == 0)
912 	    {
913 	      diff = memcmp (ap, bp, mini);
914 	      if (diff == 0)
915 		diff = tmpa - tmpb;
916 	    }
917 	}
918     }
919 
920   return reverse ? -diff : diff;
921 }
922 
923 /* Check that the lines read from the given FP come in order.  Return
924    1 if they do and 0 if there is a disorder. */
925 
926 static int
checkfp(fp)927 checkfp (fp)
928      FILE *fp;
929 {
930   struct buffer buf;		/* Input buffer. */
931   struct lines lines;		/* Lines scanned from the buffer. */
932   struct line temp;		/* Copy of previous line. */
933   int cc;			/* Character count. */
934   int cmp;			/* Result of calling compare. */
935   int alloc, i, success = 1;
936 
937   initbuf (&buf, mergealloc);
938   initlines (&lines, mergealloc / linelength + 1,
939 	     LINEALLOC / ((NMERGE + NMERGE) * sizeof (struct line)));
940   alloc = linelength;
941   temp.text = xmalloc (alloc);
942 
943   cc = fillbuf (&buf, fp);
944   findlines (&buf, &lines);
945 
946   if (cc)
947     do
948       {
949 	/* Compare each line in the buffer with its successor. */
950 	for (i = 0; i < lines.used - 1; ++i)
951 	  {
952 	    cmp = compare (&lines.lines[i], &lines.lines[i + 1]);
953 	    if ((unique && cmp >= 0) || (cmp > 0))
954 	      {
955 		success = 0;
956 		goto finish;
957 	      }
958 	  }
959 
960 	/* Save the last line of the buffer and refill the buffer. */
961 	if (lines.lines[lines.used - 1].length > alloc)
962 	  {
963 	    while (lines.lines[lines.used - 1].length + 1 > alloc)
964 	      alloc *= 2;
965 	    temp.text = xrealloc (temp.text, alloc);
966 	  }
967 	bcopy (lines.lines[lines.used - 1].text, temp.text,
968 	       lines.lines[lines.used - 1].length + 1);
969 	temp.length = lines.lines[lines.used - 1].length;
970 
971 	cc = fillbuf (&buf, fp);
972 	if (cc)
973 	  {
974 	    findlines (&buf, &lines);
975 	    /* Make sure the line saved from the old buffer contents is
976 	       less than or equal to the first line of the new buffer. */
977 	    cmp = compare (&temp, &lines.lines[0]);
978 	    if ((unique && cmp >= 0) || (cmp > 0))
979 	      {
980 		success = 0;
981 		break;
982 	      }
983 	  }
984       }
985     while (cc);
986 
987 finish:
988   xfclose (fp);
989   free (buf.buf);
990   free ((char *) lines.lines);
991   free (temp.text);
992   return success;
993 }
994 
995 /* Merge lines from FPS onto OFP.  NFPS cannot be greater than NMERGE.
996    Close FPS before returning. */
997 
998 static void
mergefps(fps,nfps,ofp)999 mergefps (fps, nfps, ofp)
1000      FILE *fps[], *ofp;
1001      register int nfps;
1002 {
1003   struct buffer buffer[NMERGE];	/* Input buffers for each file. */
1004   struct lines lines[NMERGE];	/* Line tables for each buffer. */
1005   struct line saved;		/* Saved line for unique check. */
1006   int savedflag = 0;		/* True if there is a saved line. */
1007   int savealloc;		/* Size allocated for the saved line. */
1008   int cur[NMERGE];		/* Current line in each line table. */
1009   int ord[NMERGE];		/* Table representing a permutation of fps,
1010 				   such that lines[ord[0]].lines[cur[ord[0]]]
1011 				   is the smallest line and will be next
1012 				   output. */
1013   register int i, j, t;
1014 
1015   /* Allocate space for a saved line if necessary. */
1016   if (unique)
1017     {
1018       savealloc = linelength;
1019       saved.text = xmalloc (savealloc);
1020     }
1021 
1022   /* Read initial lines from each input file. */
1023   for (i = 0; i < nfps; ++i)
1024     {
1025       initbuf (&buffer[i], mergealloc);
1026       /* If a file is empty, eliminate it from future consideration. */
1027       while (i < nfps && !fillbuf (&buffer[i], fps[i]))
1028 	{
1029 	  xfclose (fps[i]);
1030 	  --nfps;
1031 	  for (j = i; j < nfps; ++j)
1032 	    fps[j] = fps[j + 1];
1033 	}
1034       if (i == nfps)
1035 	free (buffer[i].buf);
1036       else
1037 	{
1038 	  initlines (&lines[i], mergealloc / linelength + 1,
1039 		     LINEALLOC / ((NMERGE + NMERGE) * sizeof (struct line)));
1040 	  findlines (&buffer[i], &lines[i]);
1041 	  cur[i] = 0;
1042 	}
1043     }
1044 
1045   /* Set up the ord table according to comparisons among input lines.
1046      Since this only reorders two items if one is strictly greater than
1047      the other, it is stable. */
1048   for (i = 0; i < nfps; ++i)
1049     ord[i] = i;
1050   for (i = 1; i < nfps; ++i)
1051     if (compare (&lines[ord[i - 1]].lines[cur[ord[i - 1]]],
1052 		 &lines[ord[i]].lines[cur[ord[i]]]) > 0)
1053       t = ord[i - 1], ord[i - 1] = ord[i], ord[i] = t, i = 0;
1054 
1055   /* Repeatedly output the smallest line until no input remains. */
1056   while (nfps)
1057     {
1058       /* If uniqified output is turned out, output only the first of
1059 	 an identical series of lines. */
1060       if (unique)
1061 	{
1062 	  if (savedflag && compare (&saved, &lines[ord[0]].lines[cur[ord[0]]]))
1063 	    {
1064 	      xfwrite (saved.text, 1, saved.length, ofp);
1065 	      putc ('\n', ofp);
1066 	      savedflag = 0;
1067 	    }
1068 	  if (!savedflag)
1069 	    {
1070 	      if (savealloc < lines[ord[0]].lines[cur[ord[0]]].length + 1)
1071 		{
1072 		  while (savealloc < lines[ord[0]].lines[cur[ord[0]]].length + 1)
1073 		    savealloc *= 2;
1074 		  saved.text = xrealloc (saved.text, savealloc);
1075 		}
1076 	      saved.length = lines[ord[0]].lines[cur[ord[0]]].length;
1077 	      bcopy (lines[ord[0]].lines[cur[ord[0]]].text, saved.text,
1078 		     saved.length + 1);
1079 	      savedflag = 1;
1080 	    }
1081 	}
1082       else
1083 	{
1084 	  xfwrite (lines[ord[0]].lines[cur[ord[0]]].text, 1,
1085 		   lines[ord[0]].lines[cur[ord[0]]].length, ofp);
1086 	  putc ('\n', ofp);
1087 	}
1088 
1089       /* Check if we need to read more lines into core. */
1090       if (++cur[ord[0]] == lines[ord[0]].used)
1091 	if (fillbuf (&buffer[ord[0]], fps[ord[0]]))
1092 	  {
1093 	    findlines (&buffer[ord[0]], &lines[ord[0]]);
1094 	    cur[ord[0]] = 0;
1095 	  }
1096 	else
1097 	  {
1098 	    /* We reached EOF on fps[ord[0]]. */
1099 	    for (i = 1; i < nfps; ++i)
1100 	      if (ord[i] > ord[0])
1101 		--ord[i];
1102 	    --nfps;
1103 	    xfclose (fps[ord[0]]);
1104 	    free (buffer[ord[0]].buf);
1105 	    free ((char *) lines[ord[0]].lines);
1106 	    for (i = ord[0]; i < nfps; ++i)
1107 	      {
1108 		fps[i] = fps[i + 1];
1109 		buffer[i] = buffer[i + 1];
1110 		lines[i] = lines[i + 1];
1111 		cur[i] = cur[i + 1];
1112 	      }
1113 	    for (i = 0; i < nfps; ++i)
1114 	      ord[i] = ord[i + 1];
1115 	    continue;
1116 	  }
1117 
1118       /* The new line just read in may be larger than other lines
1119 	 already in core; push it back in the queue until we encounter
1120 	 a line larger than it. */
1121       for (i = 1; i < nfps; ++i)
1122 	{
1123 	  t = compare (&lines[ord[0]].lines[cur[ord[0]]],
1124 		       &lines[ord[i]].lines[cur[ord[i]]]);
1125 	  if (!t)
1126 	    t = ord[0] - ord[i];
1127 	  if (t < 0)
1128 	    break;
1129 	}
1130       t = ord[0];
1131       for (j = 1; j < i; ++j)
1132 	ord[j - 1] = ord[j];
1133       ord[i - 1] = t;
1134     }
1135 
1136   if (unique && savedflag)
1137     {
1138       xfwrite (saved.text, 1, saved.length, ofp);
1139       putc ('\n', ofp);
1140       free (saved.text);
1141     }
1142 }
1143 
1144 /* Sort the array LINES with NLINES members, using TEMP for temporary space. */
1145 
1146 static void
sortlines(lines,nlines,temp)1147 sortlines (lines, nlines, temp)
1148      struct line *lines, *temp;
1149      int nlines;
1150 {
1151   register struct line *lo, *hi, *t;
1152   register int nlo, nhi;
1153 
1154   if (nlines == 2)
1155     {
1156       if (compare (&lines[0], &lines[1]) > 0)
1157 	*temp = lines[0], lines[0] = lines[1], lines[1] = *temp;
1158       return;
1159     }
1160 
1161   nlo = nlines / 2;
1162   lo = lines;
1163   nhi = nlines - nlo;
1164   hi = lines + nlo;
1165 
1166   if (nlo > 1)
1167     sortlines (lo, nlo, temp);
1168 
1169   if (nhi > 1)
1170     sortlines (hi, nhi, temp);
1171 
1172   t = temp;
1173 
1174   while (nlo && nhi)
1175     if (compare (lo, hi) <= 0)
1176       *t++ = *lo++, --nlo;
1177     else
1178       *t++ = *hi++, --nhi;
1179   while (nlo--)
1180     *t++ = *lo++;
1181 
1182   for (lo = lines, nlo = nlines - nhi, t = temp; nlo; --nlo)
1183     *lo++ = *t++;
1184 }
1185 
1186 /* Check that each of the NFILES FILES is ordered.
1187    Return a count of disordered files. */
1188 
1189 static int
check(files,nfiles)1190 check (files, nfiles)
1191      char *files[];
1192      int nfiles;
1193 {
1194   int i, disorders = 0;
1195   FILE *fp;
1196 
1197   for (i = 0; i < nfiles; ++i)
1198     {
1199       fp = xfopen (files[i], "r");
1200       if (!checkfp (fp))
1201 	{
1202 	  printf ("%s: disorder on %s\n", program_name, files[i]);
1203 	  ++disorders;
1204 	}
1205     }
1206   return disorders;
1207 }
1208 
1209 /* Merge NFILES FILES onto OFP. */
1210 
1211 static void
merge(files,nfiles,ofp)1212 merge (files, nfiles, ofp)
1213      char *files[];
1214      int nfiles;
1215      FILE *ofp;
1216 {
1217   int i, j, t;
1218   char *temp;
1219   FILE *fps[NMERGE], *tfp;
1220 
1221   while (nfiles > NMERGE)
1222     {
1223       t = 0;
1224       for (i = 0; i < nfiles / NMERGE; ++i)
1225 	{
1226 	  for (j = 0; j < NMERGE; ++j)
1227 	    fps[j] = xfopen (files[i * NMERGE + j], "r");
1228 	  tfp = xfopen (temp = tempname (), "w");
1229 	  mergefps (fps, NMERGE, tfp);
1230 	  xfclose (tfp);
1231 	  for (j = 0; j < NMERGE; ++j)
1232 	    zaptemp (files[i * NMERGE + j]);
1233 	  files[t++] = temp;
1234 	}
1235       for (j = 0; j < nfiles % NMERGE; ++j)
1236 	fps[j] = xfopen (files[i * NMERGE + j], "r");
1237       tfp = xfopen (temp = tempname (), "w");
1238       mergefps (fps, nfiles % NMERGE, tfp);
1239       xfclose (tfp);
1240       for (j = 0; j < nfiles % NMERGE; ++j)
1241 	zaptemp (files[i * NMERGE + j]);
1242       files[t++] = temp;
1243       nfiles = t;
1244     }
1245 
1246   for (i = 0; i < nfiles; ++i)
1247     fps[i] = xfopen (files[i], "r");
1248   mergefps (fps, i, ofp);
1249   for (i = 0; i < nfiles; ++i)
1250     zaptemp (files[i]);
1251 }
1252 
1253 /* Sort NFILES FILES onto OFP. */
1254 
1255 static void
sort(files,nfiles,ofp)1256 sort (files, nfiles, ofp)
1257      char **files;
1258      int nfiles;
1259      FILE *ofp;
1260 {
1261   struct buffer buf;
1262   struct lines lines;
1263   struct line *tmp;
1264   int i, ntmp;
1265   FILE *fp, *tfp;
1266   struct tempnode *node;
1267   int ntemp = 0;
1268   char **tempfiles;
1269 
1270   initbuf (&buf, sortalloc);
1271   initlines (&lines, sortalloc / linelength + 1,
1272 	     LINEALLOC / sizeof (struct line));
1273   ntmp = lines.alloc;
1274   tmp = (struct line *) xmalloc (ntmp * sizeof (struct line));
1275 
1276   while (nfiles--)
1277     {
1278       fp = xfopen (*files++, "r");
1279       while (fillbuf (&buf, fp))
1280 	{
1281 	  findlines (&buf, &lines);
1282 	  if (lines.used > ntmp)
1283 	    {
1284 	      while (lines.used > ntmp)
1285 		ntmp *= 2;
1286 	      tmp = (struct line *)
1287 		xrealloc ((char *) tmp, ntmp * sizeof (struct line));
1288 	    }
1289 	  sortlines (lines.lines, lines.used, tmp);
1290 	  if (feof (fp) && !nfiles && !ntemp && !buf.left)
1291 	    tfp = ofp;
1292 	  else
1293 	    {
1294 	      ++ntemp;
1295 	      tfp = xfopen (tempname (), "w");
1296 	    }
1297 	  for (i = 0; i < lines.used; ++i)
1298 	    if (!unique || i == 0
1299 		|| compare (&lines.lines[i], &lines.lines[i - 1]))
1300 	      {
1301 		xfwrite (lines.lines[i].text, 1, lines.lines[i].length, tfp);
1302 		putc ('\n', tfp);
1303 	      }
1304 	  if (tfp != ofp)
1305 	    xfclose (tfp);
1306 	}
1307       xfclose (fp);
1308     }
1309 
1310   free (buf.buf);
1311   free ((char *) lines.lines);
1312   free ((char *) tmp);
1313 
1314   if (ntemp)
1315     {
1316       tempfiles = (char **) xmalloc (ntemp * sizeof (char *));
1317       i = ntemp;
1318       for (node = temphead.next; node; node = node->next)
1319 	tempfiles[--i] = node->name;
1320       merge (tempfiles, ntemp, ofp);
1321       free ((char *) tempfiles);
1322     }
1323 }
1324 
1325 /* Insert key KEY at the end of the list (`keyhead'). */
1326 
1327 static void
insertkey(key)1328 insertkey (key)
1329      struct keyfield *key;
1330 {
1331   struct keyfield *k = &keyhead;
1332 
1333   while (k->next)
1334     k = k->next;
1335   k->next = key;
1336   key->next = NULL;
1337 }
1338 
1339 static void
badfieldspec(s)1340 badfieldspec (s)
1341      char *s;
1342 {
1343   error (2, 0, "invalid field specification `%s'", s);
1344 }
1345 
1346 /* Handle interrupts and hangups. */
1347 
1348 static void
sighandler(sig)1349 sighandler (sig)
1350      int sig;
1351 {
1352   struct sigaction sigact;
1353 
1354   sigact.sa_handler = SIG_DFL;
1355   sigemptyset (&sigact.sa_mask);
1356   sigact.sa_flags = 0;
1357   sigaction (sig, &sigact, NULL);
1358   cleanup ();
1359   kill (getpid (), sig);
1360 }
1361 
1362 /* Set the ordering options for KEY specified in S.
1363    Return the address of the first character in S that
1364    is not a valid ordering option.
1365    BLANKTYPE is the kind of blanks that 'b' should skip. */
1366 
1367 static char *
set_ordering(s,key,blanktype)1368 set_ordering (s, key, blanktype)
1369      register char *s;
1370      struct keyfield *key;
1371      enum blanktype blanktype;
1372 {
1373   while (*s)
1374     {
1375       switch (*s)
1376 	{
1377 	case 'b':
1378 	  if (blanktype == bl_start || blanktype == bl_both)
1379 	    key->skipsblanks = 1;
1380 	  if (blanktype == bl_end || blanktype == bl_both)
1381 	    key->skipeblanks = 1;
1382 	  break;
1383 	case 'd':
1384 	  key->ignore = nondictionary;
1385 	  break;
1386 	case 'f':
1387 	  key->translate = fold_toupper;
1388 	  break;
1389 #if 0
1390 	case 'g':
1391 	  /* Reserved for comparing floating-point numbers. */
1392 	  break;
1393 #endif
1394 	case 'i':
1395 	  key->ignore = nonprinting;
1396 	  break;
1397 	case 'M':
1398 	  key->skipsblanks = key->skipeblanks = key->month = 1;
1399 	  break;
1400 	case 'n':
1401 	  key->skipsblanks = key->skipeblanks = key->numeric = 1;
1402 	  break;
1403 	case 'r':
1404 	  key->reverse = 1;
1405 	  break;
1406 	default:
1407 	  return s;
1408 	}
1409       ++s;
1410     }
1411   return s;
1412 }
1413 
1414 void
main(argc,argv)1415 main (argc, argv)
1416      int argc;
1417      char *argv[];
1418 {
1419   struct keyfield *key = NULL, gkey;
1420   char *s;
1421   int i, t, t2;
1422   int checkonly = 0, mergeonly = 0, nfiles = 0;
1423   char *minus = "-", *outfile = minus, **files, *tmp;
1424   FILE *ofp;
1425   struct sigaction oldact, newact;
1426 
1427   program_name = argv[0];
1428   have_read_stdin = 0;
1429   inittables ();
1430 
1431   prefix = getenv ("TMPDIR");
1432   if (prefix == NULL)
1433     prefix = "/tmp";
1434 
1435   newact.sa_handler = sighandler;
1436   sigemptyset (&newact.sa_mask);
1437   newact.sa_flags = 0;
1438 
1439   sigaction (SIGINT, NULL, &oldact);
1440   if (oldact.sa_handler != SIG_IGN)
1441     sigaction (SIGINT, &newact, NULL);
1442   sigaction (SIGHUP, NULL, &oldact);
1443   if (oldact.sa_handler != SIG_IGN)
1444     sigaction (SIGHUP, &newact, NULL);
1445 
1446   gkey.sword = gkey.eword = -1;
1447   gkey.ignore = NULL;
1448   gkey.translate = NULL;
1449   gkey.numeric = gkey.month = gkey.reverse = 0;
1450   gkey.skipsblanks = gkey.skipeblanks = 0;
1451 
1452   files = (char **) xmalloc (sizeof (char *) * argc);
1453 
1454   for (i = 1; i < argc; ++i)
1455     {
1456       if (argv[i][0] == '+')
1457 	{
1458 	  if (key)
1459 	    insertkey (key);
1460 	  key = (struct keyfield *) xmalloc (sizeof (struct keyfield));
1461 	  key->eword = -1;
1462 	  key->ignore = NULL;
1463 	  key->translate = NULL;
1464 	  key->skipsblanks = key->skipeblanks = 0;
1465 	  key->numeric = key->month = key->reverse = 0;
1466 	  s = argv[i] + 1;
1467 	  if (!digits[UCHAR (*s)])
1468 	    badfieldspec (argv[i]);
1469 	  for (t = 0; digits[UCHAR (*s)]; ++s)
1470 	    t = 10 * t + *s - '0';
1471 	  t2 = 0;
1472 	  if (*s == '.')
1473 	    for (++s; digits[UCHAR (*s)]; ++s)
1474 	      t2 = 10 * t2 + *s - '0';
1475 	  if (t2 || t)
1476 	    {
1477 	      key->sword = t;
1478 	      key->schar = t2;
1479 	    }
1480 	  else
1481 	    key->sword = -1;
1482 	  s = set_ordering (s, key, bl_start);
1483 	  if (*s)
1484 	    badfieldspec (argv[i]);
1485 	}
1486       else if (argv[i][0] == '-')
1487 	{
1488 	  if (!strcmp ("-", argv[i]))
1489 	    break;
1490 	  s = argv[i] + 1;
1491 	  if (digits[UCHAR (*s)])
1492 	    {
1493 	      if (!key)
1494 		usage ();
1495 	      for (t = 0; digits[UCHAR (*s)]; ++s)
1496 		t = t * 10 + *s - '0';
1497 	      t2 = 0;
1498 	      if (*s == '.')
1499 		for (++s; digits[UCHAR (*s)]; ++s)
1500 		  t2 = t2 * 10 + *s - '0';
1501 	      key->eword = t;
1502 	      key->echar = t2;
1503 	      s = set_ordering (s, key, bl_end);
1504 	      if (*s)
1505 		badfieldspec (argv[i]);
1506 	      insertkey (key);
1507 	      key = NULL;
1508 	    }
1509 	  else
1510 	    while (*s)
1511 	      {
1512 		s = set_ordering (s, &gkey, bl_both);
1513 		switch (*s)
1514 		  {
1515 		  case '\0':
1516 		    break;
1517 		  case 'c':
1518 		    checkonly = 1;
1519 		    break;
1520 		  case 'k':
1521 		    if (s[1])
1522 		      ++s;
1523 		    else
1524 		      {
1525 			if (i == argc - 1)
1526 			  error (2, 0, "option `-k' requires an argument");
1527 			else
1528 			  s = argv[++i];
1529 		      }
1530 		    if (key)
1531 		      insertkey (key);
1532 		    key = (struct keyfield *)
1533 		      xmalloc (sizeof (struct keyfield));
1534 		    key->eword = -1;
1535 		    key->ignore = NULL;
1536 		    key->translate = NULL;
1537 		    key->skipsblanks = key->skipeblanks = 0;
1538 		    key->numeric = key->month = key->reverse = 0;
1539 		    /* Get POS1. */
1540 		    if (!digits[UCHAR (*s)])
1541 		      badfieldspec (argv[i]);
1542 		    for (t = 0; digits[UCHAR (*s)]; ++s)
1543 		      t = 10 * t + *s - '0';
1544 		    if (t)
1545 		      t--;
1546 		    t2 = 0;
1547 		    if (*s == '.')
1548 		      {
1549 			for (++s; digits[UCHAR (*s)]; ++s)
1550 			  t2 = 10 * t2 + *s - '0';
1551 			if (t2)
1552 			  t2--;
1553 		      }
1554 		    if (t2 || t)
1555 		      {
1556 			key->sword = t;
1557 			key->schar = t2;
1558 		      }
1559 		    else
1560 		      key->sword = -1;
1561 		    s = set_ordering (s, key, bl_start);
1562 		    if (*s && *s != ',')
1563 		      badfieldspec (argv[i]);
1564 		    else if (*s++)
1565 		      {
1566 			/* Get POS2. */
1567 			for (t = 0; digits[UCHAR (*s)]; ++s)
1568 			  t = t * 10 + *s - '0';
1569 			t2 = 0;
1570 			if (*s == '.')
1571 			  {
1572 			    for (++s; digits[UCHAR (*s)]; ++s)
1573 			      t2 = t2 * 10 + *s - '0';
1574 			    if (t2)
1575 			      t--;
1576 			  }
1577 			key->eword = t;
1578 			key->echar = t2;
1579 			s = set_ordering (s, key, bl_end);
1580 			if (*s)
1581 			  badfieldspec (argv[i]);
1582 		      }
1583 		    insertkey (key);
1584 		    key = NULL;
1585 		    goto outer;
1586 		  case 'm':
1587 		    mergeonly = 1;
1588 		    break;
1589 		  case 'o':
1590 		    if (s[1])
1591 		      outfile = s + 1;
1592 		    else
1593 		      {
1594 			if (i == argc - 1)
1595 			  error (2, 0, "option `-o' requires an argument");
1596 			else
1597 			  outfile = argv[++i];
1598 		      }
1599 		    goto outer;
1600 		  case 's':
1601 		    stable = 1;
1602 		    break;
1603 		  case 't':
1604 		    if (s[1])
1605 		      tab = *++s;
1606 		    else if (i < argc - 1)
1607 		      {
1608 			tab = *argv[++i];
1609 			goto outer;
1610 		      }
1611 		    else
1612 		      error (2, 0, "option `-t' requires an argument");
1613 		    break;
1614 		  case 'u':
1615 		    unique = 1;
1616 		    break;
1617 		  default:
1618 		    fprintf (stderr, "%s: unrecognized option `-%c'\n",
1619 			     argv[0], *s);
1620 		    usage ();
1621 		  }
1622 		if (*s)
1623 		  ++s;
1624 	      }
1625 	}
1626       else			/* Not an option. */
1627 	{
1628 	  files[nfiles++] = argv[i];
1629 	}
1630     outer:;
1631     }
1632 
1633   if (key)
1634     insertkey (key);
1635 
1636   /* Inheritance of global options to individual keys. */
1637   for (key = keyhead.next; key; key = key->next)
1638     if (!key->ignore && !key->translate && !key->skipsblanks && !key->reverse
1639 	&& !key->skipeblanks && !key->month && !key->numeric)
1640       {
1641 	key->ignore = gkey.ignore;
1642 	key->translate = gkey.translate;
1643 	key->skipsblanks = gkey.skipsblanks;
1644 	key->skipeblanks = gkey.skipeblanks;
1645 	key->month = gkey.month;
1646 	key->numeric = gkey.numeric;
1647 	key->reverse = gkey.reverse;
1648       }
1649 
1650   if (!keyhead.next && (gkey.ignore || gkey.translate || gkey.skipsblanks
1651 			|| gkey.reverse || gkey.skipeblanks
1652 			|| gkey.month || gkey.numeric))
1653     insertkey (&gkey);
1654 
1655   if (nfiles == 0)
1656     {
1657       nfiles = 1;
1658       files = &minus;
1659     }
1660 
1661   if (checkonly)
1662     exit (check (files, nfiles) != 0);
1663 
1664   if (strcmp (outfile, "-"))
1665     {
1666       for (i = 0; i < nfiles; ++i)
1667 	if (!strcmp (outfile, files[i]))
1668 	  break;
1669       if (i == nfiles)
1670 	ofp = xfopen (outfile, "w");
1671       else
1672 	{
1673 	  char buf[8192];
1674 	  FILE *fp = xfopen (outfile, "r");
1675 	  int cc;
1676 
1677 	  tmp = tempname ();
1678 	  ofp = xfopen (tmp, "w");
1679 	  while ((cc = fread (buf, 1, sizeof buf, fp)) > 0)
1680 	    xfwrite (buf, 1, cc, ofp);
1681 	  if (ferror (fp))
1682 	    {
1683 	      error (0, errno, "%s", outfile);
1684 	      cleanup ();
1685 	      exit (2);
1686 	    }
1687 	  xfclose (ofp);
1688 	  xfclose (fp);
1689 	  files[i] = tmp;
1690 	  ofp = xfopen (outfile, "w");
1691 	}
1692     }
1693   else
1694     ofp = stdout;
1695 
1696   if (mergeonly)
1697     merge (files, nfiles, ofp);
1698   else
1699     sort (files, nfiles, ofp);
1700   cleanup ();
1701 
1702   if (have_read_stdin && fclose (stdin) == EOF)
1703     error (1, errno, "-");
1704   if (ferror (stdout) || fclose (stdout) == EOF)
1705     error (1, 0, "write error");
1706 
1707   exit (0);
1708 }
1709 
1710 static void
usage()1711 usage ()
1712 {
1713   fprintf (stderr, "\
1714 Usage: %s [-cmus] [-t separator] [-o output-file] [-bdfiMnr] [+POS1 [-POS2]]\n\
1715        [-k POS1[,POS2]] [file...]\n",
1716 	   program_name);
1717   exit (2);
1718 }
1719 
error(n,e,s,s1)1720 error(n,e, s,s1) {
1721 if(e) fprintf(stderr,"error %d:", e);
1722 fprintf(stderr,s, s1);
1723 if(n) exit(n);
1724 }
1725