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 /* Make LIM point to the end of (one byte past) the current field. */
617 newlim
= memchr (ptr
, tab
, lim
- ptr
);
625 while (newlim
< lim
&& blanks
[UCHAR (*newlim
)])
627 while (newlim
< lim
&& !blanks
[UCHAR (*newlim
)])
632 /* If we're skipping leading blanks, don't start counting characters
633 until after skipping past any leading blanks. */
634 if (key
->skipsblanks
)
635 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
638 /* Advance PTR by ECHAR (if possible), but no further than LIM. */
639 if (ptr
+ echar
<= lim
)
650 trim_trailing_blanks (const char *a_start
, char **a_end
)
652 while (*a_end
> a_start
&& blanks
[UCHAR (*(*a_end
- 1))])
656 /* Find the lines in BUF, storing pointers and lengths in LINES.
657 Also replace newlines in BUF with NULs. */
660 findlines (struct buffer
*buf
, struct lines
*lines
)
662 register char *beg
= buf
->buf
, *lim
= buf
->buf
+ buf
->used
, *ptr
;
663 struct keyfield
*key
= keyhead
.next
;
667 while (beg
< lim
&& (ptr
= memchr (beg
, eolchar
, lim
- beg
))
668 && lines
->used
< lines
->limit
)
670 /* There are various places in the code that rely on a NUL
671 being at the end of in-core lines; NULs inside the lines
672 will not cause trouble, though. */
675 if (lines
->used
== lines
->alloc
)
678 lines
->lines
= (struct line
*)
679 xrealloc ((char *) lines
->lines
,
680 lines
->alloc
* sizeof (struct line
));
683 lines
->lines
[lines
->used
].text
= beg
;
684 lines
->lines
[lines
->used
].length
= ptr
- beg
;
686 /* Precompute the position of the first key for efficiency. */
690 lines
->lines
[lines
->used
].keylim
=
691 limfield (&lines
->lines
[lines
->used
], key
);
693 lines
->lines
[lines
->used
].keylim
= ptr
;
696 lines
->lines
[lines
->used
].keybeg
=
697 begfield (&lines
->lines
[lines
->used
], key
);
700 if (key
->skipsblanks
)
701 while (blanks
[UCHAR (*beg
)])
703 lines
->lines
[lines
->used
].keybeg
= beg
;
705 if (key
->skipeblanks
)
707 trim_trailing_blanks (lines
->lines
[lines
->used
].keybeg
,
708 &lines
->lines
[lines
->used
].keylim
);
713 lines
->lines
[lines
->used
].keybeg
= 0;
714 lines
->lines
[lines
->used
].keylim
= 0;
721 buf
->left
= lim
- beg
;
724 /* Compare strings A and B containing decimal fractions < 1. Each string
725 should begin with a decimal point followed immediately by the digits
726 of the fraction. Strings not of this form are considered to be zero. */
729 fraccompare (register const char *a
, register const char *b
)
731 register tmpa
= UCHAR (*a
), tmpb
= UCHAR (*b
);
733 if (tmpa
== '.' && tmpb
== '.')
736 tmpa
= UCHAR (*++a
), tmpb
= UCHAR (*++b
);
737 while (tmpa
== tmpb
&& digits
[tmpa
]);
738 if (digits
[tmpa
] && digits
[tmpb
])
758 else if (tmpa
== '.')
767 else if (tmpb
== '.')
779 /* Compare strings A and B as numbers without explicitly converting them to
780 machine numbers. Comparatively slow for short strings, but asymptotically
784 numcompare (register const char *a
, register const char *b
)
786 register int tmpa
, tmpb
, loga
, logb
, tmp
;
823 while (tmpa
== tmpb
&& digits
[tmpa
])
824 tmpa
= UCHAR (*++a
), tmpb
= UCHAR (*++b
);
826 if ((tmpa
== '.' && !digits
[tmpb
]) || (tmpb
== '.' && !digits
[tmpa
]))
827 return -fraccompare (a
, b
);
830 for (loga
= 1; digits
[UCHAR (*++a
)]; ++loga
)
836 for (logb
= 1; digits
[UCHAR (*++b
)]; ++logb
)
841 if ((tmp
= logb
- loga
) != 0)
849 else if (tmpb
== '-')
877 while (tmpa
== tmpb
&& digits
[tmpa
])
878 tmpa
= UCHAR (*++a
), tmpb
= UCHAR (*++b
);
880 if ((tmpa
== '.' && !digits
[tmpb
]) || (tmpb
== '.' && !digits
[tmpa
]))
881 return fraccompare (a
, b
);
884 for (loga
= 1; digits
[UCHAR (*++a
)]; ++loga
)
890 for (logb
= 1; digits
[UCHAR (*++b
)]; ++logb
)
895 if ((tmp
= loga
- logb
) != 0)
906 general_numcompare (const char *sa
, const char *sb
)
909 /* FIXME: add option to warn about failed conversions. */
910 /* FIXME: maybe add option to try expensive FP conversion
911 only if A and B can't be compared more cheaply/accurately. */
912 if (xstrtod (sa
, NULL
, &a
))
916 if (xstrtod (sb
, NULL
, &b
))
920 return a
== b
? 0 : a
< b
? -1 : 1;
923 /* Return an integer <= 12 associated with month name S with length LEN,
924 0 if the name in S is not recognized. */
927 getmonth (const char *s
, int len
)
930 register int i
, lo
= 0, hi
= 12;
932 while (len
> 0 && blanks
[UCHAR(*s
)])
938 for (i
= 0; i
< 3; ++i
)
939 month
[i
] = fold_toupper
[UCHAR (s
[i
])];
943 if (strcmp (month
, monthtab
[(lo
+ hi
) / 2].name
) < 0)
947 if (!strcmp (month
, monthtab
[lo
].name
))
948 return monthtab
[lo
].val
;
952 /* Compare two lines A and B trying every key in sequence until there
953 are no more keys or a difference is found. */
956 keycompare (const struct line
*a
, const struct line
*b
)
958 register char *texta
, *textb
, *lima
, *limb
, *translate
;
959 register int *ignore
;
960 struct keyfield
*key
;
961 int diff
= 0, iter
= 0, lena
, lenb
;
963 for (key
= keyhead
.next
; key
; key
= key
->next
, ++iter
)
965 ignore
= key
->ignore
;
966 translate
= key
->translate
;
968 /* Find the beginning and limit of each field. */
969 if (iter
|| a
->keybeg
== NULL
|| b
->keybeg
== NULL
)
972 lima
= limfield (a
, key
), limb
= limfield (b
, key
);
974 lima
= a
->text
+ a
->length
, limb
= b
->text
+ b
->length
;
977 texta
= begfield (a
, key
), textb
= begfield (b
, key
);
980 texta
= a
->text
, textb
= b
->text
;
981 if (key
->skipsblanks
)
983 while (texta
< lima
&& blanks
[UCHAR (*texta
)])
985 while (textb
< limb
&& blanks
[UCHAR (*textb
)])
992 /* For the first iteration only, the key positions have
993 been precomputed for us. */
994 texta
= a
->keybeg
, lima
= a
->keylim
;
995 textb
= b
->keybeg
, limb
= b
->keylim
;
998 /* Find the lengths. */
999 lena
= lima
- texta
, lenb
= limb
- textb
;
1005 if (key
->skipeblanks
)
1007 char *a_end
= texta
+ lena
;
1008 char *b_end
= textb
+ lenb
;
1009 trim_trailing_blanks (texta
, &a_end
);
1010 trim_trailing_blanks (textb
, &b_end
);
1011 lena
= a_end
- texta
;
1012 lenb
= b_end
- textb
;
1015 /* Actually compare the fields. */
1020 char savea
= *lima
, saveb
= *limb
;
1022 *lima
= *limb
= '\0';
1023 diff
= numcompare (texta
, textb
);
1024 *lima
= savea
, *limb
= saveb
;
1027 diff
= numcompare (texta
, textb
);
1030 return key
->reverse
? -diff
: diff
;
1033 else if (key
->general_numeric
)
1037 char savea
= *lima
, saveb
= *limb
;
1039 *lima
= *limb
= '\0';
1040 diff
= general_numcompare (texta
, textb
);
1041 *lima
= savea
, *limb
= saveb
;
1044 diff
= general_numcompare (texta
, textb
);
1047 return key
->reverse
? -diff
: diff
;
1050 else if (key
->month
)
1052 diff
= getmonth (texta
, lena
) - getmonth (textb
, lenb
);
1054 return key
->reverse
? -diff
: diff
;
1057 else if (ignore
&& translate
)
1059 #define CMP_WITH_IGNORE(A, B) \
1062 while (texta < lima && textb < limb) \
1064 while (texta < lima && ignore[UCHAR (*texta)]) \
1066 while (textb < limb && ignore[UCHAR (*textb)]) \
1068 if (texta < lima && textb < limb) \
1079 if (texta == lima && textb < limb && !ignore[UCHAR (*textb)]) \
1081 else if (texta < lima && textb == limb \
1082 && !ignore[UCHAR (*texta)]) \
1088 while (texta < lima && ignore[UCHAR (*texta)]) \
1090 while (textb < limb && ignore[UCHAR (*textb)]) \
1093 if (texta == lima && textb < limb) \
1095 else if (texta < lima && textb == limb) \
1098 /* Relative lengths are meaningless if characters were ignored. \
1099 Handling this case here avoids what might be an invalid length \
1100 comparison below. */ \
1101 if (diff == 0 && texta == lima && textb == limb) \
1106 CMP_WITH_IGNORE (translate
[UCHAR (*texta
)], translate
[UCHAR (*textb
)]);
1108 CMP_WITH_IGNORE (*texta
, *textb
);
1110 while (texta
< lima
&& textb
< limb
)
1112 if (translate
[UCHAR (*texta
++)] != translate
[UCHAR (*textb
++)])
1114 diff
= (translate
[UCHAR (*--texta
)]
1115 - translate
[UCHAR (*--textb
)]);
1120 diff
= memcmp (texta
, textb
, min (lena
, lenb
));
1123 return key
->reverse
? -diff
: diff
;
1124 if ((diff
= lena
- lenb
) != 0)
1125 return key
->reverse
? -diff
: diff
;
1131 /* Compare two lines A and B, returning negative, zero, or positive
1132 depending on whether A compares less than, equal to, or greater than B. */
1135 compare (register const struct line
*a
, register const struct line
*b
)
1137 int diff
, tmpa
, tmpb
, mini
;
1139 /* First try to compare on the specified keys (if any).
1140 The only two cases with no key at all are unadorned sort,
1141 and unadorned sort -r. */
1144 diff
= keycompare (a
, b
);
1147 if (unique
|| stable
)
1151 /* If the keys all compare equal (or no keys were specified)
1152 fall through to the default byte-by-byte comparison. */
1153 tmpa
= a
->length
, tmpb
= b
->length
;
1154 mini
= min (tmpa
, tmpb
);
1159 char *ap
= a
->text
, *bp
= b
->text
;
1161 diff
= UCHAR (*ap
) - UCHAR (*bp
);
1164 diff
= memcmp (ap
, bp
, mini
);
1170 return reverse
? -diff
: diff
;
1173 /* Check that the lines read from the given FP come in order. Return
1174 1 if they do and 0 if there is a disorder.
1175 FIXME: return number of first out-of-order line if not sorted. */
1180 struct buffer buf
; /* Input buffer. */
1181 struct lines lines
; /* Lines scanned from the buffer. */
1182 struct line temp
; /* Copy of previous line. */
1183 int cc
; /* Character count. */
1184 int alloc
, sorted
= 1;
1186 initbuf (&buf
, mergealloc
);
1187 initlines (&lines
, mergealloc
/ linelength
+ 1,
1188 LINEALLOC
/ ((NMERGE
+ NMERGE
) * sizeof (struct line
)));
1190 temp
.text
= xmalloc (alloc
);
1192 cc
= fillbuf (&buf
, fp
);
1196 findlines (&buf
, &lines
);
1200 struct line
*prev_line
; /* Pointer to previous line. */
1201 int cmp
; /* Result of calling compare. */
1204 /* Compare each line in the buffer with its successor. */
1205 for (i
= 0; i
< lines
.used
- 1; ++i
)
1207 cmp
= compare (&lines
.lines
[i
], &lines
.lines
[i
+ 1]);
1208 if ((unique
&& cmp
>= 0) || (cmp
> 0))
1215 /* Save the last line of the buffer and refill the buffer. */
1216 prev_line
= lines
.lines
+ (lines
.used
- 1);
1217 if (prev_line
->length
> alloc
)
1219 while (prev_line
->length
+ 1 > alloc
)
1221 temp
.text
= xrealloc (temp
.text
, alloc
);
1223 memcpy (temp
.text
, prev_line
->text
, prev_line
->length
+ 1);
1224 temp
.length
= prev_line
->length
;
1225 temp
.keybeg
= temp
.text
+ (prev_line
->keybeg
- prev_line
->text
);
1226 temp
.keylim
= temp
.text
+ (prev_line
->keylim
- prev_line
->text
);
1228 cc
= fillbuf (&buf
, fp
);
1232 findlines (&buf
, &lines
);
1233 /* Make sure the line saved from the old buffer contents is
1234 less than or equal to the first line of the new buffer. */
1235 cmp
= compare (&temp
, &lines
.lines
[0]);
1236 if ((unique
&& cmp
>= 0) || (cmp
> 0))
1246 free ((char *) lines
.lines
);
1251 /* Merge lines from FPS onto OFP. NFPS cannot be greater than NMERGE.
1252 Close FPS before returning. */
1255 mergefps (FILE **fps
, register int nfps
, FILE *ofp
)
1257 struct buffer buffer
[NMERGE
]; /* Input buffers for each file. */
1258 struct lines lines
[NMERGE
]; /* Line tables for each buffer. */
1259 struct line saved
; /* Saved line for unique check. */
1260 int savedflag
= 0; /* True if there is a saved line. */
1261 int savealloc
; /* Size allocated for the saved line. */
1262 int cur
[NMERGE
]; /* Current line in each line table. */
1263 int ord
[NMERGE
]; /* Table representing a permutation of fps,
1264 such that lines[ord[0]].lines[cur[ord[0]]]
1265 is the smallest line and will be next
1267 register int i
, j
, t
;
1269 #ifdef lint /* Suppress `used before initialized' warning. */
1273 /* Allocate space for a saved line if necessary. */
1276 savealloc
= linelength
;
1277 saved
.text
= xmalloc (savealloc
);
1280 /* Read initial lines from each input file. */
1281 for (i
= 0; i
< nfps
; ++i
)
1283 initbuf (&buffer
[i
], mergealloc
);
1284 /* If a file is empty, eliminate it from future consideration. */
1285 while (i
< nfps
&& !fillbuf (&buffer
[i
], fps
[i
]))
1289 for (j
= i
; j
< nfps
; ++j
)
1290 fps
[j
] = fps
[j
+ 1];
1293 free (buffer
[i
].buf
);
1296 initlines (&lines
[i
], mergealloc
/ linelength
+ 1,
1297 LINEALLOC
/ ((NMERGE
+ NMERGE
) * sizeof (struct line
)));
1298 findlines (&buffer
[i
], &lines
[i
]);
1303 /* Set up the ord table according to comparisons among input lines.
1304 Since this only reorders two items if one is strictly greater than
1305 the other, it is stable. */
1306 for (i
= 0; i
< nfps
; ++i
)
1308 for (i
= 1; i
< nfps
; ++i
)
1309 if (compare (&lines
[ord
[i
- 1]].lines
[cur
[ord
[i
- 1]]],
1310 &lines
[ord
[i
]].lines
[cur
[ord
[i
]]]) > 0)
1311 t
= ord
[i
- 1], ord
[i
- 1] = ord
[i
], ord
[i
] = t
, i
= 0;
1313 /* Repeatedly output the smallest line until no input remains. */
1316 /* If uniqified output is turned on, output only the first of
1317 an identical series of lines. */
1320 if (savedflag
&& compare (&saved
, &lines
[ord
[0]].lines
[cur
[ord
[0]]]))
1322 write_bytes (saved
.text
, saved
.length
, ofp
);
1323 putc (eolchar
, ofp
);
1328 if (savealloc
< lines
[ord
[0]].lines
[cur
[ord
[0]]].length
+ 1)
1330 while (savealloc
< lines
[ord
[0]].lines
[cur
[ord
[0]]].length
+ 1)
1332 saved
.text
= xrealloc (saved
.text
, savealloc
);
1334 saved
.length
= lines
[ord
[0]].lines
[cur
[ord
[0]]].length
;
1335 memcpy (saved
.text
, lines
[ord
[0]].lines
[cur
[ord
[0]]].text
,
1337 if (lines
[ord
[0]].lines
[cur
[ord
[0]]].keybeg
!= NULL
)
1339 saved
.keybeg
= saved
.text
+
1340 (lines
[ord
[0]].lines
[cur
[ord
[0]]].keybeg
1341 - lines
[ord
[0]].lines
[cur
[ord
[0]]].text
);
1343 if (lines
[ord
[0]].lines
[cur
[ord
[0]]].keylim
!= NULL
)
1345 saved
.keylim
= saved
.text
+
1346 (lines
[ord
[0]].lines
[cur
[ord
[0]]].keylim
1347 - lines
[ord
[0]].lines
[cur
[ord
[0]]].text
);
1354 write_bytes (lines
[ord
[0]].lines
[cur
[ord
[0]]].text
,
1355 lines
[ord
[0]].lines
[cur
[ord
[0]]].length
, ofp
);
1356 putc (eolchar
, ofp
);
1359 /* Check if we need to read more lines into core. */
1360 if (++cur
[ord
[0]] == lines
[ord
[0]].used
)
1361 if (fillbuf (&buffer
[ord
[0]], fps
[ord
[0]]))
1363 findlines (&buffer
[ord
[0]], &lines
[ord
[0]]);
1368 /* We reached EOF on fps[ord[0]]. */
1369 for (i
= 1; i
< nfps
; ++i
)
1370 if (ord
[i
] > ord
[0])
1373 xfclose (fps
[ord
[0]]);
1374 free (buffer
[ord
[0]].buf
);
1375 free ((char *) lines
[ord
[0]].lines
);
1376 for (i
= ord
[0]; i
< nfps
; ++i
)
1378 fps
[i
] = fps
[i
+ 1];
1379 buffer
[i
] = buffer
[i
+ 1];
1380 lines
[i
] = lines
[i
+ 1];
1381 cur
[i
] = cur
[i
+ 1];
1383 for (i
= 0; i
< nfps
; ++i
)
1384 ord
[i
] = ord
[i
+ 1];
1388 /* The new line just read in may be larger than other lines
1389 already in core; push it back in the queue until we encounter
1390 a line larger than it. */
1391 for (i
= 1; i
< nfps
; ++i
)
1393 t
= compare (&lines
[ord
[0]].lines
[cur
[ord
[0]]],
1394 &lines
[ord
[i
]].lines
[cur
[ord
[i
]]]);
1396 t
= ord
[0] - ord
[i
];
1401 for (j
= 1; j
< i
; ++j
)
1402 ord
[j
- 1] = ord
[j
];
1406 if (unique
&& savedflag
)
1408 write_bytes (saved
.text
, saved
.length
, ofp
);
1409 putc (eolchar
, ofp
);
1414 /* Sort the array LINES with NLINES members, using TEMP for temporary space. */
1417 sortlines (struct line
*lines
, int nlines
, struct line
*temp
)
1419 register struct line
*lo
, *hi
, *t
;
1420 register int nlo
, nhi
;
1424 if (compare (&lines
[0], &lines
[1]) > 0)
1425 *temp
= lines
[0], lines
[0] = lines
[1], lines
[1] = *temp
;
1435 sortlines (lo
, nlo
, temp
);
1438 sortlines (hi
, nhi
, temp
);
1443 if (compare (lo
, hi
) <= 0)
1444 *t
++ = *lo
++, --nlo
;
1446 *t
++ = *hi
++, --nhi
;
1450 for (lo
= lines
, nlo
= nlines
- nhi
, t
= temp
; nlo
; --nlo
)
1454 /* Check that each of the NFILES FILES is ordered.
1455 Return a count of disordered files. */
1458 check (char **files
, int nfiles
)
1460 int i
, disorders
= 0;
1463 for (i
= 0; i
< nfiles
; ++i
)
1465 fp
= xfopen (files
[i
], "r");
1468 fprintf (stderr
, _("%s: disorder on %s\n"), program_name
, files
[i
]);
1475 /* Merge NFILES FILES onto OFP. */
1478 merge (char **files
, int nfiles
, FILE *ofp
)
1482 FILE *fps
[NMERGE
], *tfp
;
1484 while (nfiles
> NMERGE
)
1487 for (i
= 0; i
< nfiles
/ NMERGE
; ++i
)
1489 for (j
= 0; j
< NMERGE
; ++j
)
1490 fps
[j
] = xfopen (files
[i
* NMERGE
+ j
], "r");
1491 tfp
= xtmpfopen (temp
= tempname ());
1492 mergefps (fps
, NMERGE
, tfp
);
1494 for (j
= 0; j
< NMERGE
; ++j
)
1495 zaptemp (files
[i
* NMERGE
+ j
]);
1498 for (j
= 0; j
< nfiles
% NMERGE
; ++j
)
1499 fps
[j
] = xfopen (files
[i
* NMERGE
+ j
], "r");
1500 tfp
= xtmpfopen (temp
= tempname ());
1501 mergefps (fps
, nfiles
% NMERGE
, tfp
);
1503 for (j
= 0; j
< nfiles
% NMERGE
; ++j
)
1504 zaptemp (files
[i
* NMERGE
+ j
]);
1509 for (i
= 0; i
< nfiles
; ++i
)
1510 fps
[i
] = xfopen (files
[i
], "r");
1511 mergefps (fps
, i
, ofp
);
1512 for (i
= 0; i
< nfiles
; ++i
)
1516 /* Sort NFILES FILES onto OFP. */
1519 sort (char **files
, int nfiles
, FILE *ofp
)
1526 struct tempnode
*node
;
1527 int n_temp_files
= 0;
1530 initbuf (&buf
, sortalloc
);
1531 initlines (&lines
, sortalloc
/ linelength
+ 1,
1532 LINEALLOC
/ sizeof (struct line
));
1534 tmp
= (struct line
*) xmalloc (ntmp
* sizeof (struct line
));
1538 fp
= xfopen (*files
++, "r");
1539 while (fillbuf (&buf
, fp
))
1541 findlines (&buf
, &lines
);
1542 if (lines
.used
> ntmp
)
1544 while (lines
.used
> ntmp
)
1546 tmp
= (struct line
*)
1547 xrealloc ((char *) tmp
, ntmp
* sizeof (struct line
));
1549 sortlines (lines
.lines
, lines
.used
, tmp
);
1550 if (feof (fp
) && !nfiles
&& !n_temp_files
&& !buf
.left
)
1555 tfp
= xtmpfopen (tempname ());
1557 for (i
= 0; i
< lines
.used
; ++i
)
1558 if (!unique
|| i
== 0
1559 || compare (&lines
.lines
[i
], &lines
.lines
[i
- 1]))
1561 write_bytes (lines
.lines
[i
].text
, lines
.lines
[i
].length
, tfp
);
1562 putc (eolchar
, tfp
);
1571 free ((char *) lines
.lines
);
1572 free ((char *) tmp
);
1576 tempfiles
= (char **) xmalloc (n_temp_files
* sizeof (char *));
1578 for (node
= temphead
.next
; i
> 0; node
= node
->next
)
1579 tempfiles
[--i
] = node
->name
;
1580 merge (tempfiles
, n_temp_files
, ofp
);
1581 free ((char *) tempfiles
);
1585 /* Insert key KEY at the end of the list (`keyhead'). */
1588 insertkey (struct keyfield
*key
)
1590 struct keyfield
*k
= &keyhead
;
1599 badfieldspec (const char *s
)
1601 error (SORT_FAILURE
, 0, _("invalid field specification `%s'"), s
);
1604 /* Handle interrupts and hangups. */
1607 sighandler (int sig
)
1610 struct sigaction sigact
;
1612 sigact
.sa_handler
= SIG_DFL
;
1613 sigemptyset (&sigact
.sa_mask
);
1614 sigact
.sa_flags
= 0;
1615 sigaction (sig
, &sigact
, NULL
);
1616 #else /* !SA_INTERRUPT */
1617 signal (sig
, SIG_DFL
);
1618 #endif /* SA_INTERRUPT */
1620 kill (getpid (), sig
);
1623 /* Set the ordering options for KEY specified in S.
1624 Return the address of the first character in S that
1625 is not a valid ordering option.
1626 BLANKTYPE is the kind of blanks that 'b' should skip. */
1629 set_ordering (register const char *s
, struct keyfield
*key
,
1630 enum blanktype blanktype
)
1637 if (blanktype
== bl_start
|| blanktype
== bl_both
)
1638 key
->skipsblanks
= 1;
1639 if (blanktype
== bl_end
|| blanktype
== bl_both
)
1640 key
->skipeblanks
= 1;
1643 key
->ignore
= nondictionary
;
1646 key
->translate
= fold_toupper
;
1649 key
->general_numeric
= 1;
1652 key
->ignore
= nonprinting
;
1659 if (blanktype
== bl_start
|| blanktype
== bl_both
)
1660 key
->skipsblanks
= 1;
1661 if (blanktype
== bl_end
|| blanktype
== bl_both
)
1662 key
->skipeblanks
= 1;
1676 main (int argc
, char **argv
)
1678 struct keyfield
*key
= NULL
, gkey
;
1681 int checkonly
= 0, mergeonly
= 0, nfiles
= 0;
1682 char *minus
= "-", *outfile
= minus
, **files
, *tmp
;
1685 struct sigaction oldact
, newact
;
1686 #endif /* SA_INTERRUPT */
1688 program_name
= argv
[0];
1689 setlocale (LC_ALL
, "");
1690 bindtextdomain (PACKAGE
, LOCALEDIR
);
1691 textdomain (PACKAGE
);
1693 parse_long_options (argc
, argv
, "sort", PACKAGE_VERSION
, usage
);
1695 have_read_stdin
= 0;
1698 temp_file_prefix
= getenv ("TMPDIR");
1699 if (temp_file_prefix
== NULL
)
1700 temp_file_prefix
= DEFAULT_TMPDIR
;
1703 newact
.sa_handler
= sighandler
;
1704 sigemptyset (&newact
.sa_mask
);
1705 newact
.sa_flags
= 0;
1707 sigaction (SIGINT
, NULL
, &oldact
);
1708 if (oldact
.sa_handler
!= SIG_IGN
)
1709 sigaction (SIGINT
, &newact
, NULL
);
1710 sigaction (SIGHUP
, NULL
, &oldact
);
1711 if (oldact
.sa_handler
!= SIG_IGN
)
1712 sigaction (SIGHUP
, &newact
, NULL
);
1713 sigaction (SIGPIPE
, NULL
, &oldact
);
1714 if (oldact
.sa_handler
!= SIG_IGN
)
1715 sigaction (SIGPIPE
, &newact
, NULL
);
1716 sigaction (SIGTERM
, NULL
, &oldact
);
1717 if (oldact
.sa_handler
!= SIG_IGN
)
1718 sigaction (SIGTERM
, &newact
, NULL
);
1719 #else /* !SA_INTERRUPT */
1720 if (signal (SIGINT
, SIG_IGN
) != SIG_IGN
)
1721 signal (SIGINT
, sighandler
);
1722 if (signal (SIGHUP
, SIG_IGN
) != SIG_IGN
)
1723 signal (SIGHUP
, sighandler
);
1724 if (signal (SIGPIPE
, SIG_IGN
) != SIG_IGN
)
1725 signal (SIGPIPE
, sighandler
);
1726 if (signal (SIGTERM
, SIG_IGN
) != SIG_IGN
)
1727 signal (SIGTERM
, sighandler
);
1728 #endif /* !SA_INTERRUPT */
1730 gkey
.sword
= gkey
.eword
= -1;
1732 gkey
.translate
= NULL
;
1733 gkey
.numeric
= gkey
.general_numeric
= gkey
.month
= gkey
.reverse
= 0;
1734 gkey
.skipsblanks
= gkey
.skipeblanks
= 0;
1736 files
= (char **) xmalloc (sizeof (char *) * argc
);
1738 for (i
= 1; i
< argc
; ++i
)
1740 if (argv
[i
][0] == '+')
1744 key
= (struct keyfield
*) xmalloc (sizeof (struct keyfield
));
1747 key
->translate
= NULL
;
1748 key
->skipsblanks
= key
->skipeblanks
= 0;
1749 key
->numeric
= key
->general_numeric
= key
->month
= key
->reverse
= 0;
1751 if (! (digits
[UCHAR (*s
)] || (*s
== '.' && digits
[UCHAR (s
[1])])))
1752 badfieldspec (argv
[i
]);
1753 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1754 t
= 10 * t
+ *s
- '0';
1757 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1758 t2
= 10 * t2
+ *s
- '0';
1766 s
= set_ordering (s
, key
, bl_start
);
1768 badfieldspec (argv
[i
]);
1770 else if (argv
[i
][0] == '-' && argv
[i
][1])
1773 if (digits
[UCHAR (*s
)] || (*s
== '.' && digits
[UCHAR (s
[1])]))
1777 /* Provoke with `sort -9'. */
1778 error (0, 0, _("when using the old-style +POS and -POS \
1779 key specifiers,\nthe +POS specifier must come first"));
1780 usage (SORT_FAILURE
);
1782 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1783 t
= t
* 10 + *s
- '0';
1786 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1787 t2
= t2
* 10 + *s
- '0';
1790 s
= set_ordering (s
, key
, bl_end
);
1792 badfieldspec (argv
[i
]);
1799 s
= set_ordering (s
, &gkey
, bl_both
);
1813 error (SORT_FAILURE
, 0,
1814 _("option `-k' requires an argument"));
1820 key
= (struct keyfield
*)
1821 xmalloc (sizeof (struct keyfield
));
1824 key
->translate
= NULL
;
1825 key
->skipsblanks
= key
->skipeblanks
= 0;
1826 key
->numeric
= key
->month
= key
->reverse
= 0;
1828 if (!digits
[UCHAR (*s
)])
1829 badfieldspec (argv
[i
]);
1830 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1831 t
= 10 * t
+ *s
- '0';
1834 /* Provoke with `sort -k0' */
1835 error (0, 0, _("the starting field number argument \
1836 to the `-k' option must be positive"));
1837 badfieldspec (argv
[i
]);
1843 if (!digits
[UCHAR (s
[1])])
1845 /* Provoke with `sort -k1.' */
1846 error (0, 0, _("starting field spec has `.' but \
1847 lacks following character offset"));
1848 badfieldspec (argv
[i
]);
1850 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1851 t2
= 10 * t2
+ *s
- '0';
1854 /* Provoke with `sort -k1.0' */
1855 error (0, 0, _("starting field character offset \
1856 argument to the `-k' option\nmust be positive"));
1857 badfieldspec (argv
[i
]);
1868 s
= set_ordering (s
, key
, bl_start
);
1875 badfieldspec (argv
[i
]);
1878 /* Skip over comma. */
1882 /* Provoke with `sort -k1,' */
1883 error (0, 0, _("field specification has `,' but \
1884 lacks following field spec"));
1885 badfieldspec (argv
[i
]);
1888 for (t
= 0; digits
[UCHAR (*s
)]; ++s
)
1889 t
= t
* 10 + *s
- '0';
1892 /* Provoke with `sort -k1,0' */
1893 error (0, 0, _("ending field number argument \
1894 to the `-k' option must be positive"));
1895 badfieldspec (argv
[i
]);
1901 if (!digits
[UCHAR (s
[1])])
1903 /* Provoke with `sort -k1,1.' */
1904 error (0, 0, _("ending field spec has `.' \
1905 but lacks following character offset"));
1906 badfieldspec (argv
[i
]);
1908 for (++s
; digits
[UCHAR (*s
)]; ++s
)
1909 t2
= t2
* 10 + *s
- '0';
1913 /* `-k 2,3' is equivalent to `+1 -3'. */
1918 s
= set_ordering (s
, key
, bl_end
);
1920 badfieldspec (argv
[i
]);
1934 error (SORT_FAILURE
, 0,
1935 _("option `-o' requires an argument"));
1937 outfile
= argv
[++i
];
1946 else if (i
< argc
- 1)
1952 error (SORT_FAILURE
, 0,
1953 _("option `-t' requires an argument"));
1957 temp_file_prefix
= ++s
;
1961 temp_file_prefix
= argv
[++i
];
1963 error (SORT_FAILURE
, 0,
1964 _("option `-T' requires an argument"));
1975 /* Accept and ignore e.g. -y0 for compatibility with
1979 fprintf (stderr
, _("%s: unrecognized option `-%c'\n"),
1981 usage (SORT_FAILURE
);
1987 else /* Not an option. */
1989 files
[nfiles
++] = argv
[i
];
1997 /* Inheritance of global options to individual keys. */
1998 for (key
= keyhead
.next
; key
; key
= key
->next
)
1999 if (!key
->ignore
&& !key
->translate
&& !key
->skipsblanks
&& !key
->reverse
2000 && !key
->skipeblanks
&& !key
->month
&& !key
->numeric
2001 && !key
->general_numeric
)
2003 key
->ignore
= gkey
.ignore
;
2004 key
->translate
= gkey
.translate
;
2005 key
->skipsblanks
= gkey
.skipsblanks
;
2006 key
->skipeblanks
= gkey
.skipeblanks
;
2007 key
->month
= gkey
.month
;
2008 key
->numeric
= gkey
.numeric
;
2009 key
->general_numeric
= gkey
.general_numeric
;
2010 key
->reverse
= gkey
.reverse
;
2013 if (!keyhead
.next
&& (gkey
.ignore
|| gkey
.translate
|| gkey
.skipsblanks
2014 || gkey
.skipeblanks
|| gkey
.month
|| gkey
.numeric
2015 || gkey
.general_numeric
))
2017 reverse
= gkey
.reverse
;
2027 /* POSIX requires that sort return 1 IFF invoked with -c and the
2028 input is not properly sorted. */
2029 exit (check (files
, nfiles
) == 0 ? 0 : 1);
2032 if (strcmp (outfile
, "-"))
2034 struct stat outstat
;
2035 if (stat (outfile
, &outstat
) == 0)
2037 /* The following code prevents a race condition when
2038 people use the brain dead shell programming idiom:
2039 cat file | sort -o file
2040 This feature is provided for historical compatibility,
2041 but we strongly discourage ever relying on this in
2042 new shell programs. */
2044 /* Temporarily copy each input file that might be another name
2045 for the output file. When in doubt (e.g. a pipe), copy. */
2046 for (i
= 0; i
< nfiles
; ++i
)
2052 if (S_ISREG (outstat
.st_mode
) && strcmp (outfile
, files
[i
]))
2055 if ((strcmp (files
[i
], "-")
2056 ? stat (files
[i
], &instat
)
2057 : fstat (fileno (stdin
), &instat
)) != 0)
2059 error (0, errno
, "%s", files
[i
]);
2061 exit (SORT_FAILURE
);
2063 if (S_ISREG (instat
.st_mode
)
2064 && (instat
.st_ino
!= outstat
.st_ino
2065 || instat
.st_dev
!= outstat
.st_dev
))
2067 /* We know the files are distinct. */
2072 fp
= xfopen (files
[i
], "r");
2074 ofp
= xtmpfopen (tmp
);
2075 while ((cc
= fread (buf
, 1, sizeof buf
, fp
)) > 0)
2076 write_bytes (buf
, cc
, ofp
);
2079 error (0, errno
, "%s", files
[i
]);
2081 exit (SORT_FAILURE
);
2088 ofp
= xfopen (outfile
, "w");
2094 merge (files
, nfiles
, ofp
);
2096 sort (files
, nfiles
, ofp
);
2099 /* If we wait for the implicit flush on exit, and the parent process
2100 has closed stdout (e.g., exec >&- in a shell), then the output file
2101 winds up empty. I don't understand why. This is under SunOS,
2102 Solaris, Ultrix, and Irix. This premature fflush makes the output
2103 reappear. --karl@cs.umb.edu */
2104 if (fflush (ofp
) < 0)
2105 error (SORT_FAILURE
, errno
, _("%s: write error"), outfile
);
2107 if (have_read_stdin
&& fclose (stdin
) == EOF
)
2108 error (SORT_FAILURE
, errno
, outfile
);
2109 if (ferror (stdout
) || fclose (stdout
) == EOF
)
2110 error (SORT_FAILURE
, errno
, _("%s: write error"), outfile
);
2112 exit (EXIT_SUCCESS
);