1 /* sort - sort lines of text (with all kinds of options).
2 Copyright (C) 88, 91, 92, 93, 94, 95, 1996 Free Software Foundation
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)
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.
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.
18 Written December 1988 by Mike Haertel.
19 The author may be reached (Email) at the address mike@gnu.ai.mit.edu,
20 or (US mail) as Mike Haertel c/o Free Software Foundation. */
24 /* Get isblank from GNU libc. */
27 #include <sys/types.h>
33 #include "long-options.h"
50 /* Undefine, to avoid warning about redefinition on some systems. */
52 #define min(a, b) ((a) < (b) ? (a) : (b))
54 #define UCHAR_LIM (UCHAR_MAX + 1)
55 #define UCHAR(c) ((unsigned char) (c))
57 #ifndef DEFAULT_TMPDIR
58 #define DEFAULT_TMPDIR "/tmp"
61 /* Use this as exit status in case of error, not EXIT_FAILURE. This
62 is necessary because EXIT_FAILURE is usually 1 and POSIX requires
63 that sort exit with status 1 IFF invoked with -c and the input is
64 not properly sorted. Any other irregular exit must exit with a
65 status code greater than 1. */
66 #define SORT_FAILURE 2
68 /* The kind of blanks for '-b' to skip in various options. */
69 enum blanktype
{ bl_start
, bl_end
, bl_both
};
71 /* The character marking end of line. Default to \n. */
74 /* Lines are held in core as counted strings. */
77 char *text
; /* Text of the line. */
78 int length
; /* Length not including final newline. */
79 char *keybeg
; /* Start of first key. */
80 char *keylim
; /* Limit of first key. */
83 /* Arrays of lines. */
86 struct line
*lines
; /* Dynamically allocated array of lines. */
87 int used
; /* Number of slots used. */
88 int alloc
; /* Number of slots allocated. */
89 int limit
; /* Max number of slots to allocate. */
95 char *buf
; /* Dynamically allocated buffer. */
96 int used
; /* Number of bytes used. */
97 int alloc
; /* Number of bytes allocated. */
98 int left
; /* Number of bytes left after line parsing. */
103 int sword
; /* Zero-origin 'word' to start at. */
104 int schar
; /* Additional characters to skip. */
105 int skipsblanks
; /* Skip leading white space at start. */
106 int eword
; /* Zero-origin first word after field. */
107 int echar
; /* Additional characters in field. */
108 int skipeblanks
; /* Skip trailing white space at finish. */
109 int *ignore
; /* Boolean array of characters to ignore. */
110 char *translate
; /* Translation applied to characters. */
111 int numeric
; /* Flag for numeric comparison. Handle
112 strings of digits with optional decimal
113 point, but no exponential notation. */
114 int general_numeric
; /* Flag for general, numeric comparison.
115 Handle numbers in exponential notation. */
116 int month
; /* Flag for comparison by month name. */
117 int reverse
; /* Reverse the sense of comparison. */
118 struct keyfield
*next
; /* Next keyfield to try. */
127 /* The name this program was run with. */
130 /* Table of digits. */
131 static int digits
[UCHAR_LIM
];
133 /* Table of white space. */
134 static int blanks
[UCHAR_LIM
];
136 /* Table of non-printing characters. */
137 static int nonprinting
[UCHAR_LIM
];
139 /* Table of non-dictionary characters (not letters, digits, or blanks). */
140 static int nondictionary
[UCHAR_LIM
];
142 /* Translation table folding lower case to upper. */
143 static char fold_toupper
[UCHAR_LIM
];
145 /* Table mapping 3-letter month names to integers.
146 Alphabetic order allows binary search. */
147 static struct month
const monthtab
[] =
163 /* During the merge phase, the number of files to merge at once. */
166 /* Initial buffer size for in core sorting. Will not grow unless a
167 line longer than this is seen. */
168 static int sortalloc
= 512 * 1024;
170 /* Initial buffer size for in core merge buffers. Bear in mind that
171 up to NMERGE * mergealloc bytes may be allocated for merge buffers. */
172 static int mergealloc
= 16 * 1024;
174 /* Guess of average line length. */
175 static int linelength
= 30;
177 /* Maximum number of elements for the array(s) of struct line's, in bytes. */
178 #define LINEALLOC (256 * 1024)
180 /* Prefix for temporary file names. */
181 static char *temp_file_prefix
;
183 /* Flag to reverse the order of all comparisons. */
186 /* Flag for stable sort. This turns off the last ditch bytewise
187 comparison of lines, and instead leaves lines in the same order
188 they were read if all keys compare equal. */
191 /* Tab character separating fields. If NUL, then fields are separated
192 by the empty string between a non-whitespace character and a whitespace
196 /* Flag to remove consecutive duplicate lines from the output.
197 Only the last of a sequence of equal lines will be output. */
200 /* Nonzero if any of the input files are the standard input. */
201 static int have_read_stdin
;
203 /* Lists of key field comparisons to be tried. */
204 static struct keyfield keyhead
;
210 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
215 Usage: %s [OPTION]... [FILE]...\n\
219 Write sorted concatenation of all FILE(s) to standard output.\n\
221 +POS1 [-POS2] start a key at POS1, end it before POS2\n\
222 -M compare (unknown) < `JAN' < ... < `DEC', imply -b\n\
223 -T DIRECT use DIRECT for temporary files, not $TMPDIR or %s\n\
224 -b ignore leading blanks in sort fields or keys\n\
225 -c check if given files already sorted, do not sort\n\
226 -d consider only [a-zA-Z0-9 ] characters in keys\n\
227 -f fold lower case to upper case characters in keys\n\
228 -g compare according to general numerical value, imply -b\n\
229 -i consider only [\\040-\\0176] characters in keys\n\
230 -k POS1[,POS2] same as +POS1 [-POS2], but all positions counted from 1\n\
231 -m merge already sorted files, do not sort\n\
232 -n compare according to string numerical value, imply -b\n\
233 -o FILE write result on FILE instead of standard output\n\
234 -r reverse the result of comparisons\n\
235 -s stabilize sort by disabling last resort comparison\n\
236 -t SEP use SEParator instead of non- to whitespace transition\n\
237 -u with -c, check for strict ordering\n\
238 -u with -m, only output the first of an equal sequence\n\
239 -z end lines with 0 byte, not newline, for find -print0\n\
240 --help display this help and exit\n\
241 --version output version information and exit\n\
243 POS is F[.C][OPTS], where F is the field number and C the character\n\
244 position in the field, both counted from zero. OPTS is made up of one\n\
245 or more of Mbdfinr, this effectively disable global -Mbdfinr settings\n\
246 for that key. If no key given, use the entire line as key. With no\n\
247 FILE, or when FILE is -, read standard input.\n\
251 /* Don't use EXIT_FAILURE here in case it is defined to be 1.
252 POSIX requires that sort return 1 IFF invoked with -c and
253 the input is not properly sorted. */
254 assert (status
== 0 || status
== SORT_FAILURE
);
258 /* The list of temporary files. */
259 static struct tempnode
262 struct tempnode
*next
;
265 /* Clean up any remaining temporary files. */
270 struct tempnode
*node
;
272 for (node
= temphead
.next
; node
; node
= node
->next
)
276 /* Allocate N bytes of memory dynamically, with error checking. */
279 xmalloc (unsigned int n
)
286 error (0, 0, _("virtual memory exhausted"));
293 /* Change the size of an allocated block of memory P to N bytes,
295 If P is NULL, run xmalloc.
296 If N is 0, run free and return NULL. */
299 xrealloc (char *p
, unsigned int n
)
311 error (0, 0, _("virtual memory exhausted"));
319 xtmpfopen (const char *file
)
324 fd
= open (file
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
325 if (fd
< 0 || (fp
= fdopen (fd
, "w")) == NULL
)
327 error (0, errno
, "%s", file
);
336 xfopen (const char *file
, const char *how
)
340 if (strcmp (file
, "-") == 0)
346 if ((fp
= fopen (file
, how
)) == NULL
)
348 error (0, errno
, "%s", file
);
364 /* Allow reading stdin from tty more than once. */
368 else if (fp
== stdout
)
370 if (fflush (fp
) != 0)
372 error (0, errno
, _("flushing file"));
379 if (fclose (fp
) != 0)
381 error (0, errno
, _("error closing file"));
389 write_bytes (const char *buf
, size_t n_bytes
, FILE *fp
)
391 if (fwrite (buf
, 1, n_bytes
, fp
) != n_bytes
)
393 error (0, errno
, _("write error"));
399 /* Return a name for a temporary file. */
404 static unsigned int seq
;
405 int len
= strlen (temp_file_prefix
);
406 char *name
= xmalloc (len
+ 1 + sizeof ("sort") - 1 + 5 + 5 + 1);
407 struct tempnode
*node
;
409 node
= (struct tempnode
*) xmalloc (sizeof (struct tempnode
));
411 "%s%ssort%5.5d%5.5d",
413 (len
&& temp_file_prefix
[len
- 1] != '/') ? "/" : "",
414 (unsigned int) getpid () & 0xffff, seq
);
416 /* Make sure that SEQ's value fits in 5 digits. */
422 node
->next
= temphead
.next
;
423 temphead
.next
= node
;
427 /* Search through the list of temporary files for NAME;
428 remove it if it is found on the list. */
433 struct tempnode
*node
, *temp
;
435 for (node
= &temphead
; node
->next
; node
= node
->next
)
436 if (!strcmp (name
, node
->next
->name
))
443 node
->next
= temp
->next
;
444 free ((char *) temp
);
448 /* Initialize the character class tables. */
455 for (i
= 0; i
< UCHAR_LIM
; ++i
)
463 if (!ISALNUM (i
) && !ISBLANK (i
))
464 nondictionary
[i
] = 1;
466 fold_toupper
[i
] = toupper (i
);
472 /* Initialize BUF, allocating ALLOC bytes initially. */
475 initbuf (struct buffer
*buf
, int alloc
)
478 buf
->buf
= xmalloc (buf
->alloc
);
479 buf
->used
= buf
->left
= 0;
482 /* Fill BUF reading from FP, moving buf->left bytes from the end
483 of buf->buf to the beginning first. If EOF is reached and the
484 file wasn't terminated by a newline, supply one. Return a count
485 of bytes buffered. */
488 fillbuf (struct buffer
*buf
, FILE *fp
)
492 memmove (buf
->buf
, buf
->buf
+ buf
->used
- buf
->left
, buf
->left
);
493 buf
->used
= buf
->left
;
495 while (!feof (fp
) && (buf
->used
== 0 || !memchr (buf
->buf
, eolchar
, buf
->used
)))
497 if (buf
->used
== buf
->alloc
)
500 buf
->buf
= xrealloc (buf
->buf
, buf
->alloc
);
502 cc
= fread (buf
->buf
+ buf
->used
, 1, buf
->alloc
- buf
->used
, fp
);
505 error (0, errno
, _("read error"));
512 if (feof (fp
) && buf
->used
&& buf
->buf
[buf
->used
- 1] != eolchar
)
514 if (buf
->used
== buf
->alloc
)
517 buf
->buf
= xrealloc (buf
->buf
, buf
->alloc
);
519 buf
->buf
[buf
->used
++] = eolchar
;
525 /* Initialize LINES, allocating space for ALLOC lines initially.
526 LIMIT is the maximum possible number of lines to allocate space
530 initlines (struct lines
*lines
, int alloc
, int limit
)
532 lines
->alloc
= alloc
;
533 lines
->lines
= (struct line
*) xmalloc (lines
->alloc
* sizeof (struct line
));
535 lines
->limit
= limit
;
538 /* Return a pointer to the first character of the field specified
542 begfield (const struct line
*line
, const struct keyfield
*key
)
544 register char *ptr
= line
->text
, *lim
= ptr
+ line
->length
;
545 register int sword
= key
->sword
, schar
= key
->schar
;
548 while (ptr
< lim
&& sword
--)
550 while (ptr
< lim
&& *ptr
!= tab
)
556 while (ptr
< lim
&& sword
--)
558 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
560 while (ptr
< lim
&& !blanks
[UCHAR (*ptr
)])
564 if (key
->skipsblanks
)
565 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
568 if (ptr
+ schar
<= lim
)
576 /* Return the limit of (a pointer to the first character after) the field
577 in LINE specified by KEY. */
580 limfield (const struct line
*line
, const struct keyfield
*key
)
582 register char *ptr
= line
->text
, *lim
= ptr
+ line
->length
;
583 register int eword
= key
->eword
, echar
= key
->echar
;
585 /* Note: from the POSIX spec:
586 The leading field separator itself is included in
587 a field when -t is not used. FIXME: move this comment up... */
589 /* Move PTR past EWORD fields or to one past the last byte on LINE,
590 whichever comes first. If there are more than EWORD fields, leave
591 PTR pointing at the beginning of the field having zero-based index,
592 EWORD. If a delimiter character was specified (via -t), then that
593 `beginning' is the first character following the delimiting TAB.
594 Otherwise, leave PTR pointing at the first `blank' character after
595 the preceding field. */
597 while (ptr
< lim
&& eword
--)
599 while (ptr
< lim
&& *ptr
!= tab
)
601 if (ptr
< lim
&& (eword
|| echar
> 0))
605 while (ptr
< lim
&& eword
--)
607 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
609 while (ptr
< lim
&& !blanks
[UCHAR (*ptr
)])
613 #ifdef POSIX_UNSPECIFIED
614 /* The following block of code makes GNU sort incompatible with
615 standard Unix sort, so it's ifdef'd out for now.
616 The POSIX spec isn't clear on how to interpret this.
617 FIXME: request clarification.
619 From: kwzh@gnu.ai.mit.edu (Karl Heuer)
620 Date: Thu, 30 May 96 12:20:41 -0400
622 [...]I believe I've found another bug in `sort'.
627 $ textutils-1.15/src/sort +0.6 -0.7 </tmp/sort.in
630 $ /bin/sort +0.6 -0.7 </tmp/sort.in
634 Unix sort produced the answer I expected: sort on the single character
635 in column 6. GNU sort produced different results, because it disagrees
636 on the interpretation of the key-end spec "-M.N". Unix sort reads this
637 as "skip M fields, then N characters"; but GNU sort wants it to mean
638 "skip M fields, then either N characters or the rest of the current
639 field, whichever comes first". This extra clause applies only to
640 key-ends, not key-starts.
643 /* Make LIM point to the end of (one byte past) the current field. */
647 newlim
= memchr (ptr
, tab
, lim
- ptr
);
655 while (newlim
< lim
&& blanks
[UCHAR (*newlim
)])
657 while (newlim
< lim
&& !blanks
[UCHAR (*newlim
)])
663 /* If we're skipping leading blanks, don't start counting characters
664 until after skipping past any leading blanks. */
665 if (key
->skipsblanks
)
666 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
669 /* Advance PTR by ECHAR (if possible), but no further than LIM. */
670 if (ptr
+ echar
<= lim
)
681 trim_trailing_blanks (const char *a_start
, char **a_end
)
683 while (*a_end
> a_start
&& blanks
[UCHAR (*(*a_end
- 1))])
687 /* Find the lines in BUF, storing pointers and lengths in LINES.
688 Also replace newlines in BUF with NULs. */
691 findlines (struct buffer
*buf
, struct lines
*lines
)
693 register char *beg
= buf
->buf
, *lim
= buf
->buf
+ buf
->used
, *ptr
;
694 struct keyfield
*key
= keyhead
.next
;
698 while (beg
< lim
&& (ptr
= memchr (beg
, eolchar
, lim
- beg
))
699 && lines
->used
< lines
->limit
)
701 /* There are various places in the code that rely on a NUL
702 being at the end of in-core lines; NULs inside the lines
703 will not cause trouble, though. */
706 if (lines
->used
== lines
->alloc
)
709 lines
->lines
= (struct line
*)
710 xrealloc ((char *) lines
->lines
,
711 lines
->alloc
* sizeof (struct line
));
714 lines
->lines
[lines
->used
].text
= beg
;
715 lines
->lines
[lines
->used
].length
= ptr
- beg
;
717 /* Precompute the position of the first key for efficiency. */
721 lines
->lines
[lines
->used
].keylim
=
722 limfield (&lines
->lines
[lines
->used
], key
);
724 lines
->lines
[lines
->used
].keylim
= ptr
;
727 lines
->lines
[lines
->used
].keybeg
=
728 begfield (&lines
->lines
[lines
->used
], key
);
731 if (key
->skipsblanks
)
732 while (blanks
[UCHAR (*beg
)])
734 lines
->lines
[lines
->used
].keybeg
= beg
;
736 if (key
->skipeblanks
)
738 trim_trailing_blanks (lines
->lines
[lines
->used
].keybeg
,
739 &lines
->lines
[lines
->used
].keylim
);
744 lines
->lines
[lines
->used
].keybeg
= 0;
745 lines
->lines
[lines
->used
].keylim
= 0;
752 buf
->left
= lim
- beg
;
755 /* Compare strings A and B containing decimal fractions < 1. Each string
756 should begin with a decimal point followed immediately by the digits
757 of the fraction. Strings not of this form are considered to be zero. */
760 fraccompare (register const char *a
, register const char *b
)
762 register tmpa
= UCHAR (*a
), tmpb
= UCHAR (*b
);
764 if (tmpa
== '.' && tmpb
== '.')
767 tmpa
= UCHAR (*++a
), tmpb
= UCHAR (*++b
);
768 while (tmpa
== tmpb
&& digits
[tmpa
]);
769 if (digits
[tmpa
] && digits
[tmpb
])
789 else if (tmpa
== '.')
798 else if (tmpb
== '.')
810 /* Compare strings A and B as numbers without explicitly converting them to
811 machine numbers. Comparatively slow for short strings, but asymptotically
815 numcompare (register const char *a
, register const char *b
)
817 register int tmpa
, tmpb
, loga
, logb
, tmp
;
854 while (tmpa
== tmpb
&& digits
[tmpa
])
855 tmpa
= UCHAR (*++a
), tmpb
= UCHAR (*++b
);
857 if ((tmpa
== '.' && !digits
[tmpb
]) || (tmpb
== '.' && !digits
[tmpa
]))
858 return -fraccompare (a
, b
);
861 for (loga
= 1; digits
[UCHAR (*++a
)]; ++loga
)
867 for (logb
= 1; digits
[UCHAR (*++b
)]; ++logb
)
872 if ((tmp
= logb
- loga
) != 0)
880 else if (tmpb
== '-')
908 while (tmpa
== tmpb
&& digits
[tmpa
])
909 tmpa
= UCHAR (*++a
), tmpb
= UCHAR (*++b
);
911 if ((tmpa
== '.' && !digits
[tmpb
]) || (tmpb
== '.' && !digits
[tmpa
]))
912 return fraccompare (a
, b
);
915 for (loga
= 1; digits
[UCHAR (*++a
)]; ++loga
)
921 for (logb
= 1; digits
[UCHAR (*++b
)]; ++logb
)
926 if ((tmp
= loga
- logb
) != 0)
937 general_numcompare (const char *sa
, const char *sb
)
940 /* FIXME: add option to warn about failed conversions. */
941 /* FIXME: maybe add option to try expensive FP conversion
942 only if A and B can't be compared more cheaply/accurately. */
943 if (xstrtod (sa
, NULL
, &a
))
947 if (xstrtod (sb
, NULL
, &b
))
951 return a
== b
? 0 : a
< b
? -1 : 1;
954 /* Return an integer <= 12 associated with month name S with length LEN,
955 0 if the name in S is not recognized. */
958 getmonth (const char *s
, int len
)
961 register int i
, lo
= 0, hi
= 12;
963 while (len
> 0 && blanks
[UCHAR(*s
)])
969 for (i
= 0; i
< 3; ++i
)
970 month
[i
] = fold_toupper
[UCHAR (s
[i
])];
974 if (strcmp (month
, monthtab
[(lo
+ hi
) / 2].name
) < 0)
978 if (!strcmp (month
, monthtab
[lo
].name
))
979 return monthtab
[lo
].val
;
983 /* Compare two lines A and B trying every key in sequence until there
984 are no more keys or a difference is found. */
987 keycompare (const struct line
*a
, const struct line
*b
)
989 register char *texta
, *textb
, *lima
, *limb
, *translate
;
990 register int *ignore
;
991 struct keyfield
*key
;
992 int diff
= 0, iter
= 0, lena
, lenb
;
994 for (key
= keyhead
.next
; key
; key
= key
->next
, ++iter
)
996 ignore
= key
->ignore
;
997 translate
= key
->translate
;
999 /* Find the beginning and limit of each field. */
1000 if (iter
|| a
->keybeg
== NULL
|| b
->keybeg
== NULL
)
1002 if (key
->eword
>= 0)
1003 lima
= limfield (a
, key
), limb
= limfield (b
, key
);
1005 lima
= a
->text
+ a
->length
, limb
= b
->text
+ b
->length
;
1007 if (key
->sword
>= 0)
1008 texta
= begfield (a
, key
), textb
= begfield (b
, key
);
1011 texta
= a
->text
, textb
= b
->text
;
1012 if (key
->skipsblanks
)
1014 while (texta
< lima
&& blanks
[UCHAR (*texta
)])
1016 while (textb
< limb
&& blanks
[UCHAR (*textb
)])
1023 /* For the first iteration only, the key positions have
1024 been precomputed for us. */
1025 texta
= a
->keybeg
, lima
= a
->keylim
;
1026 textb
= b
->keybeg
, limb
= b
->keylim
;
1029 /* Find the lengths. */
1030 lena
= lima
- texta
, lenb
= limb
- textb
;
1036 if (key
->skipeblanks
)
1038 char *a_end
= texta
+ lena
;
1039 char *b_end
= textb
+ lenb
;
1040 trim_trailing_blanks (texta
, &a_end
);
1041 trim_trailing_blanks (textb
, &b_end
);
1042 lena
= a_end
- texta
;
1043 lenb
= b_end
- textb
;
1046 /* Actually compare the fields. */
1051 char savea
= *lima
, saveb
= *limb
;
1053 *lima
= *limb
= '\0';
1054 diff
= numcompare (texta
, textb
);
1055 *lima
= savea
, *limb
= saveb
;
1058 diff
= numcompare (texta
, textb
);
1061 return key
->reverse
? -diff
: diff
;
1064 else if (key
->general_numeric
)
1068 char savea
= *lima
, saveb
= *limb
;
1070 *lima
= *limb
= '\0';
1071 diff
= general_numcompare (texta
, textb
);
1072 *lima
= savea
, *limb
= saveb
;
1075 diff
= general_numcompare (texta
, textb
);
1078 return key
->reverse
? -diff
: diff
;
1081 else if (key
->month
)
1083 diff
= getmonth (texta
, lena
) - getmonth (textb
, lenb
);
1085 return key
->reverse
? -diff
: diff
;
1088 else if (ignore
&& translate
)
1090 #define CMP_WITH_IGNORE(A, B) \
1093 while (texta < lima && textb < limb) \
1095 while (texta < lima && ignore[UCHAR (*texta)]) \
1097 while (textb < limb && ignore[UCHAR (*textb)]) \
1099 if (texta < lima && textb < limb) \
1110 if (texta == lima && textb < limb && !ignore[UCHAR (*textb)]) \
1112 else if (texta < lima && textb == limb \
1113 && !ignore[UCHAR (*texta)]) \
1119 while (texta < lima && ignore[UCHAR (*texta)]) \
1121 while (textb < limb && ignore[UCHAR (*textb)]) \
1124 if (texta == lima && textb < limb) \
1126 else if (texta < lima && textb == limb) \
1129 /* Relative lengths are meaningless if characters were ignored. \
1130 Handling this case here avoids what might be an invalid length \
1131 comparison below. */ \
1132 if (diff == 0 && texta == lima && textb == limb) \
1137 CMP_WITH_IGNORE (translate
[UCHAR (*texta
)], translate
[UCHAR (*textb
)]);
1139 CMP_WITH_IGNORE (*texta
, *textb
);
1141 while (texta
< lima
&& textb
< limb
)
1143 if (translate
[UCHAR (*texta
++)] != translate
[UCHAR (*textb
++)])
1145 diff
= (translate
[UCHAR (*--texta
)]
1146 - translate
[UCHAR (*--textb
)]);
1151 diff
= memcmp (texta
, textb
, min (lena
, lenb
));
1154 return key
->reverse
? -diff
: diff
;
1155 if ((diff
= lena
- lenb
) != 0)
1156 return key
->reverse
? -diff
: diff
;
1162 /* Compare two lines A and B, returning negative, zero, or positive
1163 depending on whether A compares less than, equal to, or greater than B. */
1166 compare (register const struct line
*a
, register const struct line
*b
)
1168 int diff
, tmpa
, tmpb
, mini
;
1170 /* First try to compare on the specified keys (if any).
1171 The only two cases with no key at all are unadorned sort,
1172 and unadorned sort -r. */
1175 diff
= keycompare (a
, b
);
1178 if (unique
|| stable
)
1182 /* If the keys all compare equal (or no keys were specified)
1183 fall through to the default byte-by-byte comparison. */
1184 tmpa
= a
->length
, tmpb
= b
->length
;
1185 mini
= min (tmpa
, tmpb
);
1190 char *ap
= a
->text
, *bp
= b
->text
;
1192 diff
= UCHAR (*ap
) - UCHAR (*bp
);
1195 diff
= memcmp (ap
, bp
, mini
);
1201 return reverse
? -diff
: diff
;
1204 /* Check that the lines read from the given FP come in order. Return
1205 1 if they do and 0 if there is a disorder.
1206 FIXME: return number of first out-of-order line if not sorted. */
1211 struct buffer buf
; /* Input buffer. */
1212 struct lines lines
; /* Lines scanned from the buffer. */
1213 struct line temp
; /* Copy of previous line. */
1214 int cc
; /* Character count. */
1215 int alloc
, sorted
= 1;
1217 initbuf (&buf
, mergealloc
);
1218 initlines (&lines
, mergealloc
/ linelength
+ 1,
1219 LINEALLOC
/ ((NMERGE
+ NMERGE
) * sizeof (struct line
)));
1221 temp
.text
= xmalloc (alloc
);
1223 cc
= fillbuf (&buf
, fp
);
1227 findlines (&buf
, &lines
);
1231 struct line
*prev_line
; /* Pointer to previous line. */
1232 int cmp
; /* Result of calling compare. */
1235 /* Compare each line in the buffer with its successor. */
1236 for (i
= 0; i
< lines
.used
- 1; ++i
)
1238 cmp
= compare (&lines
.lines
[i
], &lines
.lines
[i
+ 1]);
1239 if ((unique
&& cmp
>= 0) || (cmp
> 0))
1246 /* Save the last line of the buffer and refill the buffer. */
1247 prev_line
= lines
.lines
+ (lines
.used
- 1);
1248 if (prev_line
->length
> alloc
)
1250 while (prev_line
->length
+ 1 > alloc
)
1252 temp
.text
= xrealloc (temp
.text
, alloc
);
1254 memcpy (temp
.text
, prev_line
->text
, prev_line
->length
+ 1);
1255 temp
.length
= prev_line
->length
;
1256 temp
.keybeg
= temp
.text
+ (prev_line
->keybeg
- prev_line
->text
);
1257 temp
.keylim
= temp
.text
+ (prev_line
->keylim
- prev_line
->text
);
1259 cc
= fillbuf (&buf
, fp
);
1263 findlines (&buf
, &lines
);
1264 /* Make sure the line saved from the old buffer contents is
1265 less than or equal to the first line of the new buffer. */
1266 cmp
= compare (&temp
, &lines
.lines
[0]);
1267 if ((unique
&& cmp
>= 0) || (cmp
> 0))
1277 free ((char *) lines
.lines
);
1282 /* Merge lines from FPS onto OFP. NFPS cannot be greater than NMERGE.
1283 Close FPS before returning. */
1286 mergefps (FILE **fps
, register int nfps
, FILE *ofp
)
1288 struct buffer buffer
[NMERGE
]; /* Input buffers for each file. */
1289 struct lines lines
[NMERGE
]; /* Line tables for each buffer. */
1290 struct line saved
; /* Saved line for unique check. */
1291 int savedflag
= 0; /* True if there is a saved line. */
1292 int savealloc
; /* Size allocated for the saved line. */
1293 int cur
[NMERGE
]; /* Current line in each line table. */
1294 int ord
[NMERGE
]; /* Table representing a permutation of fps,
1295 such that lines[ord[0]].lines[cur[ord[0]]]
1296 is the smallest line and will be next
1298 register int i
, j
, t
;
1300 #ifdef lint /* Suppress `used before initialized' warning. */
1304 /* Allocate space for a saved line if necessary. */
1307 savealloc
= linelength
;
1308 saved
.text
= xmalloc (savealloc
);
1311 /* Read initial lines from each input file. */
1312 for (i
= 0; i
< nfps
; ++i
)
1314 initbuf (&buffer
[i
], mergealloc
);
1315 /* If a file is empty, eliminate it from future consideration. */
1316 while (i
< nfps
&& !fillbuf (&buffer
[i
], fps
[i
]))
1320 for (j
= i
; j
< nfps
; ++j
)
1321 fps
[j
] = fps
[j
+ 1];
1324 free (buffer
[i
].buf
);
1327 initlines (&lines
[i
], mergealloc
/ linelength
+ 1,
1328 LINEALLOC
/ ((NMERGE
+ NMERGE
) * sizeof (struct line
)));
1329 findlines (&buffer
[i
], &lines
[i
]);
1334 /* Set up the ord table according to comparisons among input lines.
1335 Since this only reorders two items if one is strictly greater than
1336 the other, it is stable. */
1337 for (i
= 0; i
< nfps
; ++i
)
1339 for (i
= 1; i
< nfps
; ++i
)
1340 if (compare (&lines
[ord
[i
- 1]].lines
[cur
[ord
[i
- 1]]],
1341 &lines
[ord
[i
]].lines
[cur
[ord
[i
]]]) > 0)
1342 t
= ord
[i
- 1], ord
[i
- 1] = ord
[i
], ord
[i
] = t
, i
= 0;
1344 /* Repeatedly output the smallest line until no input remains. */
1347 /* If uniqified output is turned on, output only the first of
1348 an identical series of lines. */
1351 if (savedflag
&& compare (&saved
, &lines
[ord
[0]].lines
[cur
[ord
[0]]]))
1353 write_bytes (saved
.text
, saved
.length
, ofp
);
1354 putc (eolchar
, ofp
);
1359 if (savealloc
< lines
[ord
[0]].lines
[cur
[ord
[0]]].length
+ 1)
1361 while (savealloc
< lines
[ord
[0]].lines
[cur
[ord
[0]]].length
+ 1)
1363 saved
.text
= xrealloc (saved
.text
, savealloc
);
1365 saved
.length
= lines
[ord
[0]].lines
[cur
[ord
[0]]].length
;
1366 memcpy (saved
.text
, lines
[ord
[0]].lines
[cur
[ord
[0]]].text
,
1368 if (lines
[ord
[0]].lines
[cur
[ord
[0]]].keybeg
!= NULL
)
1370 saved
.keybeg
= saved
.text
+
1371 (lines
[ord
[0]].lines
[cur
[ord
[0]]].keybeg
1372 - lines
[ord
[0]].lines
[cur
[ord
[0]]].text
);
1374 if (lines
[ord
[0]].lines
[cur
[ord
[0]]].keylim
!= NULL
)
1376 saved
.keylim
= saved
.text
+
1377 (lines
[ord
[0]].lines
[cur
[ord
[0]]].keylim
1378 - lines
[ord
[0]].lines
[cur
[ord
[0]]].text
);
1385 write_bytes (lines
[ord
[0]].lines
[cur
[ord
[0]]].text
,
1386 lines
[ord
[0]].lines
[cur
[ord
[0]]].length
, ofp
);
1387 putc (eolchar
, ofp
);
1390 /* Check if we need to read more lines into core. */
1391 if (++cur
[ord
[0]] == lines
[ord
[0]].used
)
1392 if (fillbuf (&buffer
[ord
[0]], fps
[ord
[0]]))
1394 findlines (&buffer
[ord
[0]], &lines
[ord
[0]]);
1399 /* We reached EOF on fps[ord[0]]. */
1400 for (i
= 1; i
< nfps
; ++i
)
1401 if (ord
[i
] > ord
[0])
1404 xfclose (fps
[ord
[0]]);
1405 free (buffer
[ord
[0]].buf
);
1406 free ((char *) lines
[ord
[0]].lines
);
1407 for (i
= ord
[0]; i
< nfps
; ++i
)
1409 fps
[i
] = fps
[i
+ 1];
1410 buffer
[i
] = buffer
[i
+ 1];
1411 lines
[i
] = lines
[i
+ 1];
1412 cur
[i
] = cur
[i
+ 1];
1414 for (i
= 0; i
< nfps
; ++i
)
1415 ord
[i
] = ord
[i
+ 1];
1419 /* The new line just read in may be larger than other lines
1420 already in core; push it back in the queue until we encounter
1421 a line larger than it. */
1422 for (i
= 1; i
< nfps
; ++i
)
1424 t
= compare (&lines
[ord
[0]].lines
[cur
[ord
[0]]],
1425 &lines
[ord
[i
]].lines
[cur
[ord
[i
]]]);
1427 t
= ord
[0] - ord
[i
];
1432 for (j
= 1; j
< i
; ++j
)
1433 ord
[j
- 1] = ord
[j
];
1437 if (unique
&& savedflag
)
1439 write_bytes (saved
.text
, saved
.length
, ofp
);
1440 putc (eolchar
, ofp
);
1445 /* Sort the array LINES with NLINES members, using TEMP for temporary space. */
1448 sortlines (struct line
*lines
, int nlines
, struct line
*temp
)
1450 register struct line
*lo
, *hi
, *t
;
1451 register int nlo
, nhi
;
1455 if (compare (&lines
[0], &lines
[1]) > 0)
1456 *temp
= lines
[0], lines
[0] = lines
[1], lines
[1] = *temp
;
1466 sortlines (lo
, nlo
, temp
);
1469 sortlines (hi
, nhi
, temp
);
1474 if (compare (lo
, hi
) <= 0)
1475 *t
++ = *lo
++, --nlo
;
1477 *t
++ = *hi
++, --nhi
;
1481 for (lo
= lines
, nlo
= nlines
- nhi
, t
= temp
; nlo
; --nlo
)
1485 /* Check that each of the NFILES FILES is ordered.
1486 Return a count of disordered files. */
1489 check (char **files
, int nfiles
)
1491 int i
, disorders
= 0;
1494 for (i
= 0; i
< nfiles
; ++i
)
1496 fp
= xfopen (files
[i
], "r");
1499 fprintf (stderr
, _("%s: disorder on %s\n"), program_name
, files
[i
]);
1506 /* Merge NFILES FILES onto OFP. */
1509 merge (char **files
, int nfiles
, FILE *ofp
)
1513 FILE *fps
[NMERGE
], *tfp
;
1515 while (nfiles
> NMERGE
)
1518 for (i
= 0; i
< nfiles
/ NMERGE
; ++i
)
1520 for (j
= 0; j
< NMERGE
; ++j
)
1521 fps
[j
] = xfopen (files
[i
* NMERGE
+ j
], "r");
1522 tfp
= xtmpfopen (temp
= tempname ());
1523 mergefps (fps
, NMERGE
, tfp
);
1525 for (j
= 0; j
< NMERGE
; ++j
)
1526 zaptemp (files
[i
* NMERGE
+ j
]);
1529 for (j
= 0; j
< nfiles
% NMERGE
; ++j
)
1530 fps
[j
] = xfopen (files
[i
* NMERGE
+ j
], "r");
1531 tfp
= xtmpfopen (temp
= tempname ());
1532 mergefps (fps
, nfiles
% NMERGE
, tfp
);
1534 for (j
= 0; j
< nfiles
% NMERGE
; ++j
)
1535 zaptemp (files
[i
* NMERGE
+ j
]);
1540 for (i
= 0; i
< nfiles
; ++i
)
1541 fps
[i
] = xfopen (files
[i
], "r");
1542 mergefps (fps
, i
, ofp
);
1543 for (i
= 0; i
< nfiles
; ++i
)
1547 /* Sort NFILES FILES onto OFP. */
1550 sort (char **files
, int nfiles
, FILE *ofp
)
1557 struct tempnode
*node
;
1558 int n_temp_files
= 0;
1561 initbuf (&buf
, sortalloc
);
1562 initlines (&lines
, sortalloc
/ linelength
+ 1,
1563 LINEALLOC
/ sizeof (struct line
));
1565 tmp
= (struct line
*) xmalloc (ntmp
* sizeof (struct line
));
1569 fp
= xfopen (*files
++, "r");
1570 while (fillbuf (&buf
, fp
))
1572 findlines (&buf
, &lines
);
1573 if (lines
.used
> ntmp
)
1575 while (lines
.used
> ntmp
)
1577 tmp
= (struct line
*)
1578 xrealloc ((char *) tmp
, ntmp
* sizeof (struct line
));
1580 sortlines (lines
.lines
, lines
.used
, tmp
);
1581 if (feof (fp
) && !nfiles
&& !n_temp_files
&& !buf
.left
)
1586 tfp
= xtmpfopen (tempname ());
1588 for (i
= 0; i
< lines
.used
; ++i
)
1589 if (!unique
|| i
== 0
1590 || compare (&lines
.lines
[i
], &lines
.lines
[i
- 1]))
1592 write_bytes (lines
.lines
[i
].text
, lines
.lines
[i
].length
, tfp
);
1593 putc (eolchar
, tfp
);
1602 free ((char *) lines
.lines
);
1603 free ((char *) tmp
);
1607 tempfiles
= (char **) xmalloc (n_temp_files
* sizeof (char *));
1609 for (node
= temphead
.next
; i
> 0; node
= node
->next
)
1610 tempfiles
[--i
] = node
->name
;
1611 merge (tempfiles
, n_temp_files
, ofp
);
1612 free ((char *) tempfiles
);
1616 /* Insert key KEY at the end of the list (`keyhead'). */
1619 insertkey (struct keyfield
*key
)
1621 struct keyfield
*k
= &keyhead
;
1630 badfieldspec (const char *s
)
1632 error (SORT_FAILURE
, 0, _("invalid field specification `%s'"), s
);
1635 /* Handle interrupts and hangups. */
1638 sighandler (int sig
)
1641 struct sigaction sigact
;
1643 sigact
.sa_handler
= SIG_DFL
;
1644 sigemptyset (&sigact
.sa_mask
);
1645 sigact
.sa_flags
= 0;
1646 sigaction (sig
, &sigact
, NULL
);
1647 #else /* !SA_INTERRUPT */
1648 signal (sig
, SIG_DFL
);
1649 #endif /* SA_INTERRUPT */
1651 kill (getpid (), sig
);
1654 /* Set the ordering options for KEY specified in S.
1655 Return the address of the first character in S that
1656 is not a valid ordering option.
1657 BLANKTYPE is the kind of blanks that 'b' should skip. */
1660 set_ordering (register const char *s
, struct keyfield
*key
,
1661 enum blanktype blanktype
)
1668 if (blanktype
== bl_start
|| blanktype
== bl_both
)
1669 key
->skipsblanks
= 1;
1670 if (blanktype
== bl_end
|| blanktype
== bl_both
)
1671 key
->skipeblanks
= 1;
1674 key
->ignore
= nondictionary
;
1677 key
->translate
= fold_toupper
;
1680 key
->general_numeric
= 1;
1683 key
->ignore
= nonprinting
;
1690 if (blanktype
== bl_start
|| blanktype
== bl_both
)
1691 key
->skipsblanks
= 1;
1692 if (blanktype
== bl_end
|| blanktype
== bl_both
)
1693 key
->skipeblanks
= 1;
1707 main (int argc
, char **argv
)
1709 struct keyfield
*key
= NULL
, gkey
;
1712 int checkonly
= 0, mergeonly
= 0, nfiles
= 0;
1713 char *minus
= "-", *outfile
= minus
, **files
, *tmp
;
1716 struct sigaction oldact
, newact
;
1717 #endif /* SA_INTERRUPT */
1719 program_name
= argv
[0];
1720 setlocale (LC_ALL
, "");
1721 bindtextdomain (PACKAGE
, LOCALEDIR
);
1722 textdomain (PACKAGE
);
1724 parse_long_options (argc
, argv
, "sort", PACKAGE_VERSION
, usage
);
1726 have_read_stdin
= 0;
1729 temp_file_prefix
= getenv ("TMPDIR");
1730 if (temp_file_prefix
== NULL
)
1731 temp_file_prefix
= DEFAULT_TMPDIR
;
1734 newact
.sa_handler
= sighandler
;
1735 sigemptyset (&newact
.sa_mask
);
1736 newact
.sa_flags
= 0;
1738 sigaction (SIGINT
, NULL
, &oldact
);
1739 if (oldact
.sa_handler
!= SIG_IGN
)
1740 sigaction (SIGINT
, &newact
, NULL
);
1741 sigaction (SIGHUP
, NULL
, &oldact
);
1742 if (oldact
.sa_handler
!= SIG_IGN
)
1743 sigaction (SIGHUP
, &newact
, NULL
);
1744 sigaction (SIGPIPE
, NULL
, &oldact
);
1745 if (oldact
.sa_handler
!= SIG_IGN
)
1746 sigaction (SIGPIPE
, &newact
, NULL
);
1747 sigaction (SIGTERM
, NULL
, &oldact
);
1748 if (oldact
.sa_handler
!= SIG_IGN
)
1749 sigaction (SIGTERM
, &newact
, NULL
);
1750 #else /* !SA_INTERRUPT */
1751 if (signal (SIGINT
, SIG_IGN
) != SIG_IGN
)
1752 signal (SIGINT
, sighandler
);
1753 if (signal (SIGHUP
, SIG_IGN
) != SIG_IGN
)
1754 signal (SIGHUP
, sighandler
);
1755 if (signal (SIGPIPE
, SIG_IGN
) != SIG_IGN
)
1756 signal (SIGPIPE
, sighandler
);
1757 if (signal (SIGTERM
, SIG_IGN
) != SIG_IGN
)
1758 signal (SIGTERM
, sighandler
);
1759 #endif /* !SA_INTERRUPT */
1761 gkey
.sword
= gkey
.eword
= -1;
1763 gkey
.translate
= NULL
;
1764 gkey
.numeric
= gkey
.general_numeric
= gkey
.month
= gkey
.reverse
= 0;
1765 gkey
.skipsblanks
= gkey
.skipeblanks
= 0;
1767 files
= (char **) xmalloc (sizeof (char *) * argc
);
1769 for (i
= 1; i
< argc
; ++i
)
1771 if (argv
[i
][0] == '+')
1775 key
= (struct keyfield
*) xmalloc (sizeof (struct keyfield
));
1778 key
->translate
= NULL
;
1779 key
->skipsblanks
= key
->skipeblanks
= 0;
1780 key
->numeric
= key
->general_numeric
= key
->month
= key
->reverse
= 0;
1782 if (! (digits
[UCHAR (*s
)] || (*s
== '.' && digits
[UCHAR (s
[1])])))
1783 badfieldspec (argv
[i
]);
1784 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1785 t
= 10 * t
+ *s
- '0';
1788 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1789 t2
= 10 * t2
+ *s
- '0';
1797 s
= set_ordering (s
, key
, bl_start
);
1799 badfieldspec (argv
[i
]);
1801 else if (argv
[i
][0] == '-' && argv
[i
][1])
1804 if (digits
[UCHAR (*s
)] || (*s
== '.' && digits
[UCHAR (s
[1])]))
1808 /* Provoke with `sort -9'. */
1809 error (0, 0, _("when using the old-style +POS and -POS \
1810 key specifiers,\nthe +POS specifier must come first"));
1811 usage (SORT_FAILURE
);
1813 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1814 t
= t
* 10 + *s
- '0';
1817 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1818 t2
= t2
* 10 + *s
- '0';
1821 s
= set_ordering (s
, key
, bl_end
);
1823 badfieldspec (argv
[i
]);
1830 s
= set_ordering (s
, &gkey
, bl_both
);
1844 error (SORT_FAILURE
, 0,
1845 _("option `-k' requires an argument"));
1851 key
= (struct keyfield
*)
1852 xmalloc (sizeof (struct keyfield
));
1855 key
->translate
= NULL
;
1856 key
->skipsblanks
= key
->skipeblanks
= 0;
1857 key
->numeric
= key
->month
= key
->reverse
= 0;
1859 if (!digits
[UCHAR (*s
)])
1860 badfieldspec (argv
[i
]);
1861 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1862 t
= 10 * t
+ *s
- '0';
1865 /* Provoke with `sort -k0' */
1866 error (0, 0, _("the starting field number argument \
1867 to the `-k' option must be positive"));
1868 badfieldspec (argv
[i
]);
1874 if (!digits
[UCHAR (s
[1])])
1876 /* Provoke with `sort -k1.' */
1877 error (0, 0, _("starting field spec has `.' but \
1878 lacks following character offset"));
1879 badfieldspec (argv
[i
]);
1881 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1882 t2
= 10 * t2
+ *s
- '0';
1885 /* Provoke with `sort -k1.0' */
1886 error (0, 0, _("starting field character offset \
1887 argument to the `-k' option\nmust be positive"));
1888 badfieldspec (argv
[i
]);
1899 s
= set_ordering (s
, key
, bl_start
);
1906 badfieldspec (argv
[i
]);
1909 /* Skip over comma. */
1913 /* Provoke with `sort -k1,' */
1914 error (0, 0, _("field specification has `,' but \
1915 lacks following field spec"));
1916 badfieldspec (argv
[i
]);
1919 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1920 t
= t
* 10 + *s
- '0';
1923 /* Provoke with `sort -k1,0' */
1924 error (0, 0, _("ending field number argument \
1925 to the `-k' option must be positive"));
1926 badfieldspec (argv
[i
]);
1932 if (!digits
[UCHAR (s
[1])])
1934 /* Provoke with `sort -k1,1.' */
1935 error (0, 0, _("ending field spec has `.' \
1936 but lacks following character offset"));
1937 badfieldspec (argv
[i
]);
1939 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1940 t2
= t2
* 10 + *s
- '0';
1944 /* `-k 2,3' is equivalent to `+1 -3'. */
1949 s
= set_ordering (s
, key
, bl_end
);
1951 badfieldspec (argv
[i
]);
1965 error (SORT_FAILURE
, 0,
1966 _("option `-o' requires an argument"));
1968 outfile
= argv
[++i
];
1977 else if (i
< argc
- 1)
1983 error (SORT_FAILURE
, 0,
1984 _("option `-t' requires an argument"));
1988 temp_file_prefix
= ++s
;
1992 temp_file_prefix
= argv
[++i
];
1994 error (SORT_FAILURE
, 0,
1995 _("option `-T' requires an argument"));
2006 /* Accept and ignore e.g. -y0 for compatibility with
2010 fprintf (stderr
, _("%s: unrecognized option `-%c'\n"),
2012 usage (SORT_FAILURE
);
2018 else /* Not an option. */
2020 files
[nfiles
++] = argv
[i
];
2028 /* Inheritance of global options to individual keys. */
2029 for (key
= keyhead
.next
; key
; key
= key
->next
)
2030 if (!key
->ignore
&& !key
->translate
&& !key
->skipsblanks
&& !key
->reverse
2031 && !key
->skipeblanks
&& !key
->month
&& !key
->numeric
2032 && !key
->general_numeric
)
2034 key
->ignore
= gkey
.ignore
;
2035 key
->translate
= gkey
.translate
;
2036 key
->skipsblanks
= gkey
.skipsblanks
;
2037 key
->skipeblanks
= gkey
.skipeblanks
;
2038 key
->month
= gkey
.month
;
2039 key
->numeric
= gkey
.numeric
;
2040 key
->general_numeric
= gkey
.general_numeric
;
2041 key
->reverse
= gkey
.reverse
;
2044 if (!keyhead
.next
&& (gkey
.ignore
|| gkey
.translate
|| gkey
.skipsblanks
2045 || gkey
.skipeblanks
|| gkey
.month
|| gkey
.numeric
2046 || gkey
.general_numeric
))
2048 reverse
= gkey
.reverse
;
2058 /* POSIX requires that sort return 1 IFF invoked with -c and the
2059 input is not properly sorted. */
2060 exit (check (files
, nfiles
) == 0 ? 0 : 1);
2063 if (strcmp (outfile
, "-"))
2065 struct stat outstat
;
2066 if (stat (outfile
, &outstat
) == 0)
2068 /* The following code prevents a race condition when
2069 people use the brain dead shell programming idiom:
2070 cat file | sort -o file
2071 This feature is provided for historical compatibility,
2072 but we strongly discourage ever relying on this in
2073 new shell programs. */
2075 /* Temporarily copy each input file that might be another name
2076 for the output file. When in doubt (e.g. a pipe), copy. */
2077 for (i
= 0; i
< nfiles
; ++i
)
2083 if (S_ISREG (outstat
.st_mode
) && strcmp (outfile
, files
[i
]))
2086 if ((strcmp (files
[i
], "-")
2087 ? stat (files
[i
], &instat
)
2088 : fstat (STDIN_FILENO
, &instat
)) != 0)
2090 error (0, errno
, "%s", files
[i
]);
2092 exit (SORT_FAILURE
);
2094 if (S_ISREG (instat
.st_mode
)
2095 && (instat
.st_ino
!= outstat
.st_ino
2096 || instat
.st_dev
!= outstat
.st_dev
))
2098 /* We know the files are distinct. */
2103 fp
= xfopen (files
[i
], "r");
2105 ofp
= xtmpfopen (tmp
);
2106 while ((cc
= fread (buf
, 1, sizeof buf
, fp
)) > 0)
2107 write_bytes (buf
, cc
, ofp
);
2110 error (0, errno
, "%s", files
[i
]);
2112 exit (SORT_FAILURE
);
2119 ofp
= xfopen (outfile
, "w");
2125 merge (files
, nfiles
, ofp
);
2127 sort (files
, nfiles
, ofp
);
2130 /* If we wait for the implicit flush on exit, and the parent process
2131 has closed stdout (e.g., exec >&- in a shell), then the output file
2132 winds up empty. I don't understand why. This is under SunOS,
2133 Solaris, Ultrix, and Irix. This premature fflush makes the output
2134 reappear. --karl@cs.umb.edu */
2135 if (fflush (ofp
) < 0)
2136 error (SORT_FAILURE
, errno
, _("%s: write error"), outfile
);
2138 if (have_read_stdin
&& fclose (stdin
) == EOF
)
2139 error (SORT_FAILURE
, errno
, outfile
);
2140 if (ferror (stdout
) || fclose (stdout
) == EOF
)
2141 error (SORT_FAILURE
, errno
, _("%s: write error"), outfile
);
2143 exit (EXIT_SUCCESS
);