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>
30 #ifndef ENABLE_ASSERTIONS
35 #include "long-options.h"
52 /* Undefine, to avoid warning about redefinition on some systems. */
54 #define min(a, b) ((a) < (b) ? (a) : (b))
56 #define UCHAR_LIM (UCHAR_MAX + 1)
57 #define UCHAR(c) ((unsigned char) (c))
59 #ifndef DEFAULT_TMPDIR
60 #define DEFAULT_TMPDIR "/tmp"
63 /* Use this as exit status in case of error, not EXIT_FAILURE. This
64 is necessary because EXIT_FAILURE is usually 1 and POSIX requires
65 that sort exit with status 1 IFF invoked with -c and the input is
66 not properly sorted. Any other irregular exit must exit with a
67 status code greater than 1. */
68 #define SORT_FAILURE 2
70 /* The kind of blanks for '-b' to skip in various options. */
71 enum blanktype
{ bl_start
, bl_end
, bl_both
};
73 /* The character marking end of line. Default to \n. */
76 /* Lines are held in core as counted strings. */
79 char *text
; /* Text of the line. */
80 int length
; /* Length not including final newline. */
81 char *keybeg
; /* Start of first key. */
82 char *keylim
; /* Limit of first key. */
85 /* Arrays of lines. */
88 struct line
*lines
; /* Dynamically allocated array of lines. */
89 int used
; /* Number of slots used. */
90 int alloc
; /* Number of slots allocated. */
91 int limit
; /* Max number of slots to allocate. */
97 char *buf
; /* Dynamically allocated buffer. */
98 int used
; /* Number of bytes used. */
99 int alloc
; /* Number of bytes allocated. */
100 int left
; /* Number of bytes left after line parsing. */
105 int sword
; /* Zero-origin 'word' to start at. */
106 int schar
; /* Additional characters to skip. */
107 int skipsblanks
; /* Skip leading white space at start. */
108 int eword
; /* Zero-origin first word after field. */
109 int echar
; /* Additional characters in field. */
110 int skipeblanks
; /* Skip trailing white space at finish. */
111 int *ignore
; /* Boolean array of characters to ignore. */
112 char *translate
; /* Translation applied to characters. */
113 int numeric
; /* Flag for numeric comparison. Handle
114 strings of digits with optional decimal
115 point, but no exponential notation. */
116 int general_numeric
; /* Flag for general, numeric comparison.
117 Handle numbers in exponential notation. */
118 int month
; /* Flag for comparison by month name. */
119 int reverse
; /* Reverse the sense of comparison. */
120 struct keyfield
*next
; /* Next keyfield to try. */
129 /* The name this program was run with. */
132 /* Table of white space. */
133 static int blanks
[UCHAR_LIM
];
135 /* Table of non-printing characters. */
136 static int nonprinting
[UCHAR_LIM
];
138 /* Table of non-dictionary characters (not letters, digits, or blanks). */
139 static int nondictionary
[UCHAR_LIM
];
141 /* Translation table folding lower case to upper. */
142 static char fold_toupper
[UCHAR_LIM
];
144 /* Table mapping 3-letter month names to integers.
145 Alphabetic order allows binary search. */
146 static struct month
const monthtab
[] =
162 /* During the merge phase, the number of files to merge at once. */
165 /* Initial buffer size for in core sorting. Will not grow unless a
166 line longer than this is seen. */
167 static int sortalloc
= 512 * 1024;
169 /* Initial buffer size for in core merge buffers. Bear in mind that
170 up to NMERGE * mergealloc bytes may be allocated for merge buffers. */
171 static int mergealloc
= 16 * 1024;
173 /* Guess of average line length. */
174 static int linelength
= 30;
176 /* Maximum number of elements for the array(s) of struct line's, in bytes. */
177 #define LINEALLOC (256 * 1024)
179 /* Prefix for temporary file names. */
180 static char *temp_file_prefix
;
182 /* Flag to reverse the order of all comparisons. */
185 /* Flag for stable sort. This turns off the last ditch bytewise
186 comparison of lines, and instead leaves lines in the same order
187 they were read if all keys compare equal. */
190 /* Tab character separating fields. If NUL, then fields are separated
191 by the empty string between a non-whitespace character and a whitespace
195 /* Flag to remove consecutive duplicate lines from the output.
196 Only the last of a sequence of equal lines will be output. */
199 /* Nonzero if any of the input files are the standard input. */
200 static int have_read_stdin
;
202 /* Lists of key field comparisons to be tried. */
203 static struct keyfield keyhead
;
209 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
214 Usage: %s [OPTION]... [FILE]...\n\
218 Write sorted concatenation of all FILE(s) to standard output.\n\
220 +POS1 [-POS2] start a key at POS1, end it before POS2\n\
221 -b ignore leading blanks in sort fields or keys\n\
222 -c check if given files already sorted, do not sort\n\
223 -d consider only [a-zA-Z0-9 ] characters in keys\n\
224 -f fold lower case to upper case characters in keys\n\
225 -g compare according to general numerical value, imply -b\n\
226 -i consider only [\\040-\\0176] characters in keys\n\
227 -k POS1[,POS2] same as +POS1 [-POS2], but all positions counted from 1\n\
228 -m merge already sorted files, do not sort\n\
229 -M compare (unknown) < `JAN' < ... < `DEC', imply -b\n\
230 -n compare according to string numerical value, imply -b\n\
231 -o FILE write result on FILE instead of standard output\n\
232 -r reverse the result of comparisons\n\
233 -s stabilize sort by disabling last resort comparison\n\
234 -t SEP use SEParator instead of non- to whitespace transition\n\
235 -T DIRECT use DIRECT for temporary files, not $TMPDIR or %s\n\
236 -u with -c, check for strict ordering;\n\
237 with -m, only output the first of an equal sequence\n\
238 -z end lines with 0 byte, not newline, for find -print0\n\
239 --help display this help and exit\n\
240 --version output version information and exit\n\
242 POS is F[.C][OPTS], where F is the field number and C the character\n\
243 position in the field, both counted from zero. OPTS is made up of one\n\
244 or more of Mbdfinr, this effectively disable global -Mbdfinr settings\n\
245 for that key. If no key given, use the entire line as key. With no\n\
246 FILE, or when FILE is -, read standard input.\n\
249 puts (_("\nReport bugs to <textutils-bugs@gnu.ai.mit.edu>."));
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
)
461 if (!ISALNUM (i
) && !ISBLANK (i
))
462 nondictionary
[i
] = 1;
464 fold_toupper
[i
] = toupper (i
);
470 /* Initialize BUF, allocating ALLOC bytes initially. */
473 initbuf (struct buffer
*buf
, int alloc
)
476 buf
->buf
= xmalloc (buf
->alloc
);
477 buf
->used
= buf
->left
= 0;
480 /* Fill BUF reading from FP, moving buf->left bytes from the end
481 of buf->buf to the beginning first. If EOF is reached and the
482 file wasn't terminated by a newline, supply one. Return a count
483 of bytes buffered. */
486 fillbuf (struct buffer
*buf
, FILE *fp
)
490 memmove (buf
->buf
, buf
->buf
+ buf
->used
- buf
->left
, buf
->left
);
491 buf
->used
= buf
->left
;
493 while (!feof (fp
) && (buf
->used
== 0 || !memchr (buf
->buf
, eolchar
, buf
->used
)))
495 if (buf
->used
== buf
->alloc
)
498 buf
->buf
= xrealloc (buf
->buf
, buf
->alloc
);
500 cc
= fread (buf
->buf
+ buf
->used
, 1, buf
->alloc
- buf
->used
, fp
);
503 error (0, errno
, _("read error"));
510 if (feof (fp
) && buf
->used
&& buf
->buf
[buf
->used
- 1] != eolchar
)
512 if (buf
->used
== buf
->alloc
)
515 buf
->buf
= xrealloc (buf
->buf
, buf
->alloc
);
517 buf
->buf
[buf
->used
++] = eolchar
;
523 /* Initialize LINES, allocating space for ALLOC lines initially.
524 LIMIT is the maximum possible number of lines to allocate space
528 initlines (struct lines
*lines
, int alloc
, int limit
)
530 lines
->alloc
= alloc
;
531 lines
->lines
= (struct line
*) xmalloc (lines
->alloc
* sizeof (struct line
));
533 lines
->limit
= limit
;
536 /* Return a pointer to the first character of the field specified
540 begfield (const struct line
*line
, const struct keyfield
*key
)
542 register char *ptr
= line
->text
, *lim
= ptr
+ line
->length
;
543 register int sword
= key
->sword
, schar
= key
->schar
;
546 while (ptr
< lim
&& sword
--)
548 while (ptr
< lim
&& *ptr
!= tab
)
554 while (ptr
< lim
&& sword
--)
556 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
558 while (ptr
< lim
&& !blanks
[UCHAR (*ptr
)])
562 if (key
->skipsblanks
)
563 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
566 if (ptr
+ schar
<= lim
)
574 /* Return the limit of (a pointer to the first character after) the field
575 in LINE specified by KEY. */
578 limfield (const struct line
*line
, const struct keyfield
*key
)
580 register char *ptr
= line
->text
, *lim
= ptr
+ line
->length
;
581 register int eword
= key
->eword
, echar
= key
->echar
;
583 /* Note: from the POSIX spec:
584 The leading field separator itself is included in
585 a field when -t is not used. FIXME: move this comment up... */
587 /* Move PTR past EWORD fields or to one past the last byte on LINE,
588 whichever comes first. If there are more than EWORD fields, leave
589 PTR pointing at the beginning of the field having zero-based index,
590 EWORD. If a delimiter character was specified (via -t), then that
591 `beginning' is the first character following the delimiting TAB.
592 Otherwise, leave PTR pointing at the first `blank' character after
593 the preceding field. */
595 while (ptr
< lim
&& eword
--)
597 while (ptr
< lim
&& *ptr
!= tab
)
599 if (ptr
< lim
&& (eword
|| echar
> 0))
603 while (ptr
< lim
&& eword
--)
605 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
607 while (ptr
< lim
&& !blanks
[UCHAR (*ptr
)])
611 #ifdef POSIX_UNSPECIFIED
612 /* The following block of code makes GNU sort incompatible with
613 standard Unix sort, so it's ifdef'd out for now.
614 The POSIX spec isn't clear on how to interpret this.
615 FIXME: request clarification.
617 From: kwzh@gnu.ai.mit.edu (Karl Heuer)
618 Date: Thu, 30 May 96 12:20:41 -0400
620 [...]I believe I've found another bug in `sort'.
625 $ textutils-1.15/src/sort +0.6 -0.7 </tmp/sort.in
628 $ /bin/sort +0.6 -0.7 </tmp/sort.in
632 Unix sort produced the answer I expected: sort on the single character
633 in column 6. GNU sort produced different results, because it disagrees
634 on the interpretation of the key-end spec "-M.N". Unix sort reads this
635 as "skip M fields, then N characters"; but GNU sort wants it to mean
636 "skip M fields, then either N characters or the rest of the current
637 field, whichever comes first". This extra clause applies only to
638 key-ends, not key-starts.
641 /* Make LIM point to the end of (one byte past) the current field. */
645 newlim
= memchr (ptr
, tab
, lim
- ptr
);
653 while (newlim
< lim
&& blanks
[UCHAR (*newlim
)])
655 while (newlim
< lim
&& !blanks
[UCHAR (*newlim
)])
661 /* If we're skipping leading blanks, don't start counting characters
662 until after skipping past any leading blanks. */
663 if (key
->skipsblanks
)
664 while (ptr
< lim
&& blanks
[UCHAR (*ptr
)])
667 /* Advance PTR by ECHAR (if possible), but no further than LIM. */
668 if (ptr
+ echar
<= lim
)
679 trim_trailing_blanks (const char *a_start
, char **a_end
)
681 while (*a_end
> a_start
&& blanks
[UCHAR (*(*a_end
- 1))])
685 /* Find the lines in BUF, storing pointers and lengths in LINES.
686 Also replace newlines in BUF with NULs. */
689 findlines (struct buffer
*buf
, struct lines
*lines
)
691 register char *beg
= buf
->buf
, *lim
= buf
->buf
+ buf
->used
, *ptr
;
692 struct keyfield
*key
= keyhead
.next
;
696 while (beg
< lim
&& (ptr
= memchr (beg
, eolchar
, lim
- beg
))
697 && lines
->used
< lines
->limit
)
699 /* There are various places in the code that rely on a NUL
700 being at the end of in-core lines; NULs inside the lines
701 will not cause trouble, though. */
704 if (lines
->used
== lines
->alloc
)
707 lines
->lines
= (struct line
*)
708 xrealloc ((char *) lines
->lines
,
709 lines
->alloc
* sizeof (struct line
));
712 lines
->lines
[lines
->used
].text
= beg
;
713 lines
->lines
[lines
->used
].length
= ptr
- beg
;
715 /* Precompute the position of the first key for efficiency. */
719 lines
->lines
[lines
->used
].keylim
=
720 limfield (&lines
->lines
[lines
->used
], key
);
722 lines
->lines
[lines
->used
].keylim
= ptr
;
725 lines
->lines
[lines
->used
].keybeg
=
726 begfield (&lines
->lines
[lines
->used
], key
);
729 if (key
->skipsblanks
)
730 while (blanks
[UCHAR (*beg
)])
732 lines
->lines
[lines
->used
].keybeg
= beg
;
734 if (key
->skipeblanks
)
736 trim_trailing_blanks (lines
->lines
[lines
->used
].keybeg
,
737 &lines
->lines
[lines
->used
].keylim
);
742 lines
->lines
[lines
->used
].keybeg
= 0;
743 lines
->lines
[lines
->used
].keylim
= 0;
750 buf
->left
= lim
- beg
;
753 /* Compare strings A and B containing decimal fractions < 1. Each string
754 should begin with a decimal point followed immediately by the digits
755 of the fraction. Strings not of this form are considered to be zero. */
758 fraccompare (register const char *a
, register const char *b
)
760 register int tmpa
= *a
;
761 register int tmpb
= *b
;
763 if (tmpa
== '.' && tmpb
== '.')
766 tmpa
= *++a
, tmpb
= *++b
;
767 while (tmpa
== tmpb
&& ISDIGIT (tmpa
));
768 if (ISDIGIT (tmpa
) && ISDIGIT (tmpb
))
788 else if (tmpa
== '.')
797 else if (tmpb
== '.')
809 /* Compare strings A and B as numbers without explicitly converting them to
810 machine numbers. Comparatively slow for short strings, but asymptotically
814 numcompare (register const char *a
, register const char *b
)
816 register int tmpa
, tmpb
, loga
, logb
, tmp
;
853 while (tmpa
== tmpb
&& ISDIGIT (tmpa
))
854 tmpa
= *++a
, tmpb
= *++b
;
856 if ((tmpa
== '.' && !ISDIGIT (tmpb
))
857 || (tmpb
== '.' && !ISDIGIT (tmpa
)))
858 return -fraccompare (a
, b
);
861 for (loga
= 1; ISDIGIT (*++a
); ++loga
)
867 for (logb
= 1; ISDIGIT (*++b
); ++logb
)
872 if ((tmp
= logb
- loga
) != 0)
880 else if (tmpb
== '-')
908 while (tmpa
== tmpb
&& ISDIGIT (tmpa
))
909 tmpa
= *++a
, tmpb
= *++b
;
911 if ((tmpa
== '.' && !ISDIGIT (tmpb
))
912 || (tmpb
== '.' && !ISDIGIT (tmpa
)))
913 return fraccompare (a
, b
);
916 for (loga
= 1; ISDIGIT (*++a
); ++loga
)
922 for (logb
= 1; ISDIGIT (*++b
); ++logb
)
927 if ((tmp
= loga
- logb
) != 0)
938 general_numcompare (const char *sa
, const char *sb
)
941 /* FIXME: add option to warn about failed conversions. */
942 /* FIXME: maybe add option to try expensive FP conversion
943 only if A and B can't be compared more cheaply/accurately. */
944 if (xstrtod (sa
, NULL
, &a
))
948 if (xstrtod (sb
, NULL
, &b
))
952 return a
== b
? 0 : a
< b
? -1 : 1;
955 /* Return an integer <= 12 associated with month name S with length LEN,
956 0 if the name in S is not recognized. */
959 getmonth (const char *s
, int len
)
962 register int i
, lo
= 0, hi
= 12;
964 while (len
> 0 && blanks
[UCHAR(*s
)])
970 for (i
= 0; i
< 3; ++i
)
971 month
[i
] = fold_toupper
[UCHAR (s
[i
])];
975 if (strcmp (month
, monthtab
[(lo
+ hi
) / 2].name
) < 0)
979 if (!strcmp (month
, monthtab
[lo
].name
))
980 return monthtab
[lo
].val
;
984 /* Compare two lines A and B trying every key in sequence until there
985 are no more keys or a difference is found. */
988 keycompare (const struct line
*a
, const struct line
*b
)
990 register char *texta
, *textb
, *lima
, *limb
;
991 register unsigned char *translate
;
992 register int *ignore
;
993 struct keyfield
*key
;
994 int diff
= 0, iter
= 0, lena
, lenb
;
996 for (key
= keyhead
.next
; key
; key
= key
->next
, ++iter
)
998 ignore
= key
->ignore
;
999 translate
= (unsigned char *) key
->translate
;
1001 /* Find the beginning and limit of each field. */
1002 if (iter
|| a
->keybeg
== NULL
|| b
->keybeg
== NULL
)
1004 if (key
->eword
>= 0)
1005 lima
= limfield (a
, key
), limb
= limfield (b
, key
);
1007 lima
= a
->text
+ a
->length
, limb
= b
->text
+ b
->length
;
1009 if (key
->sword
>= 0)
1010 texta
= begfield (a
, key
), textb
= begfield (b
, key
);
1013 texta
= a
->text
, textb
= b
->text
;
1014 if (key
->skipsblanks
)
1016 while (texta
< lima
&& blanks
[UCHAR (*texta
)])
1018 while (textb
< limb
&& blanks
[UCHAR (*textb
)])
1025 /* For the first iteration only, the key positions have
1026 been precomputed for us. */
1027 texta
= a
->keybeg
, lima
= a
->keylim
;
1028 textb
= b
->keybeg
, limb
= b
->keylim
;
1031 /* Find the lengths. */
1032 lena
= lima
- texta
, lenb
= limb
- textb
;
1038 if (key
->skipeblanks
)
1040 char *a_end
= texta
+ lena
;
1041 char *b_end
= textb
+ lenb
;
1042 trim_trailing_blanks (texta
, &a_end
);
1043 trim_trailing_blanks (textb
, &b_end
);
1044 lena
= a_end
- texta
;
1045 lenb
= b_end
- textb
;
1048 /* Actually compare the fields. */
1053 char savea
= *lima
, saveb
= *limb
;
1055 *lima
= *limb
= '\0';
1056 diff
= numcompare (texta
, textb
);
1057 *lima
= savea
, *limb
= saveb
;
1060 diff
= numcompare (texta
, textb
);
1063 return key
->reverse
? -diff
: diff
;
1066 else if (key
->general_numeric
)
1070 char savea
= *lima
, saveb
= *limb
;
1072 *lima
= *limb
= '\0';
1073 diff
= general_numcompare (texta
, textb
);
1074 *lima
= savea
, *limb
= saveb
;
1077 diff
= general_numcompare (texta
, textb
);
1080 return key
->reverse
? -diff
: diff
;
1083 else if (key
->month
)
1085 diff
= getmonth (texta
, lena
) - getmonth (textb
, lenb
);
1087 return key
->reverse
? -diff
: diff
;
1090 else if (ignore
&& translate
)
1092 #define CMP_WITH_IGNORE(A, B) \
1095 while (texta < lima && textb < limb) \
1097 while (texta < lima && ignore[UCHAR (*texta)]) \
1099 while (textb < limb && ignore[UCHAR (*textb)]) \
1101 if (texta < lima && textb < limb) \
1112 if (texta == lima && textb < limb && !ignore[UCHAR (*textb)]) \
1114 else if (texta < lima && textb == limb \
1115 && !ignore[UCHAR (*texta)]) \
1121 while (texta < lima && ignore[UCHAR (*texta)]) \
1123 while (textb < limb && ignore[UCHAR (*textb)]) \
1126 if (texta == lima && textb < limb) \
1128 else if (texta < lima && textb == limb) \
1131 /* Relative lengths are meaningless if characters were ignored. \
1132 Handling this case here avoids what might be an invalid length \
1133 comparison below. */ \
1134 if (diff == 0 && texta == lima && textb == limb) \
1139 CMP_WITH_IGNORE (translate
[UCHAR (*texta
)], translate
[UCHAR (*textb
)]);
1141 CMP_WITH_IGNORE (UCHAR (*texta
), UCHAR (*textb
));
1143 while (texta
< lima
&& textb
< limb
)
1145 if (translate
[UCHAR (*texta
++)] != translate
[UCHAR (*textb
++)])
1147 diff
= (translate
[UCHAR (*--texta
)]
1148 - translate
[UCHAR (*--textb
)]);
1153 diff
= memcmp (texta
, textb
, min (lena
, lenb
));
1156 return key
->reverse
? -diff
: diff
;
1157 if ((diff
= lena
- lenb
) != 0)
1158 return key
->reverse
? -diff
: diff
;
1164 /* Compare two lines A and B, returning negative, zero, or positive
1165 depending on whether A compares less than, equal to, or greater than B. */
1168 compare (register const struct line
*a
, register const struct line
*b
)
1170 int diff
, tmpa
, tmpb
, mini
;
1172 /* First try to compare on the specified keys (if any).
1173 The only two cases with no key at all are unadorned sort,
1174 and unadorned sort -r. */
1177 diff
= keycompare (a
, b
);
1180 if (unique
|| stable
)
1184 /* If the keys all compare equal (or no keys were specified)
1185 fall through to the default byte-by-byte comparison. */
1186 tmpa
= a
->length
, tmpb
= b
->length
;
1187 mini
= min (tmpa
, tmpb
);
1192 char *ap
= a
->text
, *bp
= b
->text
;
1194 diff
= UCHAR (*ap
) - UCHAR (*bp
);
1197 diff
= memcmp (ap
, bp
, mini
);
1203 return reverse
? -diff
: diff
;
1206 /* Check that the lines read from the given FP come in order. Return
1207 1 if they do and 0 if there is a disorder.
1208 FIXME: return number of first out-of-order line if not sorted. */
1213 struct buffer buf
; /* Input buffer. */
1214 struct lines lines
; /* Lines scanned from the buffer. */
1215 struct line temp
; /* Copy of previous line. */
1216 int cc
; /* Character count. */
1217 int alloc
, sorted
= 1;
1219 initbuf (&buf
, mergealloc
);
1220 initlines (&lines
, mergealloc
/ linelength
+ 1,
1221 LINEALLOC
/ ((NMERGE
+ NMERGE
) * sizeof (struct line
)));
1223 temp
.text
= xmalloc (alloc
);
1225 cc
= fillbuf (&buf
, fp
);
1229 findlines (&buf
, &lines
);
1233 struct line
*prev_line
; /* Pointer to previous line. */
1234 int cmp
; /* Result of calling compare. */
1237 /* Compare each line in the buffer with its successor. */
1238 for (i
= 0; i
< lines
.used
- 1; ++i
)
1240 cmp
= compare (&lines
.lines
[i
], &lines
.lines
[i
+ 1]);
1241 if ((unique
&& cmp
>= 0) || (cmp
> 0))
1248 /* Save the last line of the buffer and refill the buffer. */
1249 prev_line
= lines
.lines
+ (lines
.used
- 1);
1250 if (prev_line
->length
+ 1 > alloc
)
1256 while (alloc
< prev_line
->length
+ 1);
1257 temp
.text
= xrealloc (temp
.text
, alloc
);
1259 assert (prev_line
->length
+ 1 <= alloc
);
1260 memcpy (temp
.text
, prev_line
->text
, prev_line
->length
+ 1);
1261 temp
.length
= prev_line
->length
;
1262 temp
.keybeg
= temp
.text
+ (prev_line
->keybeg
- prev_line
->text
);
1263 temp
.keylim
= temp
.text
+ (prev_line
->keylim
- prev_line
->text
);
1265 cc
= fillbuf (&buf
, fp
);
1269 findlines (&buf
, &lines
);
1270 /* Make sure the line saved from the old buffer contents is
1271 less than or equal to the first line of the new buffer. */
1272 cmp
= compare (&temp
, &lines
.lines
[0]);
1273 if ((unique
&& cmp
>= 0) || (cmp
> 0))
1283 free ((char *) lines
.lines
);
1288 /* Merge lines from FPS onto OFP. NFPS cannot be greater than NMERGE.
1289 Close FPS before returning. */
1292 mergefps (FILE **fps
, register int nfps
, FILE *ofp
)
1294 struct buffer buffer
[NMERGE
]; /* Input buffers for each file. */
1295 struct lines lines
[NMERGE
]; /* Line tables for each buffer. */
1296 struct line saved
; /* Saved line for unique check. */
1297 int savedflag
= 0; /* True if there is a saved line. */
1298 int savealloc
; /* Size allocated for the saved line. */
1299 int cur
[NMERGE
]; /* Current line in each line table. */
1300 int ord
[NMERGE
]; /* Table representing a permutation of fps,
1301 such that lines[ord[0]].lines[cur[ord[0]]]
1302 is the smallest line and will be next
1304 register int i
, j
, t
;
1306 #ifdef lint /* Suppress `used before initialized' warning. */
1310 /* Allocate space for a saved line if necessary. */
1313 savealloc
= linelength
;
1314 saved
.text
= xmalloc (savealloc
);
1317 /* Read initial lines from each input file. */
1318 for (i
= 0; i
< nfps
; ++i
)
1320 initbuf (&buffer
[i
], mergealloc
);
1321 /* If a file is empty, eliminate it from future consideration. */
1322 while (i
< nfps
&& !fillbuf (&buffer
[i
], fps
[i
]))
1326 for (j
= i
; j
< nfps
; ++j
)
1327 fps
[j
] = fps
[j
+ 1];
1330 free (buffer
[i
].buf
);
1333 initlines (&lines
[i
], mergealloc
/ linelength
+ 1,
1334 LINEALLOC
/ ((NMERGE
+ NMERGE
) * sizeof (struct line
)));
1335 findlines (&buffer
[i
], &lines
[i
]);
1340 /* Set up the ord table according to comparisons among input lines.
1341 Since this only reorders two items if one is strictly greater than
1342 the other, it is stable. */
1343 for (i
= 0; i
< nfps
; ++i
)
1345 for (i
= 1; i
< nfps
; ++i
)
1346 if (compare (&lines
[ord
[i
- 1]].lines
[cur
[ord
[i
- 1]]],
1347 &lines
[ord
[i
]].lines
[cur
[ord
[i
]]]) > 0)
1348 t
= ord
[i
- 1], ord
[i
- 1] = ord
[i
], ord
[i
] = t
, i
= 0;
1350 /* Repeatedly output the smallest line until no input remains. */
1353 /* If uniqified output is turned on, output only the first of
1354 an identical series of lines. */
1357 if (savedflag
&& compare (&saved
, &lines
[ord
[0]].lines
[cur
[ord
[0]]]))
1359 write_bytes (saved
.text
, saved
.length
, ofp
);
1360 putc (eolchar
, ofp
);
1365 if (savealloc
< lines
[ord
[0]].lines
[cur
[ord
[0]]].length
+ 1)
1367 while (savealloc
< lines
[ord
[0]].lines
[cur
[ord
[0]]].length
+ 1)
1369 saved
.text
= xrealloc (saved
.text
, savealloc
);
1371 saved
.length
= lines
[ord
[0]].lines
[cur
[ord
[0]]].length
;
1372 memcpy (saved
.text
, lines
[ord
[0]].lines
[cur
[ord
[0]]].text
,
1374 if (lines
[ord
[0]].lines
[cur
[ord
[0]]].keybeg
!= NULL
)
1376 saved
.keybeg
= saved
.text
+
1377 (lines
[ord
[0]].lines
[cur
[ord
[0]]].keybeg
1378 - lines
[ord
[0]].lines
[cur
[ord
[0]]].text
);
1380 if (lines
[ord
[0]].lines
[cur
[ord
[0]]].keylim
!= NULL
)
1382 saved
.keylim
= saved
.text
+
1383 (lines
[ord
[0]].lines
[cur
[ord
[0]]].keylim
1384 - lines
[ord
[0]].lines
[cur
[ord
[0]]].text
);
1391 write_bytes (lines
[ord
[0]].lines
[cur
[ord
[0]]].text
,
1392 lines
[ord
[0]].lines
[cur
[ord
[0]]].length
, ofp
);
1393 putc (eolchar
, ofp
);
1396 /* Check if we need to read more lines into core. */
1397 if (++cur
[ord
[0]] == lines
[ord
[0]].used
)
1398 if (fillbuf (&buffer
[ord
[0]], fps
[ord
[0]]))
1400 findlines (&buffer
[ord
[0]], &lines
[ord
[0]]);
1405 /* We reached EOF on fps[ord[0]]. */
1406 for (i
= 1; i
< nfps
; ++i
)
1407 if (ord
[i
] > ord
[0])
1410 xfclose (fps
[ord
[0]]);
1411 free (buffer
[ord
[0]].buf
);
1412 free ((char *) lines
[ord
[0]].lines
);
1413 for (i
= ord
[0]; i
< nfps
; ++i
)
1415 fps
[i
] = fps
[i
+ 1];
1416 buffer
[i
] = buffer
[i
+ 1];
1417 lines
[i
] = lines
[i
+ 1];
1418 cur
[i
] = cur
[i
+ 1];
1420 for (i
= 0; i
< nfps
; ++i
)
1421 ord
[i
] = ord
[i
+ 1];
1425 /* The new line just read in may be larger than other lines
1426 already in core; push it back in the queue until we encounter
1427 a line larger than it. */
1428 for (i
= 1; i
< nfps
; ++i
)
1430 t
= compare (&lines
[ord
[0]].lines
[cur
[ord
[0]]],
1431 &lines
[ord
[i
]].lines
[cur
[ord
[i
]]]);
1433 t
= ord
[0] - ord
[i
];
1438 for (j
= 1; j
< i
; ++j
)
1439 ord
[j
- 1] = ord
[j
];
1443 if (unique
&& savedflag
)
1445 write_bytes (saved
.text
, saved
.length
, ofp
);
1446 putc (eolchar
, ofp
);
1451 /* Sort the array LINES with NLINES members, using TEMP for temporary space. */
1454 sortlines (struct line
*lines
, int nlines
, struct line
*temp
)
1456 register struct line
*lo
, *hi
, *t
;
1457 register int nlo
, nhi
;
1461 if (compare (&lines
[0], &lines
[1]) > 0)
1462 *temp
= lines
[0], lines
[0] = lines
[1], lines
[1] = *temp
;
1472 sortlines (lo
, nlo
, temp
);
1475 sortlines (hi
, nhi
, temp
);
1480 if (compare (lo
, hi
) <= 0)
1481 *t
++ = *lo
++, --nlo
;
1483 *t
++ = *hi
++, --nhi
;
1487 for (lo
= lines
, nlo
= nlines
- nhi
, t
= temp
; nlo
; --nlo
)
1491 /* Check that each of the NFILES FILES is ordered.
1492 Return a count of disordered files. */
1495 check (char **files
, int nfiles
)
1497 int i
, disorders
= 0;
1500 for (i
= 0; i
< nfiles
; ++i
)
1502 fp
= xfopen (files
[i
], "r");
1505 fprintf (stderr
, _("%s: disorder on %s\n"), program_name
, files
[i
]);
1512 /* Merge NFILES FILES onto OFP. */
1515 merge (char **files
, int nfiles
, FILE *ofp
)
1519 FILE *fps
[NMERGE
], *tfp
;
1521 while (nfiles
> NMERGE
)
1524 for (i
= 0; i
< nfiles
/ NMERGE
; ++i
)
1526 for (j
= 0; j
< NMERGE
; ++j
)
1527 fps
[j
] = xfopen (files
[i
* NMERGE
+ j
], "r");
1528 tfp
= xtmpfopen (temp
= tempname ());
1529 mergefps (fps
, NMERGE
, tfp
);
1531 for (j
= 0; j
< NMERGE
; ++j
)
1532 zaptemp (files
[i
* NMERGE
+ j
]);
1535 for (j
= 0; j
< nfiles
% NMERGE
; ++j
)
1536 fps
[j
] = xfopen (files
[i
* NMERGE
+ j
], "r");
1537 tfp
= xtmpfopen (temp
= tempname ());
1538 mergefps (fps
, nfiles
% NMERGE
, tfp
);
1540 for (j
= 0; j
< nfiles
% NMERGE
; ++j
)
1541 zaptemp (files
[i
* NMERGE
+ j
]);
1546 for (i
= 0; i
< nfiles
; ++i
)
1547 fps
[i
] = xfopen (files
[i
], "r");
1548 mergefps (fps
, i
, ofp
);
1549 for (i
= 0; i
< nfiles
; ++i
)
1553 /* Sort NFILES FILES onto OFP. */
1556 sort (char **files
, int nfiles
, FILE *ofp
)
1563 struct tempnode
*node
;
1564 int n_temp_files
= 0;
1567 initbuf (&buf
, sortalloc
);
1568 initlines (&lines
, sortalloc
/ linelength
+ 1,
1569 LINEALLOC
/ sizeof (struct line
));
1571 tmp
= (struct line
*) xmalloc (ntmp
* sizeof (struct line
));
1575 fp
= xfopen (*files
++, "r");
1576 while (fillbuf (&buf
, fp
))
1578 findlines (&buf
, &lines
);
1579 if (lines
.used
> ntmp
)
1581 while (lines
.used
> ntmp
)
1583 tmp
= (struct line
*)
1584 xrealloc ((char *) tmp
, ntmp
* sizeof (struct line
));
1586 sortlines (lines
.lines
, lines
.used
, tmp
);
1587 if (feof (fp
) && !nfiles
&& !n_temp_files
&& !buf
.left
)
1592 tfp
= xtmpfopen (tempname ());
1594 for (i
= 0; i
< lines
.used
; ++i
)
1595 if (!unique
|| i
== 0
1596 || compare (&lines
.lines
[i
], &lines
.lines
[i
- 1]))
1598 write_bytes (lines
.lines
[i
].text
, lines
.lines
[i
].length
, tfp
);
1599 putc (eolchar
, tfp
);
1608 free ((char *) lines
.lines
);
1609 free ((char *) tmp
);
1613 tempfiles
= (char **) xmalloc (n_temp_files
* sizeof (char *));
1615 for (node
= temphead
.next
; i
> 0; node
= node
->next
)
1616 tempfiles
[--i
] = node
->name
;
1617 merge (tempfiles
, n_temp_files
, ofp
);
1618 free ((char *) tempfiles
);
1622 /* Insert key KEY at the end of the list (`keyhead'). */
1625 insertkey (struct keyfield
*key
)
1627 struct keyfield
*k
= &keyhead
;
1636 badfieldspec (const char *s
)
1638 error (SORT_FAILURE
, 0, _("invalid field specification `%s'"), s
);
1641 /* Handle interrupts and hangups. */
1644 sighandler (int sig
)
1647 struct sigaction sigact
;
1649 sigact
.sa_handler
= SIG_DFL
;
1650 sigemptyset (&sigact
.sa_mask
);
1651 sigact
.sa_flags
= 0;
1652 sigaction (sig
, &sigact
, NULL
);
1653 #else /* !SA_INTERRUPT */
1654 signal (sig
, SIG_DFL
);
1655 #endif /* SA_INTERRUPT */
1657 kill (getpid (), sig
);
1660 /* Set the ordering options for KEY specified in S.
1661 Return the address of the first character in S that
1662 is not a valid ordering option.
1663 BLANKTYPE is the kind of blanks that 'b' should skip. */
1666 set_ordering (register const char *s
, struct keyfield
*key
,
1667 enum blanktype blanktype
)
1674 if (blanktype
== bl_start
|| blanktype
== bl_both
)
1675 key
->skipsblanks
= 1;
1676 if (blanktype
== bl_end
|| blanktype
== bl_both
)
1677 key
->skipeblanks
= 1;
1680 key
->ignore
= nondictionary
;
1683 key
->translate
= fold_toupper
;
1686 key
->general_numeric
= 1;
1689 key
->ignore
= nonprinting
;
1709 key_init (struct keyfield
*key
)
1711 memset (key
, 0, sizeof (*key
));
1716 main (int argc
, char **argv
)
1718 struct keyfield
*key
= NULL
, gkey
;
1721 int checkonly
= 0, mergeonly
= 0, nfiles
= 0;
1722 char *minus
= "-", *outfile
= minus
, **files
, *tmp
;
1725 struct sigaction oldact
, newact
;
1726 #endif /* SA_INTERRUPT */
1728 program_name
= argv
[0];
1729 setlocale (LC_ALL
, "");
1730 bindtextdomain (PACKAGE
, LOCALEDIR
);
1731 textdomain (PACKAGE
);
1733 parse_long_options (argc
, argv
, "sort", GNU_PACKAGE
, VERSION
, usage
);
1735 have_read_stdin
= 0;
1738 temp_file_prefix
= getenv ("TMPDIR");
1739 if (temp_file_prefix
== NULL
)
1740 temp_file_prefix
= DEFAULT_TMPDIR
;
1743 newact
.sa_handler
= sighandler
;
1744 sigemptyset (&newact
.sa_mask
);
1745 newact
.sa_flags
= 0;
1747 sigaction (SIGINT
, NULL
, &oldact
);
1748 if (oldact
.sa_handler
!= SIG_IGN
)
1749 sigaction (SIGINT
, &newact
, NULL
);
1750 sigaction (SIGHUP
, NULL
, &oldact
);
1751 if (oldact
.sa_handler
!= SIG_IGN
)
1752 sigaction (SIGHUP
, &newact
, NULL
);
1753 sigaction (SIGPIPE
, NULL
, &oldact
);
1754 if (oldact
.sa_handler
!= SIG_IGN
)
1755 sigaction (SIGPIPE
, &newact
, NULL
);
1756 sigaction (SIGTERM
, NULL
, &oldact
);
1757 if (oldact
.sa_handler
!= SIG_IGN
)
1758 sigaction (SIGTERM
, &newact
, NULL
);
1759 #else /* !SA_INTERRUPT */
1760 if (signal (SIGINT
, SIG_IGN
) != SIG_IGN
)
1761 signal (SIGINT
, sighandler
);
1762 if (signal (SIGHUP
, SIG_IGN
) != SIG_IGN
)
1763 signal (SIGHUP
, sighandler
);
1764 if (signal (SIGPIPE
, SIG_IGN
) != SIG_IGN
)
1765 signal (SIGPIPE
, sighandler
);
1766 if (signal (SIGTERM
, SIG_IGN
) != SIG_IGN
)
1767 signal (SIGTERM
, sighandler
);
1768 #endif /* !SA_INTERRUPT */
1770 gkey
.sword
= gkey
.eword
= -1;
1772 gkey
.translate
= NULL
;
1773 gkey
.numeric
= gkey
.general_numeric
= gkey
.month
= gkey
.reverse
= 0;
1774 gkey
.skipsblanks
= gkey
.skipeblanks
= 0;
1776 files
= (char **) xmalloc (sizeof (char *) * argc
);
1778 for (i
= 1; i
< argc
; ++i
)
1780 if (argv
[i
][0] == '+')
1784 key
= (struct keyfield
*) xmalloc (sizeof (struct keyfield
));
1787 if (! (ISDIGIT (*s
) || (*s
== '.' && ISDIGIT (s
[1]))))
1788 badfieldspec (argv
[i
]);
1789 for (t
= 0; ISDIGIT (*s
); ++s
)
1790 t
= 10 * t
+ *s
- '0';
1793 for (++s
; ISDIGIT (*s
); ++s
)
1794 t2
= 10 * t2
+ *s
- '0';
1802 s
= set_ordering (s
, key
, bl_start
);
1804 badfieldspec (argv
[i
]);
1806 else if (argv
[i
][0] == '-' && argv
[i
][1])
1809 if (ISDIGIT (*s
) || (*s
== '.' && ISDIGIT (s
[1])))
1813 /* Provoke with `sort -9'. */
1814 error (0, 0, _("when using the old-style +POS and -POS \
1815 key specifiers,\nthe +POS specifier must come first"));
1816 usage (SORT_FAILURE
);
1818 for (t
= 0; ISDIGIT (*s
); ++s
)
1819 t
= t
* 10 + *s
- '0';
1822 for (++s
; ISDIGIT (*s
); ++s
)
1823 t2
= t2
* 10 + *s
- '0';
1826 s
= set_ordering (s
, key
, bl_end
);
1828 badfieldspec (argv
[i
]);
1835 s
= set_ordering (s
, &gkey
, bl_both
);
1849 error (SORT_FAILURE
, 0,
1850 _("option `-k' requires an argument"));
1856 key
= (struct keyfield
*)
1857 xmalloc (sizeof (struct keyfield
));
1861 badfieldspec (argv
[i
]);
1862 for (t
= 0; ISDIGIT (*s
); ++s
)
1863 t
= 10 * t
+ *s
- '0';
1866 /* Provoke with `sort -k0' */
1867 error (0, 0, _("the starting field number argument \
1868 to the `-k' option must be positive"));
1869 badfieldspec (argv
[i
]);
1875 if (!ISDIGIT (s
[1]))
1877 /* Provoke with `sort -k1.' */
1878 error (0, 0, _("starting field spec has `.' but \
1879 lacks following character offset"));
1880 badfieldspec (argv
[i
]);
1882 for (++s
; ISDIGIT (*s
); ++s
)
1883 t2
= 10 * t2
+ *s
- '0';
1886 /* Provoke with `sort -k1.0' */
1887 error (0, 0, _("starting field character offset \
1888 argument to the `-k' option\nmust be positive"));
1889 badfieldspec (argv
[i
]);
1900 s
= set_ordering (s
, key
, bl_start
);
1907 badfieldspec (argv
[i
]);
1910 /* Skip over comma. */
1914 /* Provoke with `sort -k1,' */
1915 error (0, 0, _("field specification has `,' but \
1916 lacks following field spec"));
1917 badfieldspec (argv
[i
]);
1920 for (t
= 0; ISDIGIT (*s
); ++s
)
1921 t
= t
* 10 + *s
- '0';
1924 /* Provoke with `sort -k1,0' */
1925 error (0, 0, _("ending field number argument \
1926 to the `-k' option must be positive"));
1927 badfieldspec (argv
[i
]);
1933 if (!ISDIGIT (s
[1]))
1935 /* Provoke with `sort -k1,1.' */
1936 error (0, 0, _("ending field spec has `.' \
1937 but lacks following character offset"));
1938 badfieldspec (argv
[i
]);
1940 for (++s
; ISDIGIT (*s
); ++s
)
1941 t2
= t2
* 10 + *s
- '0';
1945 /* `-k 2,3' is equivalent to `+1 -3'. */
1950 s
= set_ordering (s
, key
, bl_end
);
1952 badfieldspec (argv
[i
]);
1966 error (SORT_FAILURE
, 0,
1967 _("option `-o' requires an argument"));
1969 outfile
= argv
[++i
];
1978 else if (i
< argc
- 1)
1984 error (SORT_FAILURE
, 0,
1985 _("option `-t' requires an argument"));
1989 temp_file_prefix
= ++s
;
1993 temp_file_prefix
= argv
[++i
];
1995 error (SORT_FAILURE
, 0,
1996 _("option `-T' requires an argument"));
2007 /* Accept and ignore e.g. -y0 for compatibility with
2011 fprintf (stderr
, _("%s: unrecognized option `-%c'\n"),
2013 usage (SORT_FAILURE
);
2019 else /* Not an option. */
2021 files
[nfiles
++] = argv
[i
];
2029 /* Inheritance of global options to individual keys. */
2030 for (key
= keyhead
.next
; key
; key
= key
->next
)
2031 if (!key
->ignore
&& !key
->translate
&& !key
->skipsblanks
&& !key
->reverse
2032 && !key
->skipeblanks
&& !key
->month
&& !key
->numeric
2033 && !key
->general_numeric
)
2035 key
->ignore
= gkey
.ignore
;
2036 key
->translate
= gkey
.translate
;
2037 key
->skipsblanks
= gkey
.skipsblanks
;
2038 key
->skipeblanks
= gkey
.skipeblanks
;
2039 key
->month
= gkey
.month
;
2040 key
->numeric
= gkey
.numeric
;
2041 key
->general_numeric
= gkey
.general_numeric
;
2042 key
->reverse
= gkey
.reverse
;
2045 if (!keyhead
.next
&& (gkey
.ignore
|| gkey
.translate
|| gkey
.skipsblanks
2046 || gkey
.skipeblanks
|| gkey
.month
|| gkey
.numeric
2047 || gkey
.general_numeric
))
2049 reverse
= gkey
.reverse
;
2059 /* POSIX requires that sort return 1 IFF invoked with -c and the
2060 input is not properly sorted. */
2061 exit (check (files
, nfiles
) == 0 ? 0 : 1);
2064 if (strcmp (outfile
, "-"))
2066 struct stat outstat
;
2067 if (stat (outfile
, &outstat
) == 0)
2069 /* The following code prevents a race condition when
2070 people use the brain dead shell programming idiom:
2071 cat file | sort -o file
2072 This feature is provided for historical compatibility,
2073 but we strongly discourage ever relying on this in
2074 new shell programs. */
2076 /* Temporarily copy each input file that might be another name
2077 for the output file. When in doubt (e.g. a pipe), copy. */
2078 for (i
= 0; i
< nfiles
; ++i
)
2084 if (S_ISREG (outstat
.st_mode
) && strcmp (outfile
, files
[i
]))
2087 if ((strcmp (files
[i
], "-")
2088 ? stat (files
[i
], &instat
)
2089 : fstat (STDIN_FILENO
, &instat
)) != 0)
2091 error (0, errno
, "%s", files
[i
]);
2093 exit (SORT_FAILURE
);
2095 if (S_ISREG (instat
.st_mode
)
2096 && (instat
.st_ino
!= outstat
.st_ino
2097 || instat
.st_dev
!= outstat
.st_dev
))
2099 /* We know the files are distinct. */
2104 fp
= xfopen (files
[i
], "r");
2106 ofp
= xtmpfopen (tmp
);
2107 while ((cc
= fread (buf
, 1, sizeof buf
, fp
)) > 0)
2108 write_bytes (buf
, cc
, ofp
);
2111 error (0, errno
, "%s", files
[i
]);
2113 exit (SORT_FAILURE
);
2120 ofp
= xfopen (outfile
, "w");
2126 merge (files
, nfiles
, ofp
);
2128 sort (files
, nfiles
, ofp
);
2131 /* If we wait for the implicit flush on exit, and the parent process
2132 has closed stdout (e.g., exec >&- in a shell), then the output file
2133 winds up empty. I don't understand why. This is under SunOS,
2134 Solaris, Ultrix, and Irix. This premature fflush makes the output
2135 reappear. --karl@cs.umb.edu */
2136 if (fflush (ofp
) < 0)
2137 error (SORT_FAILURE
, errno
, _("%s: write error"), outfile
);
2139 if (have_read_stdin
&& fclose (stdin
) == EOF
)
2140 error (SORT_FAILURE
, errno
, outfile
);
2141 if (ferror (stdout
) || fclose (stdout
) == EOF
)
2142 error (SORT_FAILURE
, errno
, _("%s: write error"), outfile
);
2144 exit (EXIT_SUCCESS
);