OpenCoverage

sort.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/sort.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* sort - sort lines of text (with all kinds of options).-
2 Copyright (C) 1988-2018 Free Software Foundation, Inc.-
3-
4 This program is free software: you can redistribute it and/or modify-
5 it under the terms of the GNU General Public License as published by-
6 the Free Software Foundation, either version 3 of the License, or-
7 (at your option) any later version.-
8-
9 This program is distributed in the hope that it will be useful,-
10 but WITHOUT ANY WARRANTY; without even the implied warranty of-
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
12 GNU General Public License for more details.-
13-
14 You should have received a copy of the GNU General Public License-
15 along with this program. If not, see <https://www.gnu.org/licenses/>.-
16-
17 Written December 1988 by Mike Haertel.-
18 The author may be reached (Email) at the address mike@gnu.ai.mit.edu,-
19 or (US mail) as Mike Haertel c/o Free Software Foundation.-
20-
21 Ørn E. Hansen added NLS support in 1997. */-
22-
23#include <config.h>-
24-
25#include <getopt.h>-
26#include <pthread.h>-
27#include <sys/resource.h>-
28#include <sys/types.h>-
29#include <sys/wait.h>-
30#include <signal.h>-
31#include <assert.h>-
32#include "system.h"-
33#include "argmatch.h"-
34#include "die.h"-
35#include "error.h"-
36#include "fadvise.h"-
37#include "filevercmp.h"-
38#include "flexmember.h"-
39#include "hard-locale.h"-
40#include "hash.h"-
41#include "heap.h"-
42#include "ignore-value.h"-
43#include "md5.h"-
44#include "mbswidth.h"-
45#include "nproc.h"-
46#include "physmem.h"-
47#include "posixver.h"-
48#include "quote.h"-
49#include "randread.h"-
50#include "readtokens0.h"-
51#include "stdlib--.h"-
52#include "strnumcmp.h"-
53#include "xmemcoll.h"-
54#include "xnanosleep.h"-
55#include "xstrtol.h"-
56-
57#ifndef RLIMIT_DATA-
58struct rlimit { size_t rlim_cur; };-
59# define getrlimit(Resource, Rlp) (-1)-
60#endif-
61-
62/* The official name of this program (e.g., no 'g' prefix). */-
63#define PROGRAM_NAME "sort"-
64-
65#define AUTHORS \-
66 proper_name ("Mike Haertel"), \-
67 proper_name ("Paul Eggert")-
68-
69#if HAVE_LANGINFO_CODESET-
70# include <langinfo.h>-
71#endif-
72-
73/* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is-
74 present. */-
75#ifndef SA_NOCLDSTOP-
76# define SA_NOCLDSTOP 0-
77/* No sigprocmask. Always 'return' zero. */-
78# define sigprocmask(How, Set, Oset) (0)-
79# define sigset_t int-
80# if ! HAVE_SIGINTERRUPT-
81# define siginterrupt(sig, flag) /* empty */-
82# endif-
83#endif-
84-
85#if GNULIB_defined_pthread_functions-
86# undef pthread_sigmask-
87# define pthread_sigmask(how, set, oset) sigprocmask (how, set, oset)-
88#endif-
89-
90#if !defined OPEN_MAX && defined NR_OPEN-
91# define OPEN_MAX NR_OPEN-
92#endif-
93#if !defined OPEN_MAX-
94# define OPEN_MAX 20-
95#endif-
96-
97#define UCHAR_LIM (UCHAR_MAX + 1)-
98-
99#if HAVE_C99_STRTOLD-
100# define long_double long double-
101#else-
102# define long_double double-
103# undef strtold-
104# define strtold strtod-
105#endif-
106-
107#ifndef DEFAULT_TMPDIR-
108# define DEFAULT_TMPDIR "/tmp"-
109#endif-
110-
111/* Maximum number of lines to merge every time a NODE is taken from-
112 the merge queue. Node is at LEVEL in the binary merge tree,-
113 and is responsible for merging TOTAL lines. */-
114#define MAX_MERGE(total, level) (((total) >> (2 * ((level) + 1))) + 1)-
115-
116/* Heuristic value for the number of lines for which it is worth creating-
117 a subthread, during an internal merge sort. I.e., it is a small number-
118 of "average" lines for which sorting via two threads is faster than-
119 sorting via one on an "average" system. On a dual-core 2.0 GHz i686-
120 system with 3GB of RAM and 2MB of L2 cache, a file containing 128K-
121 lines of gensort -a output is sorted slightly faster with --parallel=2-
122 than with --parallel=1. By contrast, using --parallel=1 is about 10%-
123 faster than using --parallel=2 with a 64K-line input. */-
124enum { SUBTHREAD_LINES_HEURISTIC = 128 * 1024 };-
125verify (4 <= SUBTHREAD_LINES_HEURISTIC);-
126-
127/* The number of threads after which there are-
128 diminishing performance gains. */-
129enum { DEFAULT_MAX_THREADS = 8 };-
130-
131/* Exit statuses. */-
132enum-
133 {-
134 /* POSIX says to exit with status 1 if invoked with -c and the-
135 input is not properly sorted. */-
136 SORT_OUT_OF_ORDER = 1,-
137-
138 /* POSIX says any other irregular exit must exit with a status-
139 code greater than 1. */-
140 SORT_FAILURE = 2-
141 };-
142-
143enum-
144 {-
145 /* The number of times we should try to fork a compression process-
146 (we retry if the fork call fails). We don't _need_ to compress-
147 temp files, this is just to reduce disk access, so this number-
148 can be small. Each retry doubles in duration. */-
149 MAX_FORK_TRIES_COMPRESS = 4,-
150-
151 /* The number of times we should try to fork a decompression process.-
152 If we can't fork a decompression process, we can't sort, so this-
153 number should be big. Each retry doubles in duration. */-
154 MAX_FORK_TRIES_DECOMPRESS = 9-
155 };-
156-
157enum-
158 {-
159 /* Level of the end-of-merge node, one level above the root. */-
160 MERGE_END = 0,-
161-
162 /* Level of the root node in merge tree. */-
163 MERGE_ROOT = 1-
164 };-
165-
166/* The representation of the decimal point in the current locale. */-
167static int decimal_point;-
168-
169/* Thousands separator; if -1, then there isn't one. */-
170static int thousands_sep;-
171-
172/* Nonzero if the corresponding locales are hard. */-
173static bool hard_LC_COLLATE;-
174#if HAVE_NL_LANGINFO-
175static bool hard_LC_TIME;-
176#endif-
177-
178#define NONZERO(x) ((x) != 0)-
179-
180/* The kind of blanks for '-b' to skip in various options. */-
181enum blanktype { bl_start, bl_end, bl_both };-
182-
183/* The character marking end of line. Default to \n. */-
184static char eolchar = '\n';-
185-
186/* Lines are held in core as counted strings. */-
187struct line-
188{-
189 char *text; /* Text of the line. */-
190 size_t length; /* Length including final newline. */-
191 char *keybeg; /* Start of first key. */-
192 char *keylim; /* Limit of first key. */-
193};-
194-
195/* Input buffers. */-
196struct buffer-
197{-
198 char *buf; /* Dynamically allocated buffer,-
199 partitioned into 3 regions:-
200 - input data;-
201 - unused area;-
202 - an array of lines, in reverse order. */-
203 size_t used; /* Number of bytes used for input data. */-
204 size_t nlines; /* Number of lines in the line array. */-
205 size_t alloc; /* Number of bytes allocated. */-
206 size_t left; /* Number of bytes left from previous reads. */-
207 size_t line_bytes; /* Number of bytes to reserve for each line. */-
208 bool eof; /* An EOF has been read. */-
209};-
210-
211/* Sort key. */-
212struct keyfield-
213{-
214 size_t sword; /* Zero-origin 'word' to start at. */-
215 size_t schar; /* Additional characters to skip. */-
216 size_t eword; /* Zero-origin last 'word' of key. */-
217 size_t echar; /* Additional characters in field. */-
218 bool const *ignore; /* Boolean array of characters to ignore. */-
219 char const *translate; /* Translation applied to characters. */-
220 bool skipsblanks; /* Skip leading blanks when finding start. */-
221 bool skipeblanks; /* Skip leading blanks when finding end. */-
222 bool numeric; /* Flag for numeric comparison. Handle-
223 strings of digits with optional decimal-
224 point, but no exponential notation. */-
225 bool random; /* Sort by random hash of key. */-
226 bool general_numeric; /* Flag for general, numeric comparison.-
227 Handle numbers in exponential notation. */-
228 bool human_numeric; /* Flag for sorting by human readable-
229 units with either SI or IEC prefixes. */-
230 bool month; /* Flag for comparison by month name. */-
231 bool reverse; /* Reverse the sense of comparison. */-
232 bool version; /* sort by version number */-
233 bool traditional_used; /* Traditional key option format is used. */-
234 struct keyfield *next; /* Next keyfield to try. */-
235};-
236-
237struct month-
238{-
239 char const *name;-
240 int val;-
241};-
242-
243/* Binary merge tree node. */-
244struct merge_node-
245{-
246 struct line *lo; /* Lines to merge from LO child node. */-
247 struct line *hi; /* Lines to merge from HI child node. */-
248 struct line *end_lo; /* End of available lines from LO. */-
249 struct line *end_hi; /* End of available lines from HI. */-
250 struct line **dest; /* Pointer to destination of merge. */-
251 size_t nlo; /* Total Lines remaining from LO. */-
252 size_t nhi; /* Total lines remaining from HI. */-
253 struct merge_node *parent; /* Parent node. */-
254 struct merge_node *lo_child; /* LO child node. */-
255 struct merge_node *hi_child; /* HI child node. */-
256 unsigned int level; /* Level in merge tree. */-
257 bool queued; /* Node is already in heap. */-
258 pthread_mutex_t lock; /* Lock for node operations. */-
259};-
260-
261/* Priority queue of merge nodes. */-
262struct merge_node_queue-
263{-
264 struct heap *priority_queue; /* Priority queue of merge tree nodes. */-
265 pthread_mutex_t mutex; /* Lock for queue operations. */-
266 pthread_cond_t cond; /* Conditional wait for empty queue to populate-
267 when popping. */-
268};-
269-
270/* Used to implement --unique (-u). */-
271static struct line saved_line;-
272-
273/* FIXME: None of these tables work with multibyte character sets.-
274 Also, there are many other bugs when handling multibyte characters.-
275 One way to fix this is to rewrite 'sort' to use wide characters-
276 internally, but doing this with good performance is a bit-
277 tricky. */-
278-
279/* Table of blanks. */-
280static bool blanks[UCHAR_LIM];-
281-
282/* Table of non-printing characters. */-
283static bool nonprinting[UCHAR_LIM];-
284-
285/* Table of non-dictionary characters (not letters, digits, or blanks). */-
286static bool nondictionary[UCHAR_LIM];-
287-
288/* Translation table folding lower case to upper. */-
289static char fold_toupper[UCHAR_LIM];-
290-
291#define MONTHS_PER_YEAR 12-
292-
293/* Table mapping month names to integers.-
294 Alphabetic order allows binary search. */-
295static struct month monthtab[] =-
296{-
297 {"APR", 4},-
298 {"AUG", 8},-
299 {"DEC", 12},-
300 {"FEB", 2},-
301 {"JAN", 1},-
302 {"JUL", 7},-
303 {"JUN", 6},-
304 {"MAR", 3},-
305 {"MAY", 5},-
306 {"NOV", 11},-
307 {"OCT", 10},-
308 {"SEP", 9}-
309};-
310-
311/* During the merge phase, the number of files to merge at once. */-
312#define NMERGE_DEFAULT 16-
313-
314/* Minimum size for a merge or check buffer. */-
315#define MIN_MERGE_BUFFER_SIZE (2 + sizeof (struct line))-
316-
317/* Minimum sort size; the code might not work with smaller sizes. */-
318#define MIN_SORT_SIZE (nmerge * MIN_MERGE_BUFFER_SIZE)-
319-
320/* The number of bytes needed for a merge or check buffer, which can-
321 function relatively efficiently even if it holds only one line. If-
322 a longer line is seen, this value is increased. */-
323static size_t merge_buffer_size = MAX (MIN_MERGE_BUFFER_SIZE, 256 * 1024);-
324-
325/* The approximate maximum number of bytes of main memory to use, as-
326 specified by the user. Zero if the user has not specified a size. */-
327static size_t sort_size;-
328-
329/* The initial allocation factor for non-regular files.-
330 This is used, e.g., when reading from a pipe.-
331 Don't make it too big, since it is multiplied by ~130 to-
332 obtain the size of the actual buffer sort will allocate.-
333 Also, there may be 8 threads all doing this at the same time. */-
334#define INPUT_FILE_SIZE_GUESS (128 * 1024)-
335-
336/* Array of directory names in which any temporary files are to be created. */-
337static char const **temp_dirs;-
338-
339/* Number of temporary directory names used. */-
340static size_t temp_dir_count;-
341-
342/* Number of allocated slots in temp_dirs. */-
343static size_t temp_dir_alloc;-
344-
345/* Flag to reverse the order of all comparisons. */-
346static bool reverse;-
347-
348/* Flag for stable sort. This turns off the last ditch bytewise-
349 comparison of lines, and instead leaves lines in the same order-
350 they were read if all keys compare equal. */-
351static bool stable;-
352-
353/* If TAB has this value, blanks separate fields. */-
354enum { TAB_DEFAULT = CHAR_MAX + 1 };-
355-
356/* Tab character separating fields. If TAB_DEFAULT, then fields are-
357 separated by the empty string between a non-blank character and a blank-
358 character. */-
359static int tab = TAB_DEFAULT;-
360-
361/* Flag to remove consecutive duplicate lines from the output.-
362 Only the last of a sequence of equal lines will be output. */-
363static bool unique;-
364-
365/* Nonzero if any of the input files are the standard input. */-
366static bool have_read_stdin;-
367-
368/* List of key field comparisons to be tried. */-
369static struct keyfield *keylist;-
370-
371/* Program used to (de)compress temp files. Must accept -d. */-
372static char const *compress_program;-
373-
374/* Annotate the output with extra info to aid the user. */-
375static bool debug;-
376-
377/* Maximum number of files to merge in one go. If more than this-
378 number are present, temp files will be used. */-
379static unsigned int nmerge = NMERGE_DEFAULT;-
380-
381/* Output an error to stderr and exit using async-signal-safe routines.-
382 This can be used safely from signal handlers,-
383 and between fork and exec of multithreaded processes. */-
384-
385static void async_safe_die (int, const char *) ATTRIBUTE_NORETURN;-
386static void-
387async_safe_die (int errnum, const char *errstr)-
388{-
389 ignore_value (write (STDERR_FILENO, errstr, strlen (errstr)));-
390-
391 /* Even if defined HAVE_STRERROR_R, we can't use it,-
392 as it may return a translated string etc. and even if not-
393 may call malloc which is unsafe. We might improve this-
394 by testing for sys_errlist and using that if available.-
395 For now just report the error number. */-
396 if (errnum)
errnumDescription
TRUEnever evaluated
FALSEnever evaluated
0
397 {-
398 char errbuf[INT_BUFSIZE_BOUND (errnum)];-
399 char *p = inttostr (errnum, errbuf);-
400 ignore_value (write (STDERR_FILENO, ": errno ", 8));-
401 ignore_value (write (STDERR_FILENO, p, strlen (p)));-
402 }
never executed: end of block
0
403-
404 ignore_value (write (STDERR_FILENO, "\n", 1));-
405-
406 _exit (SORT_FAILURE);-
407}
never executed: end of block
0
408-
409/* Report MESSAGE for FILE, then clean up and exit.-
410 If FILE is null, it represents standard output. */-
411-
412static void sort_die (char const *, char const *) ATTRIBUTE_NORETURN;-
413static void-
414sort_die (char const *message, char const *file)-
415{-
416 die (SORT_FAILURE, errno, "%s: %s", message,-
417 quotef (file ? file : _("standard output")));-
418}
never executed: end of block
0
419-
420void-
421usage (int status)-
422{-
423 if (status != EXIT_SUCCESS)
status != 0Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 24 times by 1 test
Evaluated by:
  • sort
5-24
424 emit_try_help ();
executed 5 times by 1 test: end of block
Executed by:
  • sort
5
425 else-
426 {-
427 printf (_("\-
428Usage: %s [OPTION]... [FILE]...\n\-
429 or: %s [OPTION]... --files0-from=F\n\-
430"),-
431 program_name, program_name);-
432 fputs (_("\-
433Write sorted concatenation of all FILE(s) to standard output.\n\-
434"), stdout);-
435-
436 emit_stdin_note ();-
437 emit_mandatory_arg_note ();-
438-
439 fputs (_("\-
440Ordering options:\n\-
441\n\-
442"), stdout);-
443 fputs (_("\-
444 -b, --ignore-leading-blanks ignore leading blanks\n\-
445 -d, --dictionary-order consider only blanks and alphanumeric characters\-
446\n\-
447 -f, --ignore-case fold lower case to upper case characters\n\-
448"), stdout);-
449 fputs (_("\-
450 -g, --general-numeric-sort compare according to general numerical value\n\-
451 -i, --ignore-nonprinting consider only printable characters\n\-
452 -M, --month-sort compare (unknown) < 'JAN' < ... < 'DEC'\n\-
453"), stdout);-
454 fputs (_("\-
455 -h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)\n\-
456"), stdout);-
457 fputs (_("\-
458 -n, --numeric-sort compare according to string numerical value\n\-
459 -R, --random-sort shuffle, but group identical keys. See shuf(1)\n\-
460 --random-source=FILE get random bytes from FILE\n\-
461 -r, --reverse reverse the result of comparisons\n\-
462"), stdout);-
463 fputs (_("\-
464 --sort=WORD sort according to WORD:\n\-
465 general-numeric -g, human-numeric -h, month -M,\-
466\n\-
467 numeric -n, random -R, version -V\n\-
468 -V, --version-sort natural sort of (version) numbers within text\n\-
469\n\-
470"), stdout);-
471 fputs (_("\-
472Other options:\n\-
473\n\-
474"), stdout);-
475 fputs (_("\-
476 --batch-size=NMERGE merge at most NMERGE inputs at once;\n\-
477 for more use temp files\n\-
478"), stdout);-
479 fputs (_("\-
480 -c, --check, --check=diagnose-first check for sorted input; do not sort\n\-
481 -C, --check=quiet, --check=silent like -c, but do not report first bad line\-
482\n\-
483 --compress-program=PROG compress temporaries with PROG;\n\-
484 decompress them with PROG -d\n\-
485"), stdout);-
486 fputs (_("\-
487 --debug annotate the part of the line used to sort,\n\-
488 and warn about questionable usage to stderr\n\-
489 --files0-from=F read input from the files specified by\n\-
490 NUL-terminated names in file F;\n\-
491 If F is - then read names from standard input\n\-
492"), stdout);-
493 fputs (_("\-
494 -k, --key=KEYDEF sort via a key; KEYDEF gives location and type\n\-
495 -m, --merge merge already sorted files; do not sort\n\-
496"), stdout);-
497 fputs (_("\-
498 -o, --output=FILE write result to FILE instead of standard output\n\-
499 -s, --stable stabilize sort by disabling last-resort comparison\-
500\n\-
501 -S, --buffer-size=SIZE use SIZE for main memory buffer\n\-
502"), stdout);-
503 printf (_("\-
504 -t, --field-separator=SEP use SEP instead of non-blank to blank transition\n\-
505 -T, --temporary-directory=DIR use DIR for temporaries, not $TMPDIR or %s;\n\-
506 multiple options specify multiple directories\n\-
507 --parallel=N change the number of sorts run concurrently to N\n\-
508 -u, --unique with -c, check for strict ordering;\n\-
509 without -c, output only the first of an equal run\-
510\n\-
511"), DEFAULT_TMPDIR);-
512 fputs (_("\-
513 -z, --zero-terminated line delimiter is NUL, not newline\n\-
514"), stdout);-
515 fputs (HELP_OPTION_DESCRIPTION, stdout);-
516 fputs (VERSION_OPTION_DESCRIPTION, stdout);-
517 fputs (_("\-
518\n\-
519KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where F is a\n\-
520field number and C a character position in the field; both are origin 1, and\n\-
521the stop position defaults to the line's end. If neither -t nor -b is in\n\-
522effect, characters in a field are counted from the beginning of the preceding\n\-
523whitespace. OPTS is one or more single-letter ordering options [bdfgiMhnRrV],\-
524\n\-
525which override global ordering options for that key. If no key is given, use\n\-
526the entire line as the key. Use --debug to diagnose incorrect key usage.\n\-
527\n\-
528SIZE may be followed by the following multiplicative suffixes:\n\-
529"), stdout);-
530 fputs (_("\-
531% 1% of memory, b 1, K 1024 (default), and so on for M, G, T, P, E, Z, Y.\n\-
532\n\-
533*** WARNING ***\n\-
534The locale specified by the environment affects sort order.\n\-
535Set LC_ALL=C to get the traditional sort order that uses\n\-
536native byte values.\n\-
537"), stdout );-
538 emit_ancillary_info (PROGRAM_NAME);-
539 }
executed 24 times by 1 test: end of block
Executed by:
  • sort
24
540-
541 exit (status);
executed 29 times by 1 test: exit (status);
Executed by:
  • sort
29
542}-
543-
544/* For long options that have no equivalent short option, use a-
545 non-character as a pseudo short option, starting with CHAR_MAX + 1. */-
546enum-
547{-
548 CHECK_OPTION = CHAR_MAX + 1,-
549 COMPRESS_PROGRAM_OPTION,-
550 DEBUG_PROGRAM_OPTION,-
551 FILES0_FROM_OPTION,-
552 NMERGE_OPTION,-
553 RANDOM_SOURCE_OPTION,-
554 SORT_OPTION,-
555 PARALLEL_OPTION-
556};-
557-
558static char const short_options[] = "-bcCdfghik:mMno:rRsS:t:T:uVy:z";-
559-
560static struct option const long_options[] =-
561{-
562 {"ignore-leading-blanks", no_argument, NULL, 'b'},-
563 {"check", optional_argument, NULL, CHECK_OPTION},-
564 {"compress-program", required_argument, NULL, COMPRESS_PROGRAM_OPTION},-
565 {"debug", no_argument, NULL, DEBUG_PROGRAM_OPTION},-
566 {"dictionary-order", no_argument, NULL, 'd'},-
567 {"ignore-case", no_argument, NULL, 'f'},-
568 {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},-
569 {"general-numeric-sort", no_argument, NULL, 'g'},-
570 {"ignore-nonprinting", no_argument, NULL, 'i'},-
571 {"key", required_argument, NULL, 'k'},-
572 {"merge", no_argument, NULL, 'm'},-
573 {"month-sort", no_argument, NULL, 'M'},-
574 {"numeric-sort", no_argument, NULL, 'n'},-
575 {"human-numeric-sort", no_argument, NULL, 'h'},-
576 {"version-sort", no_argument, NULL, 'V'},-
577 {"random-sort", no_argument, NULL, 'R'},-
578 {"random-source", required_argument, NULL, RANDOM_SOURCE_OPTION},-
579 {"sort", required_argument, NULL, SORT_OPTION},-
580 {"output", required_argument, NULL, 'o'},-
581 {"reverse", no_argument, NULL, 'r'},-
582 {"stable", no_argument, NULL, 's'},-
583 {"batch-size", required_argument, NULL, NMERGE_OPTION},-
584 {"buffer-size", required_argument, NULL, 'S'},-
585 {"field-separator", required_argument, NULL, 't'},-
586 {"temporary-directory", required_argument, NULL, 'T'},-
587 {"unique", no_argument, NULL, 'u'},-
588 {"zero-terminated", no_argument, NULL, 'z'},-
589 {"parallel", required_argument, NULL, PARALLEL_OPTION},-
590 {GETOPT_HELP_OPTION_DECL},-
591 {GETOPT_VERSION_OPTION_DECL},-
592 {NULL, 0, NULL, 0},-
593};-
594-
595#define CHECK_TABLE \-
596 _ct_("quiet", 'C') \-
597 _ct_("silent", 'C') \-
598 _ct_("diagnose-first", 'c')-
599-
600static char const *const check_args[] =-
601{-
602#define _ct_(_s, _c) _s,-
603 CHECK_TABLE NULL-
604#undef _ct_-
605};-
606static char const check_types[] =-
607{-
608#define _ct_(_s, _c) _c,-
609 CHECK_TABLE-
610#undef _ct_-
611};-
612-
613#define SORT_TABLE \-
614 _st_("general-numeric", 'g') \-
615 _st_("human-numeric", 'h') \-
616 _st_("month", 'M') \-
617 _st_("numeric", 'n') \-
618 _st_("random", 'R') \-
619 _st_("version", 'V')-
620-
621static char const *const sort_args[] =-
622{-
623#define _st_(_s, _c) _s,-
624 SORT_TABLE NULL-
625#undef _st_-
626};-
627static char const sort_types[] =-
628{-
629#define _st_(_s, _c) _c,-
630 SORT_TABLE-
631#undef _st_-
632};-
633-
634/* The set of signals that are caught. */-
635static sigset_t caught_signals;-
636-
637/* Critical section status. */-
638struct cs_status-
639{-
640 bool valid;-
641 sigset_t sigs;-
642};-
643-
644/* Enter a critical section. */-
645static void-
646cs_enter (struct cs_status *status)-
647{-
648 int ret = pthread_sigmask (SIG_BLOCK, &caught_signals, &status->sigs);-
649 status->valid = ret == 0;-
650}
executed 8476 times by 1 test: end of block
Executed by:
  • sort
8476
651-
652/* Leave a critical section. */-
653static void-
654cs_leave (struct cs_status const *status)-
655{-
656 if (status->valid)
status->validDescription
TRUEevaluated 8476 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-8476
657 {-
658 /* Ignore failure when restoring the signal mask. */-
659 pthread_sigmask (SIG_SETMASK, &status->sigs, NULL);-
660 }
executed 8476 times by 1 test: end of block
Executed by:
  • sort
8476
661}
executed 8476 times by 1 test: end of block
Executed by:
  • sort
8476
662-
663/* Possible states for a temp file. If compressed, the file's status-
664 is unreaped or reaped, depending on whether 'sort' has waited for-
665 the subprocess to finish. */-
666enum { UNCOMPRESSED, UNREAPED, REAPED };-
667-
668/* The list of temporary files. */-
669struct tempnode-
670{-
671 struct tempnode *volatile next;-
672 pid_t pid; /* The subprocess PID; undefined if state == UNCOMPRESSED. */-
673 char state;-
674 char name[FLEXIBLE_ARRAY_MEMBER];-
675};-
676static struct tempnode *volatile temphead;-
677static struct tempnode *volatile *temptail = &temphead;-
678-
679/* A file to be sorted. */-
680struct sortfile-
681{-
682 /* The file's name. */-
683 char const *name;-
684-
685 /* Non-null if this is a temporary file, in which case NAME == TEMP->name. */-
686 struct tempnode *temp;-
687};-
688-
689/* Map PIDs of unreaped subprocesses to their struct tempnode objects. */-
690static Hash_table *proctab;-
691-
692enum { INIT_PROCTAB_SIZE = 47 };-
693-
694static size_t-
695proctab_hasher (void const *entry, size_t tabsize)-
696{-
697 struct tempnode const *node = entry;-
698 return node->pid % tabsize;
executed 7440 times by 1 test: return node->pid % tabsize;
Executed by:
  • sort
7440
699}-
700-
701static bool-
702proctab_comparator (void const *e1, void const *e2)-
703{-
704 struct tempnode const *n1 = e1;-
705 struct tempnode const *n2 = e2;-
706 return n1->pid == n2->pid;
executed 3963 times by 1 test: return n1->pid == n2->pid;
Executed by:
  • sort
3963
707}-
708-
709/* The number of unreaped child processes. */-
710static pid_t nprocs;-
711-
712static bool delete_proc (pid_t);-
713-
714/* If PID is positive, wait for the child process with that PID to-
715 exit, and assume that PID has already been removed from the process-
716 table. If PID is 0 or -1, clean up some child that has exited (by-
717 waiting for it, and removing it from the proc table) and return the-
718 child's process ID. However, if PID is 0 and no children have-
719 exited, return 0 without waiting. */-
720-
721static pid_t-
722reap (pid_t pid)-
723{-
724 int status;-
725 pid_t cpid = waitpid ((pid ? pid : -1), &status, (pid ? 0 : WNOHANG));-
726-
727 if (cpid < 0)
cpid < 0Description
TRUEnever evaluated
FALSEevaluated 5513 times by 1 test
Evaluated by:
  • sort
0-5513
728 die (SORT_FAILURE, errno, _("waiting for %s [-d]"),
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"waiting for %s [-d]\", 5), quotearg_style (shell_escape_always_quoting_style, compress_program)... : __builtin_unreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "waiting for %s [-d]" , 5) , quotearg_style (shell_escape_always_quoting_style, compress_program)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
0
729 quoteaf (compress_program));
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"waiting for %s [-d]\", 5), quotearg_style (shell_escape_always_quoting_style, compress_program)... : __builtin_unreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "waiting for %s [-d]" , 5) , quotearg_style (shell_escape_always_quoting_style, compress_program)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
0
730 else if (0 < cpid && (0 < pid || delete_proc (cpid)))
0 < cpidDescription
TRUEevaluated 3720 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1793 times by 1 test
Evaluated by:
  • sort
0 < pidDescription
TRUEevaluated 1867 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1853 times by 1 test
Evaluated by:
  • sort
delete_proc (cpid)Description
TRUEevaluated 1852 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1 time by 1 test
Evaluated by:
  • sort
1-3720
731 {-
732 if (! WIFEXITED (status) || WEXITSTATUS (status))
! ((( status ) & 0x7f) == 0)Description
TRUEnever evaluated
FALSEevaluated 3719 times by 1 test
Evaluated by:
  • sort
((( status ) & 0xff00) >> 8)Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 3717 times by 1 test
Evaluated by:
  • sort
0-3719
733 die (SORT_FAILURE, 0, _("%s [-d] terminated abnormally"),
executed 2 times by 1 test: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, 0, dcgettext (((void *)0), \"%s [-d] terminated abnormally\", 5), quotearg_style (shell_escape_always_quoting_style, compress_program)), assume (...) ? (void) 0 : __builtin_unreachable ()))) : ((error (SORT_FAILURE, 0, dcgettext (((void *)0), "%s [-d] terminated abnormally" , 5) , quotearg_style (shell_escape_always_quoting_style, compress_program)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
Executed by:
  • sort
2
734 quoteaf (compress_program));
executed 2 times by 1 test: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, 0, dcgettext (((void *)0), \"%s [-d] terminated abnormally\", 5), quotearg_style (shell_escape_always_quoting_style, compress_program)), assume (...) ? (void) 0 : __builtin_unreachable ()))) : ((error (SORT_FAILURE, 0, dcgettext (((void *)0), "%s [-d] terminated abnormally" , 5) , quotearg_style (shell_escape_always_quoting_style, compress_program)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
Executed by:
  • sort
2
735 --nprocs;-
736 }
executed 3717 times by 1 test: end of block
Executed by:
  • sort
3717
737-
738 return cpid;
executed 5511 times by 1 test: return cpid;
Executed by:
  • sort
5511
739}-
740-
741/* TEMP represents a new process; add it to the process table. Create-
742 the process table the first time it's called. */-
743-
744static void-
745register_proc (struct tempnode *temp)-
746{-
747 if (! proctab)
! proctabDescription
TRUEevaluated 7 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 3713 times by 1 test
Evaluated by:
  • sort
7-3713
748 {-
749 proctab = hash_initialize (INIT_PROCTAB_SIZE, NULL,-
750 proctab_hasher,-
751 proctab_comparator,-
752 NULL);-
753 if (! proctab)
! proctabDescription
TRUEnever evaluated
FALSEevaluated 7 times by 1 test
Evaluated by:
  • sort
0-7
754 xalloc_die ();
never executed: xalloc_die ();
0
755 }
executed 7 times by 1 test: end of block
Executed by:
  • sort
7
756-
757 temp->state = UNREAPED;-
758-
759 if (! hash_insert (proctab, temp))
! hash_insert (proctab, temp)Description
TRUEnever evaluated
FALSEevaluated 3720 times by 1 test
Evaluated by:
  • sort
0-3720
760 xalloc_die ();
never executed: xalloc_die ();
0
761}
executed 3720 times by 1 test: end of block
Executed by:
  • sort
3720
762-
763/* If PID is in the process table, remove it and return true.-
764 Otherwise, return false. */-
765-
766static bool-
767delete_proc (pid_t pid)-
768{-
769 struct tempnode test;-
770-
771 test.pid = pid;-
772 struct tempnode *node = hash_delete (proctab, &test);-
773 if (! node)
! nodeDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • sort
FALSEevaluated 3719 times by 1 test
Evaluated by:
  • sort
1-3719
774 return false;
executed 1 time by 1 test: return 0 ;
Executed by:
  • sort
1
775 node->state = REAPED;-
776 return true;
executed 3719 times by 1 test: return 1 ;
Executed by:
  • sort
3719
777}-
778-
779/* Remove PID from the process table, and wait for it to exit if it-
780 hasn't already. */-
781-
782static void-
783wait_proc (pid_t pid)-
784{-
785 if (delete_proc (pid))
delete_proc (pid)Description
TRUEevaluated 1867 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-1867
786 reap (pid);
executed 1867 times by 1 test: reap (pid);
Executed by:
  • sort
1867
787}
executed 1865 times by 1 test: end of block
Executed by:
  • sort
1865
788-
789/* Reap any exited children. Do not block; reap only those that have-
790 already exited. */-
791-
792static void-
793reap_exited (void)-
794{-
795 while (0 < nprocs && reap (0))
0 < nprocsDescription
TRUEevaluated 1853 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
reap (0)Description
TRUEevaluated 60 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1793 times by 1 test
Evaluated by:
  • sort
0-1853
796 continue;
executed 60 times by 1 test: continue;
Executed by:
  • sort
60
797}
executed 1793 times by 1 test: end of block
Executed by:
  • sort
1793
798-
799/* Reap at least one exited child, waiting if necessary. */-
800-
801static void-
802reap_some (void)-
803{-
804 reap (-1);-
805 reap_exited ();-
806}
executed 1793 times by 1 test: end of block
Executed by:
  • sort
1793
807-
808/* Reap all children, waiting if necessary. */-
809-
810static void-
811reap_all (void)-
812{-
813 while (0 < nprocs)
0 < nprocsDescription
TRUEnever evaluated
FALSEevaluated 711 times by 1 test
Evaluated by:
  • sort
0-711
814 reap (-1);
never executed: reap (-1);
0
815}
executed 711 times by 1 test: end of block
Executed by:
  • sort
711
816-
817/* Clean up any remaining temporary files. */-
818-
819static void-
820cleanup (void)-
821{-
822 struct tempnode const *node;-
823-
824 for (node = temphead; node; node = node->next)
nodeDescription
TRUEevaluated 8 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 7 times by 1 test
Evaluated by:
  • sort
7-8
825 unlink (node->name);
executed 8 times by 1 test: unlink (node->name);
Executed by:
  • sort
8
826 temphead = NULL;-
827}
executed 7 times by 1 test: end of block
Executed by:
  • sort
7
828-
829/* Cleanup actions to take when exiting. */-
830-
831static void-
832exit_cleanup (void)-
833{-
834 if (temphead)
tempheadDescription
TRUEevaluated 7 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 852 times by 1 test
Evaluated by:
  • sort
7-852
835 {-
836 /* Clean up any remaining temporary files in a critical section so-
837 that a signal handler does not try to clean them too. */-
838 struct cs_status cs;-
839 cs_enter (&cs);-
840 cleanup ();-
841 cs_leave (&cs);-
842 }
executed 7 times by 1 test: end of block
Executed by:
  • sort
7
843-
844 close_stdout ();-
845}
executed 859 times by 1 test: end of block
Executed by:
  • sort
859
846-
847/* Create a new temporary file, returning its newly allocated tempnode.-
848 Store into *PFD the file descriptor open for writing.-
849 If the creation fails, return NULL and store -1 into *PFD if the-
850 failure is due to file descriptor exhaustion and-
851 SURVIVE_FD_EXHAUSTION; otherwise, die. */-
852-
853static struct tempnode *-
854create_temp_file (int *pfd, bool survive_fd_exhaustion)-
855{-
856 static char const slashbase[] = "/sortXXXXXX";-
857 static size_t temp_dir_index;-
858 int fd;-
859 int saved_errno;-
860 char const *temp_dir = temp_dirs[temp_dir_index];-
861 size_t len = strlen (temp_dir);-
862 struct tempnode *node =-
863 xmalloc (FLEXSIZEOF (struct tempnode, name, len + sizeof slashbase));-
864 char *file = node->name;-
865 struct cs_status cs;-
866-
867 memcpy (file, temp_dir, len);-
868 memcpy (file + len, slashbase, sizeof slashbase);-
869 node->next = NULL;-
870 if (++temp_dir_index == temp_dir_count)
++temp_dir_ind...temp_dir_countDescription
TRUEevaluated 2379 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-2379
871 temp_dir_index = 0;
executed 2379 times by 1 test: temp_dir_index = 0;
Executed by:
  • sort
2379
872-
873 /* Create the temporary file in a critical section, to avoid races. */-
874 cs_enter (&cs);-
875 fd = mkostemp (file, O_CLOEXEC);-
876 if (0 <= fd)
0 <= fdDescription
TRUEevaluated 2378 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1 time by 1 test
Evaluated by:
  • sort
1-2378
877 {-
878 *temptail = node;-
879 temptail = &node->next;-
880 }
executed 2378 times by 1 test: end of block
Executed by:
  • sort
2378
881 saved_errno = errno;-
882 cs_leave (&cs);-
883 errno = saved_errno;-
884-
885 if (fd < 0)
fd < 0Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • sort
FALSEevaluated 2378 times by 1 test
Evaluated by:
  • sort
1-2378
886 {-
887 if (! (survive_fd_exhaustion && errno == EMFILE))
survive_fd_exhaustionDescription
TRUEnever evaluated
FALSEevaluated 1 time by 1 test
Evaluated by:
  • sort
(*__errno_location ()) == 24Description
TRUEnever evaluated
FALSEnever evaluated
0-1
888 die (SORT_FAILURE, errno, _("cannot create temporary file in %s"),
executed 1 time by 1 test: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"cannot create temporary file in %s\", 5), quotearg_style (shell_escape_always_quoting_style, te...iltin_unreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "cannot create temporary file in %s" , 5) , quotearg_style (shell_escape_always_quoting_style, temp_dir)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
Executed by:
  • sort
1
889 quoteaf (temp_dir));
executed 1 time by 1 test: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"cannot create temporary file in %s\", 5), quotearg_style (shell_escape_always_quoting_style, te...iltin_unreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "cannot create temporary file in %s" , 5) , quotearg_style (shell_escape_always_quoting_style, temp_dir)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
Executed by:
  • sort
1
890 free (node);-
891 node = NULL;-
892 }
never executed: end of block
0
893-
894 *pfd = fd;-
895 return node;
executed 2378 times by 1 test: return node;
Executed by:
  • sort
2378
896}-
897-
898/* Return a stream for FILE, opened with mode HOW. A null FILE means-
899 standard output; HOW should be "w". When opening for input, "-"-
900 means standard input. To avoid confusion, do not return file-
901 descriptors STDIN_FILENO, STDOUT_FILENO, or STDERR_FILENO when-
902 opening an ordinary FILE. Return NULL if unsuccessful.-
903-
904 Use fadvise to specify an access pattern for input files.-
905 There are a few hints we could possibly provide,-
906 and after careful testing it was decided that-
907 specifying FADVISE_SEQUENTIAL was not detrimental-
908 to any cases. On Linux 2.6.31, this option doubles-
909 the size of read ahead performed and thus was seen to-
910 benefit these cases:-
911 Merging-
912 Sorting with a smaller internal buffer-
913 Reading from faster flash devices-
914-
915 In _addition_ one could also specify other hints...-
916-
917 FADVISE_WILLNEED was tested, but Linux 2.6.31-
918 at least uses that to _synchronously_ prepopulate the cache-
919 with the specified range. While sort does need to-
920 read all of its input before outputting, a synchronous-
921 read of the whole file up front precludes any processing-
922 that sort could do in parallel with the system doing-
923 read ahead of the data. This was seen to have negative effects-
924 in a couple of cases:-
925 Merging-
926 Sorting with a smaller internal buffer-
927 This option was seen to shorten the runtime for sort-
928 on a multicore system with lots of RAM and other processes-
929 competing for CPU. It could be argued that more explicit-
930 scheduling hints with 'nice' et. al. are more appropriate-
931 for this situation.-
932-
933 FADVISE_NOREUSE is a possibility as it could lower-
934 the priority of input data in the cache as sort will-
935 only need to process it once. However its functionality-
936 has changed over Linux kernel versions and as of 2.6.31-
937 it does nothing and thus we can't depend on what it might-
938 do in future.-
939-
940 FADVISE_DONTNEED is not appropriate for user specified-
941 input files, but for temp files we do want to drop the-
942 cache immediately after processing. This is done implicitly-
943 however when the files are unlinked. */-
944-
945static FILE *-
946stream_open (char const *file, char const *how)-
947{-
948 FILE *fp;-
949-
950 if (*how == 'r')
*how == 'r'Description
TRUEevaluated 1516 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 725 times by 1 test
Evaluated by:
  • sort
725-1516
951 {-
952 if (STREQ (file, "-"))
never executed: __result = (((const unsigned char *) (const char *) ( file ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( "-" ))[3] - __s2[3]);
never executed: end of block
executed 571 times by 1 test: end of block
Executed by:
  • sort
( __extension_...)))); }) == 0)Description
TRUEevaluated 571 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 945 times by 1 test
Evaluated by:
  • sort
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEevaluated 1516 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
__result == 0Description
TRUEevaluated 571 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 945 times by 1 test
Evaluated by:
  • sort
__s2_len > 1Description
TRUEnever evaluated
FALSEevaluated 571 times by 1 test
Evaluated by:
  • sort
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-1516
953 {-
954 have_read_stdin = true;-
955 fp = stdin;-
956 }
executed 571 times by 1 test: end of block
Executed by:
  • sort
571
957 else-
958 {-
959 int fd = open (file, O_RDONLY | O_CLOEXEC);-
960 fp = fd < 0 ? NULL : fdopen (fd, how);
fd < 0Description
TRUEevaluated 64 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 881 times by 1 test
Evaluated by:
  • sort
64-881
961 }
executed 945 times by 1 test: end of block
Executed by:
  • sort
945
962 fadvise (fp, FADVISE_SEQUENTIAL);-
963 }
executed 1516 times by 1 test: end of block
Executed by:
  • sort
1516
964 else if (*how == 'w')
*how == 'w'Description
TRUEevaluated 725 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-725
965 {-
966 if (file && ftruncate (STDOUT_FILENO, 0) != 0)
fileDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 719 times by 1 test
Evaluated by:
  • sort
ftruncate ( 1 , 0) != 0Description
TRUEnever evaluated
FALSEevaluated 6 times by 1 test
Evaluated by:
  • sort
0-719
967 die (SORT_FAILURE, errno, _("%s: error truncating"),
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"%s: error truncating\", 5), quotearg_n_style_colon (0, shell_escape_quoting_style, file)), assu...void) 0 : __builtin_unreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "%s: error truncating" , 5) , quotearg_n_style_colon (0, shell_escape_quoting_style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
0
968 quotef (file));
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"%s: error truncating\", 5), quotearg_n_style_colon (0, shell_escape_quoting_style, file)), assu...void) 0 : __builtin_unreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "%s: error truncating" , 5) , quotearg_n_style_colon (0, shell_escape_quoting_style, file)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
0
969 fp = stdout;-
970 }
executed 725 times by 1 test: end of block
Executed by:
  • sort
725
971 else-
972 assert (!"unexpected mode passed to stream_open");
never executed: (( !"unexpected mode passed to stream_open" ) ? (void) (0) : __assert_fail ( "!\"unexpected mode passed to stream_open\"" , "src/sort.c", 972, __PRETTY_FUNCTION__)) ;
0
973-
974 return fp;
executed 2241 times by 1 test: return fp;
Executed by:
  • sort
2241
975}-
976-
977/* Same as stream_open, except always return a non-null value; die on-
978 failure. */-
979-
980static FILE *-
981xfopen (char const *file, char const *how)-
982{-
983 FILE *fp = stream_open (file, how);-
984 if (!fp)
!fpDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • sort
FALSEevaluated 1401 times by 1 test
Evaluated by:
  • sort
1-1401
985 sort_die (_("open failed"), file);
executed 1 time by 1 test: sort_die ( dcgettext (((void *)0), "open failed" , 5) , file);
Executed by:
  • sort
1
986 return fp;
executed 1401 times by 1 test: return fp;
Executed by:
  • sort
1401
987}-
988-
989/* Close FP, whose name is FILE, and report any errors. */-
990-
991static void-
992xfclose (FILE *fp, char const *file)-
993{-
994 switch (fileno (fp))-
995 {-
996 case STDIN_FILENO:
executed 571 times by 1 test: case 0 :
Executed by:
  • sort
571
997 /* Allow reading stdin from tty more than once. */-
998 if (feof (fp))
feof_unlocked (fp)Description
TRUEevaluated 571 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-571
999 clearerr (fp);
executed 571 times by 1 test: clearerr_unlocked (fp);
Executed by:
  • sort
571
1000 break;
executed 571 times by 1 test: break;
Executed by:
  • sort
571
1001-
1002 case STDOUT_FILENO:
executed 724 times by 1 test: case 1 :
Executed by:
  • sort
724
1003 /* Don't close stdout just yet. close_stdout does that. */-
1004 if (fflush (fp) != 0)
fflush_unlocked (fp) != 0Description
TRUEnever evaluated
FALSEevaluated 724 times by 1 test
Evaluated by:
  • sort
0-724
1005 sort_die (_("fflush failed"), file);
never executed: sort_die ( dcgettext (((void *)0), "fflush failed" , 5) , file);
0
1006 break;
executed 724 times by 1 test: break;
Executed by:
  • sort
724
1007-
1008 default:
executed 5118 times by 1 test: default:
Executed by:
  • sort
5118
1009 if (fclose (fp) != 0)
rpl_fclose (fp) != 0Description
TRUEnever evaluated
FALSEevaluated 5118 times by 1 test
Evaluated by:
  • sort
0-5118
1010 sort_die (_("close failed"), file);
never executed: sort_die ( dcgettext (((void *)0), "close failed" , 5) , file);
0
1011 break;
executed 5118 times by 1 test: break;
Executed by:
  • sort
5118
1012 }-
1013}-
1014-
1015/* Move OLDFD to NEWFD. If OLDFD != NEWFD, NEWFD is not close-on-exec. */-
1016-
1017static void-
1018move_fd (int oldfd, int newfd)-
1019{-
1020 if (oldfd != newfd)
oldfd != newfdDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-6
1021 {-
1022 /* This should never fail for our usage. */-
1023 dup2 (oldfd, newfd);-
1024 close (oldfd);-
1025 }
executed 6 times by 1 test: end of block
Executed by:
  • sort
6
1026}
executed 6 times by 1 test: end of block
Executed by:
  • sort
6
1027-
1028/* Fork a child process for piping to and do common cleanup. The-
1029 TRIES parameter specifies how many times to try to fork before-
1030 giving up. Return the PID of the child, or -1 (setting errno)-
1031 on failure. */-
1032-
1033static pid_t-
1034pipe_fork (int pipefds[2], size_t tries)-
1035{-
1036#if HAVE_WORKING_FORK-
1037 struct tempnode *saved_temphead;-
1038 int saved_errno;-
1039 double wait_retry = 0.25;-
1040 pid_t pid IF_LINT ( = -1);-
1041 struct cs_status cs;-
1042-
1043 if (pipe2 (pipefds, O_CLOEXEC) < 0)
rpl_pipe2 (pip...02000000 ) < 0Description
TRUEnever evaluated
FALSEevaluated 3720 times by 1 test
Evaluated by:
  • sort
0-3720
1044 return -1;
never executed: return -1;
0
1045-
1046 /* At least NMERGE + 1 subprocesses are needed. More could be created, but-
1047 uncontrolled subprocess generation can hurt performance significantly.-
1048 Allow at most NMERGE + 2 subprocesses, on the theory that there-
1049 may be some useful parallelism by letting compression for the-
1050 previous merge finish (1 subprocess) in parallel with the current-
1051 merge (NMERGE + 1 subprocesses). */-
1052-
1053 if (nmerge + 1 < nprocs)
nmerge + 1 < nprocsDescription
TRUEevaluated 1793 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1927 times by 1 test
Evaluated by:
  • sort
1793-1927
1054 reap_some ();
executed 1793 times by 1 test: reap_some ();
Executed by:
  • sort
1793
1055-
1056 while (tries--)
tries--Description
TRUEevaluated 3720 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-3720
1057 {-
1058 /* This is so the child process won't delete our temp files-
1059 if it receives a signal before exec-ing. */-
1060 cs_enter (&cs);-
1061 saved_temphead = temphead;-
1062 temphead = NULL;-
1063-
1064 pid = fork ();-
1065 saved_errno = errno;-
1066 if (pid)
pidDescription
TRUEevaluated 3720 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-3720
1067 temphead = saved_temphead;
executed 3720 times by 1 test: temphead = saved_temphead;
Executed by:
  • sort
3720
1068-
1069 cs_leave (&cs);-
1070 errno = saved_errno;-
1071-
1072 if (0 <= pid || errno != EAGAIN)
0 <= pidDescription
TRUEevaluated 3720 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
(*__errno_location ()) != 11Description
TRUEnever evaluated
FALSEnever evaluated
0-3720
1073 break;
executed 3720 times by 1 test: break;
Executed by:
  • sort
3720
1074 else-
1075 {-
1076 xnanosleep (wait_retry);-
1077 wait_retry *= 2;-
1078 reap_exited ();-
1079 }
never executed: end of block
0
1080 }-
1081-
1082 if (pid < 0)
pid < 0Description
TRUEnever evaluated
FALSEevaluated 3720 times by 1 test
Evaluated by:
  • sort
0-3720
1083 {-
1084 saved_errno = errno;-
1085 close (pipefds[0]);-
1086 close (pipefds[1]);-
1087 errno = saved_errno;-
1088 }
never executed: end of block
0
1089 else if (pid == 0)
pid == 0Description
TRUEnever evaluated
FALSEevaluated 3720 times by 1 test
Evaluated by:
  • sort
0-3720
1090 {-
1091 close (STDIN_FILENO);-
1092 close (STDOUT_FILENO);-
1093 }
never executed: end of block
0
1094 else-
1095 ++nprocs;
executed 3720 times by 1 test: ++nprocs;
Executed by:
  • sort
3720
1096-
1097 return pid;
executed 3720 times by 1 test: return pid;
Executed by:
  • sort
3720
1098-
1099#else /* ! HAVE_WORKING_FORK */-
1100 return -1;-
1101#endif-
1102}-
1103-
1104/* Create a temporary file and, if asked for, start a compressor-
1105 to that file. Set *PFP to the file handle and return-
1106 the address of the new temp node. If the creation-
1107 fails, return NULL if the failure is due to file descriptor-
1108 exhaustion and SURVIVE_FD_EXHAUSTION; otherwise, die. */-
1109-
1110static struct tempnode *-
1111maybe_create_temp (FILE **pfp, bool survive_fd_exhaustion)-
1112{-
1113 int tempfd;-
1114 struct tempnode *node = create_temp_file (&tempfd, survive_fd_exhaustion);-
1115 if (! node)
! nodeDescription
TRUEnever evaluated
FALSEevaluated 2378 times by 1 test
Evaluated by:
  • sort
0-2378
1116 return NULL;
never executed: return ((void *)0) ;
0
1117-
1118 node->state = UNCOMPRESSED;-
1119-
1120 if (compress_program)
compress_programDescription
TRUEevaluated 1861 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 517 times by 1 test
Evaluated by:
  • sort
517-1861
1121 {-
1122 int pipefds[2];-
1123-
1124 node->pid = pipe_fork (pipefds, MAX_FORK_TRIES_COMPRESS);-
1125 if (0 < node->pid)
0 < node->pidDescription
TRUEevaluated 1861 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-1861
1126 {-
1127 close (tempfd);-
1128 close (pipefds[0]);-
1129 tempfd = pipefds[1];-
1130-
1131 register_proc (node);-
1132 }
executed 1861 times by 1 test: end of block
Executed by:
  • sort
1861
1133 else if (node->pid == 0)
node->pid == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1134 {-
1135 /* Being the child of a multithreaded program before exec,-
1136 we're restricted to calling async-signal-safe routines here. */-
1137 close (pipefds[1]);-
1138 move_fd (tempfd, STDOUT_FILENO);-
1139 move_fd (pipefds[0], STDIN_FILENO);-
1140-
1141 execlp (compress_program, compress_program, (char *) NULL);-
1142-
1143 async_safe_die (errno, "couldn't execute compress program");-
1144 }
never executed: end of block
0
1145 }
executed 1861 times by 1 test: end of block
Executed by:
  • sort
1861
1146-
1147 *pfp = fdopen (tempfd, "w");-
1148 if (! *pfp)
! *pfpDescription
TRUEnever evaluated
FALSEevaluated 2378 times by 1 test
Evaluated by:
  • sort
0-2378
1149 sort_die (_("couldn't create temporary file"), node->name);
never executed: sort_die ( dcgettext (((void *)0), "couldn't create temporary file" , 5) , node->name);
0
1150-
1151 return node;
executed 2378 times by 1 test: return node;
Executed by:
  • sort
2378
1152}-
1153-
1154/* Create a temporary file and, if asked for, start a compressor-
1155 to that file. Set *PFP to the file handle and return the address-
1156 of the new temp node. Die on failure. */-
1157-
1158static struct tempnode *-
1159create_temp (FILE **pfp)-
1160{-
1161 return maybe_create_temp (pfp, false);
executed 2350 times by 1 test: return maybe_create_temp (pfp, 0 );
Executed by:
  • sort
2350
1162}-
1163-
1164/* Open a compressed temp file and start a decompression process through-
1165 which to filter the input. Return NULL (setting errno to-
1166 EMFILE) if we ran out of file descriptors, and die on any other-
1167 kind of failure. */-
1168-
1169static FILE *-
1170open_temp (struct tempnode *temp)-
1171{-
1172 int tempfd, pipefds[2];-
1173 FILE *fp = NULL;-
1174-
1175 if (temp->state == UNREAPED)
temp->state == UNREAPEDDescription
TRUEevaluated 20 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1840 times by 1 test
Evaluated by:
  • sort
20-1840
1176 wait_proc (temp->pid);
executed 20 times by 1 test: wait_proc (temp->pid);
Executed by:
  • sort
20
1177-
1178 tempfd = open (temp->name, O_RDONLY);-
1179 if (tempfd < 0)
tempfd < 0Description
TRUEnever evaluated
FALSEevaluated 1859 times by 1 test
Evaluated by:
  • sort
0-1859
1180 return NULL;
never executed: return ((void *)0) ;
0
1181-
1182 pid_t child = pipe_fork (pipefds, MAX_FORK_TRIES_DECOMPRESS);-
1183-
1184 switch (child)-
1185 {-
1186 case -1:
never executed: case -1:
0
1187 if (errno != EMFILE)
(*__errno_location ()) != 24Description
TRUEnever evaluated
FALSEnever evaluated
0
1188 die (SORT_FAILURE, errno, _("couldn't create process for %s -d"),
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"couldn't create process for %s -d\", 5), quotearg_style (shell_escape_always_quoting_style, com...nreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "couldn't create process for %s -d" , 5) , quotearg_style (shell_escape_always_quoting_style, compress_program)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
0
1189 quoteaf (compress_program));
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, (*__errno_location ()), dcgettext (((void *)0), \"couldn't create process for %s -d\", 5), quotearg_style (shell_escape_always_quoting_style, com...nreachable ()))) : ((error (SORT_FAILURE, (*__errno_location ()) , dcgettext (((void *)0), "couldn't create process for %s -d" , 5) , quotearg_style (shell_escape_always_quoting_style, compress_program)), (( 0 ) ? (void) 0 : __builtin_unreachable ())))) ;
0
1190 close (tempfd);-
1191 errno = EMFILE;-
1192 break;
never executed: break;
0
1193-
1194 case 0:
never executed: case 0:
0
1195 /* Being the child of a multithreaded program before exec,-
1196 we're restricted to calling async-signal-safe routines here. */-
1197 close (pipefds[0]);-
1198 move_fd (tempfd, STDIN_FILENO);-
1199 move_fd (pipefds[1], STDOUT_FILENO);-
1200-
1201 execlp (compress_program, compress_program, "-d", (char *) NULL);-
1202-
1203 async_safe_die (errno, "couldn't execute compress program (with -d)");-
1204-
1205 default:
code before this statement never executed: default:
executed 1859 times by 1 test: default:
Executed by:
  • sort
0-1859
1206 temp->pid = child;-
1207 register_proc (temp);-
1208 close (tempfd);-
1209 close (pipefds[1]);-
1210-
1211 fp = fdopen (pipefds[0], "r");-
1212 if (! fp)
! fpDescription
TRUEnever evaluated
FALSEevaluated 1859 times by 1 test
Evaluated by:
  • sort
0-1859
1213 {-
1214 int saved_errno = errno;-
1215 close (pipefds[0]);-
1216 errno = saved_errno;-
1217 }
never executed: end of block
0
1218 break;
executed 1859 times by 1 test: break;
Executed by:
  • sort
1859
1219 }-
1220-
1221 return fp;
executed 1859 times by 1 test: return fp;
Executed by:
  • sort
1859
1222}-
1223-
1224/* Append DIR to the array of temporary directory names. */-
1225static void-
1226add_temp_dir (char const *dir)-
1227{-
1228 if (temp_dir_count == temp_dir_alloc)
temp_dir_count...temp_dir_allocDescription
TRUEevaluated 777 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-777
1229 temp_dirs = X2NREALLOC (temp_dirs, &temp_dir_alloc);
executed 777 times by 1 test: temp_dirs = ((void) (!!sizeof (struct { _Static_assert (sizeof *(temp_dirs) != 1, "verify_true (" "sizeof *(temp_dirs) != 1" ")"); int _gl_dummy; })), x2nrealloc (temp_dirs, &temp_dir_alloc, sizeof *(temp_dirs)));
Executed by:
  • sort
777
1230-
1231 temp_dirs[temp_dir_count++] = dir;-
1232}
executed 777 times by 1 test: end of block
Executed by:
  • sort
777
1233-
1234/* Remove NAME from the list of temporary files. */-
1235-
1236static void-
1237zaptemp (char const *name)-
1238{-
1239 struct tempnode *volatile *pnode;-
1240 struct tempnode *node;-
1241 struct tempnode *next;-
1242 int unlink_status;-
1243 int unlink_errno = 0;-
1244 struct cs_status cs;-
1245-
1246 for (pnode = &temphead; (node = *pnode)->name != name; pnode = &node->next)
(node = *pnode)->name != nameDescription
TRUEevaluated 11174 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 2371 times by 1 test
Evaluated by:
  • sort
2371-11174
1247 continue;
executed 11174 times by 1 test: continue;
Executed by:
  • sort
11174
1248-
1249 if (node->state == UNREAPED)
node->state == UNREAPEDDescription
TRUEevaluated 1847 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 524 times by 1 test
Evaluated by:
  • sort
524-1847
1250 wait_proc (node->pid);
executed 1847 times by 1 test: wait_proc (node->pid);
Executed by:
  • sort
1847
1251-
1252 /* Unlink the temporary file in a critical section to avoid races. */-
1253 next = node->next;-
1254 cs_enter (&cs);-
1255 unlink_status = unlink (name);-
1256 unlink_errno = errno;-
1257 *pnode = next;-
1258 cs_leave (&cs);-
1259-
1260 if (unlink_status != 0)
unlink_status != 0Description
TRUEnever evaluated
FALSEevaluated 2370 times by 1 test
Evaluated by:
  • sort
0-2370
1261 error (0, unlink_errno, _("warning: cannot remove: %s"), quotef (name));
never executed: error (0, unlink_errno, dcgettext (((void *)0), "warning: cannot remove: %s" , 5) , quotearg_n_style_colon (0, shell_escape_quoting_style, name));
0
1262 if (! next)
! nextDescription
TRUEevaluated 117 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 2253 times by 1 test
Evaluated by:
  • sort
117-2253
1263 temptail = pnode;
executed 117 times by 1 test: temptail = pnode;
Executed by:
  • sort
117
1264 free (node);-
1265}
executed 2370 times by 1 test: end of block
Executed by:
  • sort
2370
1266-
1267#if HAVE_NL_LANGINFO-
1268-
1269static int-
1270struct_month_cmp (void const *m1, void const *m2)-
1271{-
1272 struct month const *month1 = m1;-
1273 struct month const *month2 = m2;-
1274 return strcmp (month1->name, month2->name);
executed 60 times by 1 test: return __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p ( month1->name ) && __builtin_constant_p ( month2->name ) && (__s1_len = __builtin_strlen ( month1->name ), __s2_len = __builtin_strlen ( month2->name ), (!((size_t)(const void *)(( ... char *) (const char *) ( month2->name ))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ( month2->name ))[3] - __s2[3]); } } __result; }))) : __builtin_strcmp ( month1->name , month2->name )))); }) ;
Executed by:
  • sort
never executed: __result = (((const unsigned char *) (const char *) ( month1->name ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( month2->name ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-60
1275}-
1276-
1277#endif-
1278-
1279/* Initialize the character class tables. */-
1280-
1281static void-
1282inittables (void)-
1283{-
1284 size_t i;-
1285-
1286 for (i = 0; i < UCHAR_LIM; ++i)
i < ( (0x7f * 2 + 1) + 1)Description
TRUEevaluated 219904 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 859 times by 1 test
Evaluated by:
  • sort
859-219904
1287 {-
1288 blanks[i] = field_sep (i);-
1289 nonprinting[i] = ! isprint (i);-
1290 nondictionary[i] = ! isalnum (i) && ! field_sep (i);
! ((*__ctype_b...int) _ISalnum)Description
TRUEevaluated 166646 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 53258 times by 1 test
Evaluated by:
  • sort
! field_sep (i)Description
TRUEevaluated 164069 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 2577 times by 1 test
Evaluated by:
  • sort
2577-166646
1291 fold_toupper[i] = toupper (i);
never executed: end of block
executed 219904 times by 1 test: __res = toupper ( i );
Executed by:
  • sort
never executed: __res = (*__ctype_toupper_loc ())[(int) ( i )];
sizeof ( i ) > 1Description
TRUEevaluated 219904 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
__builtin_constant_p ( i )Description
TRUEnever evaluated
FALSEevaluated 219904 times by 1 test
Evaluated by:
  • sort
__c < -128Description
TRUEnever evaluated
FALSEnever evaluated
__c > 255Description
TRUEnever evaluated
FALSEnever evaluated
0-219904
1292 }
executed 219904 times by 1 test: end of block
Executed by:
  • sort
219904
1293-
1294#if HAVE_NL_LANGINFO-
1295 /* If we're not in the "C" locale, read different names for months. */-
1296 if (hard_LC_TIME)
hard_LC_TIMEDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 857 times by 1 test
Evaluated by:
  • sort
2-857
1297 {-
1298 for (i = 0; i < MONTHS_PER_YEAR; i++)
i < 12Description
TRUEevaluated 24 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 2 times by 1 test
Evaluated by:
  • sort
2-24
1299 {-
1300 char const *s;-
1301 size_t s_len;-
1302 size_t j, k;-
1303 char *name;-
1304-
1305 s = nl_langinfo (ABMON_1 + i);-
1306 s_len = strlen (s);-
1307 monthtab[i].name = name = xmalloc (s_len + 1);-
1308 monthtab[i].val = i + 1;-
1309-
1310 for (j = k = 0; j < s_len; j++)
j < s_lenDescription
TRUEevaluated 72 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 24 times by 1 test
Evaluated by:
  • sort
24-72
1311 if (! isblank (to_uchar (s[j])))
! ((*__ctype_b...int) _ISblank)Description
TRUEevaluated 72 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-72
1312 name[k++] = fold_toupper[to_uchar (s[j])];
executed 72 times by 1 test: name[k++] = fold_toupper[to_uchar (s[j])];
Executed by:
  • sort
72
1313 name[k] = '\0';-
1314 }
executed 24 times by 1 test: end of block
Executed by:
  • sort
24
1315 qsort (monthtab, MONTHS_PER_YEAR, sizeof *monthtab, struct_month_cmp);-
1316 }
executed 2 times by 1 test: end of block
Executed by:
  • sort
2
1317#endif-
1318}
executed 859 times by 1 test: end of block
Executed by:
  • sort
859
1319-
1320/* Specify how many inputs may be merged at once.-
1321 This may be set on the command-line with the-
1322 --batch-size option. */-
1323static void-
1324specify_nmerge (int oi, char c, char const *s)-
1325{-
1326 uintmax_t n;-
1327 struct rlimit rlimit;-
1328 enum strtol_error e = xstrtoumax (s, NULL, 10, &n, NULL);-
1329-
1330 /* Try to find out how many file descriptors we'll be able-
1331 to open. We need at least nmerge + 3 (STDIN_FILENO,-
1332 STDOUT_FILENO and STDERR_FILENO). */-
1333 unsigned int max_nmerge = ((getrlimit (RLIMIT_NOFILE, &rlimit) == 0
getrlimit ( RL... &rlimit) == 0Description
TRUEevaluated 14 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-14
1334 ? rlimit.rlim_cur-
1335 : OPEN_MAX)-
1336 - 3);-
1337-
1338 if (e == LONGINT_OK)
e == LONGINT_OKDescription
TRUEevaluated 11 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 3 times by 1 test
Evaluated by:
  • sort
3-11
1339 {-
1340 nmerge = n;-
1341 if (nmerge != n)
nmerge != nDescription
TRUEnever evaluated
FALSEevaluated 11 times by 1 test
Evaluated by:
  • sort
0-11
1342 e = LONGINT_OVERFLOW;
never executed: e = LONGINT_OVERFLOW;
0
1343 else-
1344 {-
1345 if (nmerge < 2)
nmerge < 2Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 9 times by 1 test
Evaluated by:
  • sort
2-9
1346 {-
1347 error (0, 0, _("invalid --%s argument %s"),-
1348 long_options[oi].name, quote (s));-
1349 die (SORT_FAILURE, 0,-
1350 _("minimum --%s argument is %s"),-
1351 long_options[oi].name, quote ("2"));-
1352 }
never executed: end of block
0
1353 else if (max_nmerge < nmerge)
max_nmerge < nmergeDescription
TRUEnever evaluated
FALSEevaluated 9 times by 1 test
Evaluated by:
  • sort
0-9
1354 {-
1355 e = LONGINT_OVERFLOW;-
1356 }
never executed: end of block
0
1357 else-
1358 return;
executed 9 times by 1 test: return;
Executed by:
  • sort
9
1359 }-
1360 }-
1361-
1362 if (e == LONGINT_OVERFLOW)
e == LONGINT_OVERFLOWDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • sort
FALSEevaluated 2 times by 1 test
Evaluated by:
  • sort
1-2
1363 {-
1364 char max_nmerge_buf[INT_BUFSIZE_BOUND (max_nmerge)];-
1365 error (0, 0, _("--%s argument %s too large"),-
1366 long_options[oi].name, quote (s));-
1367 die (SORT_FAILURE, 0,-
1368 _("maximum --%s argument with current rlimit is %s"),-
1369 long_options[oi].name,-
1370 uinttostr (max_nmerge, max_nmerge_buf));-
1371 }
never executed: end of block
0
1372 else-
1373 xstrtol_fatal (e, oi, c, long_options, s);
executed 2 times by 1 test: xstrtol_fatal (e, oi, c, long_options, s);
Executed by:
  • sort
2
1374}-
1375-
1376/* Specify the amount of main memory to use when sorting. */-
1377static void-
1378specify_sort_size (int oi, char c, char const *s)-
1379{-
1380 uintmax_t n;-
1381 char *suffix;-
1382 enum strtol_error e = xstrtoumax (s, &suffix, 10, &n, "EgGkKmMPtTYZ");-
1383-
1384 /* The default unit is KiB. */-
1385 if (e == LONGINT_OK && ISDIGIT (suffix[-1]))
e == LONGINT_OKDescription
TRUEevaluated 15 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 13 times by 1 test
Evaluated by:
  • sort
((unsigned int...]) - '0' <= 9)Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 9 times by 1 test
Evaluated by:
  • sort
6-15
1386 {-
1387 if (n <= UINTMAX_MAX / 1024)
n <= (18446744...1615UL) / 1024Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-6
1388 n *= 1024;
executed 6 times by 1 test: n *= 1024;
Executed by:
  • sort
6
1389 else-
1390 e = LONGINT_OVERFLOW;
never executed: e = LONGINT_OVERFLOW;
0
1391 }-
1392-
1393 /* A 'b' suffix means bytes; a '%' suffix means percent of memory. */-
1394 if (e == LONGINT_INVALID_SUFFIX_CHAR && ISDIGIT (suffix[-1]) && ! suffix[1])
e == LONGINT_I...ID_SUFFIX_CHARDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 15 times by 1 test
Evaluated by:
  • sort
((unsigned int...]) - '0' <= 9)Description
TRUEevaluated 13 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
! suffix[1]Description
TRUEevaluated 13 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-15
1395 switch (suffix[0])-
1396 {-
1397 case 'b':
executed 13 times by 1 test: case 'b':
Executed by:
  • sort
13
1398 e = LONGINT_OK;-
1399 break;
executed 13 times by 1 test: break;
Executed by:
  • sort
13
1400-
1401 case '%':
never executed: case '%':
0
1402 {-
1403 double mem = physmem_total () * n / 100;-
1404-
1405 /* Use "<", not "<=", to avoid problems with rounding. */-
1406 if (mem < UINTMAX_MAX)
mem < (18446744073709551615UL)Description
TRUEnever evaluated
FALSEnever evaluated
0
1407 {-
1408 n = mem;-
1409 e = LONGINT_OK;-
1410 }
never executed: end of block
0
1411 else-
1412 e = LONGINT_OVERFLOW;
never executed: e = LONGINT_OVERFLOW;
0
1413 }-
1414 break;
never executed: break;
0
1415 }
never executed: end of block
0
1416-
1417 if (e == LONGINT_OK)
e == LONGINT_OKDescription
TRUEevaluated 28 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-28
1418 {-
1419 /* If multiple sort sizes are specified, take the maximum, so-
1420 that option order does not matter. */-
1421 if (n < sort_size)
n < sort_sizeDescription
TRUEnever evaluated
FALSEevaluated 28 times by 1 test
Evaluated by:
  • sort
0-28
1422 return;
never executed: return;
0
1423-
1424 sort_size = n;-
1425 if (sort_size == n)
sort_size == nDescription
TRUEevaluated 28 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-28
1426 {-
1427 sort_size = MAX (sort_size, MIN_SORT_SIZE);
(( sort_size )...uct line))) ))Description
TRUEevaluated 15 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 13 times by 1 test
Evaluated by:
  • sort
13-15
1428 return;
executed 28 times by 1 test: return;
Executed by:
  • sort
28
1429 }-
1430-
1431 e = LONGINT_OVERFLOW;-
1432 }
never executed: end of block
0
1433-
1434 xstrtol_fatal (e, oi, c, long_options, s);-
1435}
never executed: end of block
0
1436-
1437/* Specify the number of threads to spawn during internal sort. */-
1438static size_t-
1439specify_nthreads (int oi, char c, char const *s)-
1440{-
1441 unsigned long int nthreads;-
1442 enum strtol_error e = xstrtoul (s, NULL, 10, &nthreads, "");-
1443 if (e == LONGINT_OVERFLOW)
e == LONGINT_OVERFLOWDescription
TRUEnever evaluated
FALSEevaluated 14 times by 1 test
Evaluated by:
  • sort
0-14
1444 return SIZE_MAX;
never executed: return (18446744073709551615UL) ;
0
1445 if (e != LONGINT_OK)
e != LONGINT_OKDescription
TRUEnever evaluated
FALSEevaluated 14 times by 1 test
Evaluated by:
  • sort
0-14
1446 xstrtol_fatal (e, oi, c, long_options, s);
never executed: xstrtol_fatal (e, oi, c, long_options, s);
0
1447 if (SIZE_MAX < nthreads)
(1844674407370...UL) < nthreadsDescription
TRUEnever evaluated
FALSEevaluated 14 times by 1 test
Evaluated by:
  • sort
0-14
1448 nthreads = SIZE_MAX;
never executed: nthreads = (18446744073709551615UL) ;
0
1449 if (nthreads == 0)
nthreads == 0Description
TRUEnever evaluated
FALSEevaluated 14 times by 1 test
Evaluated by:
  • sort
0-14
1450 die (SORT_FAILURE, 0, _("number in parallel must be nonzero"));
never executed: ((!!sizeof (struct { _Static_assert (SORT_FAILURE, "verify_expr (" "SORT_FAILURE" ", " "(error (SORT_FAILURE, 0, dcgettext (((void *)0), \"number in parallel must be nonzero\", 5)), assume (false))" ")"); int _gl_dummy; })) ? ((error (SORT_FAILURE, 0, dcg...t (((void *)0), "number in parallel must be nonzero" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))) : ((error (SORT_FAILURE, 0, dcgettext (((void *)0), "number in parallel must be nonzero" , 5) ), (( 0 ) ? (void) 0 : __builtin_unreachable ()))));
0
1451 return nthreads;
executed 14 times by 1 test: return nthreads;
Executed by:
  • sort
14
1452}-
1453-
1454/* Return the default sort size. */-
1455static size_t-
1456default_sort_size (void)-
1457{-
1458 /* Let SIZE be MEM, but no more than the maximum object size,-
1459 total memory, or system resource limits. Don't bother to check-
1460 for values like RLIM_INFINITY since in practice they are not much-
1461 less than SIZE_MAX. */-
1462 size_t size = SIZE_MAX;-
1463 struct rlimit rlimit;-
1464 if (getrlimit (RLIMIT_DATA, &rlimit) == 0 && rlimit.rlim_cur < size)
getrlimit ( RL... &rlimit) == 0Description
TRUEevaluated 685 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
rlimit.rlim_cur < sizeDescription
TRUEnever evaluated
FALSEevaluated 685 times by 1 test
Evaluated by:
  • sort
0-685
1465 size = rlimit.rlim_cur;
never executed: size = rlimit.rlim_cur;
0
1466#ifdef RLIMIT_AS-
1467 if (getrlimit (RLIMIT_AS, &rlimit) == 0 && rlimit.rlim_cur < size)
getrlimit ( RL... &rlimit) == 0Description
TRUEevaluated 685 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
rlimit.rlim_cur < sizeDescription
TRUEnever evaluated
FALSEevaluated 685 times by 1 test
Evaluated by:
  • sort
0-685
1468 size = rlimit.rlim_cur;
never executed: size = rlimit.rlim_cur;
0
1469#endif-
1470-
1471 /* Leave a large safety margin for the above limits, as failure can-
1472 occur when they are exceeded. */-
1473 size /= 2;-
1474-
1475#ifdef RLIMIT_RSS-
1476 /* Leave a 1/16 margin for RSS to leave room for code, stack, etc.-
1477 Exceeding RSS is not fatal, but can be quite slow. */-
1478 if (getrlimit (RLIMIT_RSS, &rlimit) == 0 && rlimit.rlim_cur / 16 * 15 < size)
getrlimit ( __... &rlimit) == 0Description
TRUEevaluated 685 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
rlimit.rlim_cu...16 * 15 < sizeDescription
TRUEnever evaluated
FALSEevaluated 685 times by 1 test
Evaluated by:
  • sort
0-685
1479 size = rlimit.rlim_cur / 16 * 15;
never executed: size = rlimit.rlim_cur / 16 * 15;
0
1480#endif-
1481-
1482 /* Let MEM be available memory or 1/8 of total memory, whichever-
1483 is greater. */-
1484 double avail = physmem_available ();-
1485 double total = physmem_total ();-
1486 double mem = MAX (avail, total / 8);
(( avail )>( total / 8 ))Description
TRUEevaluated 600 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 85 times by 1 test
Evaluated by:
  • sort
85-600
1487-
1488 /* Leave a 1/4 margin for physical memory. */-
1489 if (total * 0.75 < size)
total * 0.75 < sizeDescription
TRUEevaluated 685 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-685
1490 size = total * 0.75;
executed 685 times by 1 test: size = total * 0.75;
Executed by:
  • sort
685
1491-
1492 /* Return the minimum of MEM and SIZE, but no less than-
1493 MIN_SORT_SIZE. Avoid the MIN macro here, as it is not quite-
1494 right when only one argument is floating point. */-
1495 if (mem < size)
mem < sizeDescription
TRUEevaluated 685 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-685
1496 size = mem;
executed 685 times by 1 test: size = mem;
Executed by:
  • sort
685
1497 return MAX (size, MIN_SORT_SIZE);
executed 685 times by 1 test: return ((( size )>( (nmerge * (2 + sizeof (struct line))) ))?( size ):( (nmerge * (2 + sizeof (struct line))) )) ;
Executed by:
  • sort
685
1498}-
1499-
1500/* Return the sort buffer size to use with the input files identified-
1501 by FPS and FILES, which are alternate names of the same files.-
1502 NFILES gives the number of input files; NFPS may be less. Assume-
1503 that each input line requires LINE_BYTES extra bytes' worth of line-
1504 information. Do not exceed the size bound specified by the user-
1505 (or a default size bound, if the user does not specify one). */-
1506-
1507static size_t-
1508sort_buffer_size (FILE *const *fps, size_t nfps,-
1509 char *const *files, size_t nfiles,-
1510 size_t line_bytes)-
1511{-
1512 /* A bound on the input size. If zero, the bound hasn't been-
1513 determined yet. */-
1514 static size_t size_bound;-
1515-
1516 /* In the worst case, each input byte is a newline. */-
1517 size_t worst_case_per_input_byte = line_bytes + 1;-
1518-
1519 /* Keep enough room for one extra input line and an extra byte.-
1520 This extra room might be needed when preparing to read EOF. */-
1521 size_t size = worst_case_per_input_byte + 1;-
1522-
1523 for (size_t i = 0; i < nfiles; i++)
i < nfilesDescription
TRUEevaluated 715 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 687 times by 1 test
Evaluated by:
  • sort
687-715
1524 {-
1525 struct stat st;-
1526 off_t file_size;-
1527 size_t worst_case;-
1528-
1529 if ((i < nfps ? fstat (fileno (fps[i]), &st)
(i < nfps ? fs...i], &st)) != 0Description
TRUEnever evaluated
FALSEevaluated 715 times by 1 test
Evaluated by:
  • sort
i < nfpsDescription
TRUEevaluated 713 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 2 times by 1 test
Evaluated by:
  • sort
0-715
1530 : STREQ (files[i], "-") ? fstat (STDIN_FILENO, &st)
never executed: __result = (((const unsigned char *) (const char *) ( files[i] ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( "-" ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
(i < nfps ? fs...i], &st)) != 0Description
TRUEnever evaluated
FALSEevaluated 715 times by 1 test
Evaluated by:
  • sort
( __extension_...)))); }) == 0)Description
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • sort
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • sort
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-715
1531 : stat (files[i], &st))
(i < nfps ? fs...i], &st)) != 0Description
TRUEnever evaluated
FALSEevaluated 715 times by 1 test
Evaluated by:
  • sort
0-715
1532 != 0)
(i < nfps ? fs...i], &st)) != 0Description
TRUEnever evaluated
FALSEevaluated 715 times by 1 test
Evaluated by:
  • sort
0-715
1533 sort_die (_("stat failed"), files[i]);
never executed: sort_die ( dcgettext (((void *)0), "stat failed" , 5) , files[i]);
0
1534-
1535 if (S_ISREG (st.st_mode))
(((( st.st_mod... == (0100000))Description
TRUEevaluated 296 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 419 times by 1 test
Evaluated by:
  • sort
296-419
1536 file_size = st.st_size;
executed 296 times by 1 test: file_size = st.st_size;
Executed by:
  • sort
296
1537 else-
1538 {-
1539 /* The file has unknown size. If the user specified a sort-
1540 buffer size, use that; otherwise, guess the size. */-
1541 if (sort_size)
sort_sizeDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 413 times by 1 test
Evaluated by:
  • sort
6-413
1542 return sort_size;
executed 6 times by 1 test: return sort_size;
Executed by:
  • sort
6
1543 file_size = INPUT_FILE_SIZE_GUESS;-
1544 }
executed 413 times by 1 test: end of block
Executed by:
  • sort
413
1545-
1546 if (! size_bound)
! size_boundDescription
TRUEevaluated 707 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 2 times by 1 test
Evaluated by:
  • sort
2-707
1547 {-
1548 size_bound = sort_size;-
1549 if (! size_bound)
! size_boundDescription
TRUEevaluated 685 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 22 times by 1 test
Evaluated by:
  • sort
22-685
1550 size_bound = default_sort_size ();
executed 685 times by 1 test: size_bound = default_sort_size ();
Executed by:
  • sort
685
1551 }
executed 707 times by 1 test: end of block
Executed by:
  • sort
707
1552-
1553 /* Add the amount of memory needed to represent the worst case-
1554 where the input consists entirely of newlines followed by a-
1555 single non-newline. Check for overflow. */-
1556 worst_case = file_size * worst_case_per_input_byte + 1;-
1557 if (file_size != worst_case / worst_case_per_input_byte
file_size != w...per_input_byteDescription
TRUEnever evaluated
FALSEevaluated 709 times by 1 test
Evaluated by:
  • sort
0-709
1558 || size_bound - size <= worst_case)
size_bound - s... <= worst_caseDescription
TRUEevaluated 20 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 689 times by 1 test
Evaluated by:
  • sort
20-689
1559 return size_bound;
executed 20 times by 1 test: return size_bound;
Executed by:
  • sort
20
1560 size += worst_case;-
1561 }
executed 689 times by 1 test: end of block
Executed by:
  • sort
689
1562-
1563 return size;
executed 687 times by 1 test: return size;
Executed by:
  • sort
687
1564}-
1565-
1566/* Initialize BUF. Reserve LINE_BYTES bytes for each line; LINE_BYTES-
1567 must be at least sizeof (struct line). Allocate ALLOC bytes-
1568 initially. */-
1569-
1570static void-
1571initbuf (struct buffer *buf, size_t line_bytes, size_t alloc)-
1572{-
1573 /* Ensure that the line array is properly aligned. If the desired-
1574 size cannot be allocated, repeatedly halve it until allocation-
1575 succeeds. The smaller allocation may hurt overall performance,-
1576 but that's better than failing. */-
1577 while (true)-
1578 {-
1579 alloc += sizeof (struct line) - alloc % sizeof (struct line);-
1580 buf->buf = malloc (alloc);-
1581 if (buf->buf)
buf->bufDescription
TRUEevaluated 3270 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-3270
1582 break;
executed 3270 times by 1 test: break;
Executed by:
  • sort
3270
1583 alloc /= 2;-
1584 if (alloc <= line_bytes + 1)
alloc <= line_bytes + 1Description
TRUEnever evaluated
FALSEnever evaluated
0
1585 xalloc_die ();
never executed: xalloc_die ();
0
1586 }
never executed: end of block
0
1587-
1588 buf->line_bytes = line_bytes;-
1589 buf->alloc = alloc;-
1590 buf->used = buf->left = buf->nlines = 0;-
1591 buf->eof = false;-
1592}
executed 3270 times by 1 test: end of block
Executed by:
  • sort
3270
1593-
1594/* Return one past the limit of the line array. */-
1595-
1596static inline struct line *-
1597buffer_linelim (struct buffer const *buf)-
1598{-
1599 void *linelim = buf->buf + buf->alloc;-
1600 return linelim;
executed 15152 times by 1 test: return linelim;
Executed by:
  • sort
15152
1601}-
1602-
1603/* Return a pointer to the first character of the field specified-
1604 by KEY in LINE. */-
1605-
1606static char *-
1607begfield (struct line const *line, struct keyfield const *key)-
1608{-
1609 char *ptr = line->text, *lim = ptr + line->length - 1;-
1610 size_t sword = key->sword;-
1611 size_t schar = key->schar;-
1612-
1613 /* The leading field separator itself is included in a field when -t-
1614 is absent. */-
1615-
1616 if (tab != TAB_DEFAULT)
tab != TAB_DEFAULTDescription
TRUEevaluated 72 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 447 times by 1 test
Evaluated by:
  • sort
72-447
1617 while (ptr < lim && sword--)
ptr < limDescription
TRUEevaluated 138 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
sword--Description
TRUEevaluated 66 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 72 times by 1 test
Evaluated by:
  • sort
0-138
1618 {-
1619 while (ptr < lim && *ptr != tab)
ptr < limDescription
TRUEevaluated 114 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
*ptr != tabDescription
TRUEevaluated 48 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 66 times by 1 test
Evaluated by:
  • sort
0-114
1620 ++ptr;
executed 48 times by 1 test: ++ptr;
Executed by:
  • sort
48
1621 if (ptr < lim)
ptr < limDescription
TRUEevaluated 66 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-66
1622 ++ptr;
executed 66 times by 1 test: ++ptr;
Executed by:
  • sort
66
1623 }
executed 66 times by 1 test: end of block
Executed by:
  • sort
66
1624 else-
1625 while (ptr < lim && sword--)
ptr < limDescription
TRUEevaluated 750 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 58 times by 1 test
Evaluated by:
  • sort
sword--Description
TRUEevaluated 361 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 389 times by 1 test
Evaluated by:
  • sort
58-750
1626 {-
1627 while (ptr < lim && blanks[to_uchar (*ptr)])
ptr < limDescription
TRUEevaluated 532 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
blanks[to_uchar (*ptr)]Description
TRUEevaluated 171 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 361 times by 1 test
Evaluated by:
  • sort
0-532
1628 ++ptr;
executed 171 times by 1 test: ++ptr;
Executed by:
  • sort
171
1629 while (ptr < lim && !blanks[to_uchar (*ptr)])
ptr < limDescription
TRUEevaluated 752 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 42 times by 1 test
Evaluated by:
  • sort
!blanks[to_uchar (*ptr)]Description
TRUEevaluated 433 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 319 times by 1 test
Evaluated by:
  • sort
42-752
1630 ++ptr;
executed 433 times by 1 test: ++ptr;
Executed by:
  • sort
433
1631 }
executed 361 times by 1 test: end of block
Executed by:
  • sort
361
1632-
1633 /* If we're ignoring leading blanks when computing the Start-
1634 of the field, skip past them here. */-
1635 if (key->skipsblanks)
key->skipsblanksDescription
TRUEevaluated 28 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 491 times by 1 test
Evaluated by:
  • sort
28-491
1636 while (ptr < lim && blanks[to_uchar (*ptr)])
ptr < limDescription
TRUEevaluated 61 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
blanks[to_uchar (*ptr)]Description
TRUEevaluated 33 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 28 times by 1 test
Evaluated by:
  • sort
0-61
1637 ++ptr;
executed 33 times by 1 test: ++ptr;
Executed by:
  • sort
33
1638-
1639 /* Advance PTR by SCHAR (if possible), but no further than LIM. */-
1640 ptr = MIN (lim, ptr + schar);
(( lim )<( ptr + schar ))Description
TRUEevaluated 18 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 501 times by 1 test
Evaluated by:
  • sort
18-501
1641-
1642 return ptr;
executed 519 times by 1 test: return ptr;
Executed by:
  • sort
519
1643}-
1644-
1645/* Return the limit of (a pointer to the first character after) the field-
1646 in LINE specified by KEY. */-
1647-
1648static char *-
1649limfield (struct line const *line, struct keyfield const *key)-
1650{-
1651 char *ptr = line->text, *lim = ptr + line->length - 1;-
1652 size_t eword = key->eword, echar = key->echar;-
1653-
1654 if (echar == 0)
echar == 0Description
TRUEevaluated 520 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 160 times by 1 test
Evaluated by:
  • sort
160-520
1655 eword++; /* Skip all of end field. */
executed 520 times by 1 test: eword++;
Executed by:
  • sort
520
1656-
1657 /* Move PTR past EWORD fields or to one past the last byte on LINE,-
1658 whichever comes first. If there are more than EWORD fields, leave-
1659 PTR pointing at the beginning of the field having zero-based index,-
1660 EWORD. If a delimiter character was specified (via -t), then that-
1661 'beginning' is the first character following the delimiting TAB.-
1662 Otherwise, leave PTR pointing at the first 'blank' character after-
1663 the preceding field. */-
1664 if (tab != TAB_DEFAULT)
tab != TAB_DEFAULTDescription
TRUEevaluated 66 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 614 times by 1 test
Evaluated by:
  • sort
66-614
1665 while (ptr < lim && eword--)
ptr < limDescription
TRUEevaluated 132 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 12 times by 1 test
Evaluated by:
  • sort
eword--Description
TRUEevaluated 78 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 54 times by 1 test
Evaluated by:
  • sort
12-132
1666 {-
1667 while (ptr < lim && *ptr != tab)
ptr < limDescription
TRUEevaluated 168 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 12 times by 1 test
Evaluated by:
  • sort
*ptr != tabDescription
TRUEevaluated 102 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 66 times by 1 test
Evaluated by:
  • sort
12-168
1668 ++ptr;
executed 102 times by 1 test: ++ptr;
Executed by:
  • sort
102
1669 if (ptr < lim && (eword || echar))
ptr < limDescription
TRUEevaluated 66 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 12 times by 1 test
Evaluated by:
  • sort
ewordDescription
TRUEevaluated 18 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 48 times by 1 test
Evaluated by:
  • sort
echarDescription
TRUEevaluated 24 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 24 times by 1 test
Evaluated by:
  • sort
12-66
1670 ++ptr;
executed 42 times by 1 test: ++ptr;
Executed by:
  • sort
42
1671 }
executed 78 times by 1 test: end of block
Executed by:
  • sort
78
1672 else-
1673 while (ptr < lim && eword--)
ptr < limDescription
TRUEevaluated 1055 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 376 times by 1 test
Evaluated by:
  • sort
eword--Description
TRUEevaluated 817 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 238 times by 1 test
Evaluated by:
  • sort
238-1055
1674 {-
1675 while (ptr < lim && blanks[to_uchar (*ptr)])
ptr < limDescription
TRUEevaluated 1290 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 4 times by 1 test
Evaluated by:
  • sort
blanks[to_uchar (*ptr)]Description
TRUEevaluated 477 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 813 times by 1 test
Evaluated by:
  • sort
4-1290
1676 ++ptr;
executed 477 times by 1 test: ++ptr;
Executed by:
  • sort
477
1677 while (ptr < lim && !blanks[to_uchar (*ptr)])
ptr < limDescription
TRUEevaluated 1794 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 372 times by 1 test
Evaluated by:
  • sort
!blanks[to_uchar (*ptr)]Description
TRUEevaluated 1349 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 445 times by 1 test
Evaluated by:
  • sort
372-1794
1678 ++ptr;
executed 1349 times by 1 test: ++ptr;
Executed by:
  • sort
1349
1679 }
executed 817 times by 1 test: end of block
Executed by:
  • sort
817
1680-
1681#ifdef POSIX_UNSPECIFIED-
1682 /* The following block of code makes GNU sort incompatible with-
1683 standard Unix sort, so it's ifdef'd out for now.-
1684 The POSIX spec isn't clear on how to interpret this.-
1685 FIXME: request clarification.-
1686-
1687 From: kwzh@gnu.ai.mit.edu (Karl Heuer)-
1688 Date: Thu, 30 May 96 12:20:41 -0400-
1689 [Translated to POSIX 1003.1-2001 terminology by Paul Eggert.]-
1690-
1691 [...]I believe I've found another bug in 'sort'.-
1692-
1693 $ cat /tmp/sort.in-
1694 a b c 2 d-
1695 pq rs 1 t-
1696 $ textutils-1.15/src/sort -k1.7,1.7 </tmp/sort.in-
1697 a b c 2 d-
1698 pq rs 1 t-
1699 $ /bin/sort -k1.7,1.7 </tmp/sort.in-
1700 pq rs 1 t-
1701 a b c 2 d-
1702-
1703 Unix sort produced the answer I expected: sort on the single character-
1704 in column 7. GNU sort produced different results, because it disagrees-
1705 on the interpretation of the key-end spec "M.N". Unix sort reads this-
1706 as "skip M-1 fields, then N-1 characters"; but GNU sort wants it to mean-
1707 "skip M-1 fields, then either N-1 characters or the rest of the current-
1708 field, whichever comes first". This extra clause applies only to-
1709 key-ends, not key-starts.-
1710 */-
1711-
1712 /* Make LIM point to the end of (one byte past) the current field. */-
1713 if (tab != TAB_DEFAULT)-
1714 {-
1715 char *newlim;-
1716 newlim = memchr (ptr, tab, lim - ptr);-
1717 if (newlim)-
1718 lim = newlim;-
1719 }-
1720 else-
1721 {-
1722 char *newlim;-
1723 newlim = ptr;-
1724 while (newlim < lim && blanks[to_uchar (*newlim)])-
1725 ++newlim;-
1726 while (newlim < lim && !blanks[to_uchar (*newlim)])-
1727 ++newlim;-
1728 lim = newlim;-
1729 }-
1730#endif-
1731-
1732 if (echar != 0) /* We need to skip over a portion of the end field. */
echar != 0Description
TRUEevaluated 160 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 520 times by 1 test
Evaluated by:
  • sort
160-520
1733 {-
1734 /* If we're ignoring leading blanks when computing the End-
1735 of the field, skip past them here. */-
1736 if (key->skipeblanks)
key->skipeblanksDescription
TRUEevaluated 24 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 136 times by 1 test
Evaluated by:
  • sort
24-136
1737 while (ptr < lim && blanks[to_uchar (*ptr)])
ptr < limDescription
TRUEevaluated 42 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
blanks[to_uchar (*ptr)]Description
TRUEevaluated 18 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 24 times by 1 test
Evaluated by:
  • sort
0-42
1738 ++ptr;
executed 18 times by 1 test: ++ptr;
Executed by:
  • sort
18
1739-
1740 /* Advance PTR by ECHAR (if possible), but no further than LIM. */-
1741 ptr = MIN (lim, ptr + echar);
(( lim )<( ptr + echar ))Description
TRUEnever evaluated
FALSEevaluated 160 times by 1 test
Evaluated by:
  • sort
0-160
1742 }
executed 160 times by 1 test: end of block
Executed by:
  • sort
160
1743-
1744 return ptr;
executed 680 times by 1 test: return ptr;
Executed by:
  • sort
680
1745}-
1746-
1747/* Fill BUF reading from FP, moving buf->left bytes from the end-
1748 of buf->buf to the beginning first. If EOF is reached and the-
1749 file wasn't terminated by a newline, supply one. Set up BUF's line-
1750 table too. FILE is the name of the file corresponding to FP.-
1751 Return true if some input was read. */-
1752-
1753static bool-
1754fillbuf (struct buffer *buf, FILE *fp, char const *file)-
1755{-
1756 struct keyfield const *key = keylist;-
1757 char eol = eolchar;-
1758 size_t line_bytes = buf->line_bytes;-
1759 size_t mergesize = merge_buffer_size - MIN_MERGE_BUFFER_SIZE;-
1760-
1761 if (buf->eof)
buf->eofDescription
TRUEevaluated 2545 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 5086 times by 1 test
Evaluated by:
  • sort
2545-5086
1762 return false;
executed 2545 times by 1 test: return 0 ;
Executed by:
  • sort
2545
1763-
1764 if (buf->used != buf->left)
buf->used != buf->leftDescription
TRUEevaluated 1814 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 3272 times by 1 test
Evaluated by:
  • sort
1814-3272
1765 {-
1766 memmove (buf->buf, buf->buf + buf->used - buf->left, buf->left);-
1767 buf->used = buf->left;-
1768 buf->nlines = 0;-
1769 }
executed 1814 times by 1 test: end of block
Executed by:
  • sort
1814
1770-
1771 while (true)-
1772 {-
1773 char *ptr = buf->buf + buf->used;-
1774 struct line *linelim = buffer_linelim (buf);-
1775 struct line *line = linelim - buf->nlines;-
1776 size_t avail = (char *) linelim - buf->nlines * line_bytes - ptr;-
1777 char *line_start = buf->nlines ? line->text + line->length : buf->buf;
buf->nlinesDescription
TRUEevaluated 2 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 5102 times by 1 test
Evaluated by:
  • sort
2-5102
1778-
1779 while (line_bytes + 1 < avail)
line_bytes + 1 < availDescription
TRUEevaluated 32863 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1832 times by 1 test
Evaluated by:
  • sort
1832-32863
1780 {-
1781 /* Read as many bytes as possible, but do not read so many-
1782 bytes that there might not be enough room for the-
1783 corresponding line array. The worst case is when the-
1784 rest of the input file consists entirely of newlines,-
1785 except that the last byte is not a newline. */-
1786 size_t readsize = (avail - 1) / (line_bytes + 1);-
1787 size_t bytes_read = fread (ptr, 1, readsize, fp);-
1788 char *ptrlim = ptr + bytes_read;-
1789 char *p;-
1790 avail -= bytes_read;-
1791-
1792 if (bytes_read != readsize)
bytes_read != readsizeDescription
TRUEevaluated 3272 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 29591 times by 1 test
Evaluated by:
  • sort
3272-29591
1793 {-
1794 if (ferror (fp))
ferror_unlocked (fp)Description
TRUEnever evaluated
FALSEevaluated 3272 times by 1 test
Evaluated by:
  • sort
0-3272
1795 sort_die (_("read failed"), file);
never executed: sort_die ( dcgettext (((void *)0), "read failed" , 5) , file);
0
1796 if (feof (fp))
feof_unlocked (fp)Description
TRUEevaluated 3272 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-3272
1797 {-
1798 buf->eof = true;-
1799 if (buf->buf == ptrlim)
buf->buf == ptrlimDescription
TRUEevaluated 76 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 3196 times by 1 test
Evaluated by:
  • sort
76-3196
1800 return false;
executed 76 times by 1 test: return 0 ;
Executed by:
  • sort
76
1801 if (line_start != ptrlim && ptrlim[-1] != eol)
line_start != ptrlimDescription
TRUEevaluated 3196 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
ptrlim[-1] != eolDescription
TRUEevaluated 9 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 3187 times by 1 test
Evaluated by:
  • sort
0-3196
1802 *ptrlim++ = eol;
executed 9 times by 1 test: *ptrlim++ = eol;
Executed by:
  • sort
9
1803 }
executed 3196 times by 1 test: end of block
Executed by:
  • sort
3196
1804 }
executed 3196 times by 1 test: end of block
Executed by:
  • sort
3196
1805-
1806 /* Find and record each line in the just-read input. */-
1807 while ((p = memchr (ptr, eol, ptrlim - ptr)))
(p = memchr (p...ptrlim - ptr))Description
TRUEevaluated 185424 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 32787 times by 1 test
Evaluated by:
  • sort
32787-185424
1808 {-
1809 /* Delimit the line with NUL. This eliminates the need to-
1810 temporarily replace the last byte with NUL when calling-
1811 xmemcoll, which increases performance. */-
1812 *p = '\0';-
1813 ptr = p + 1;-
1814 line--;-
1815 line->text = line_start;-
1816 line->length = ptr - line_start;-
1817 mergesize = MAX (mergesize, line->length);
(( mergesize )...ine->length ))Description
TRUEevaluated 185424 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-185424
1818 avail -= line_bytes;-
1819-
1820 if (key)
keyDescription
TRUEevaluated 95822 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 89602 times by 1 test
Evaluated by:
  • sort
89602-95822
1821 {-
1822 /* Precompute the position of the first key for-
1823 efficiency. */-
1824 line->keylim = (key->eword == SIZE_MAX
key->eword == ...73709551615UL)Description
TRUEevaluated 95182 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 640 times by 1 test
Evaluated by:
  • sort
640-95182
1825 ? p-
1826 : limfield (line, key));-
1827-
1828 if (key->sword != SIZE_MAX)
key->sword != ...73709551615UL)Description
TRUEevaluated 438 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 95384 times by 1 test
Evaluated by:
  • sort
438-95384
1829 line->keybeg = begfield (line, key);
executed 438 times by 1 test: line->keybeg = begfield (line, key);
Executed by:
  • sort
438
1830 else-
1831 {-
1832 if (key->skipsblanks)
key->skipsblanksDescription
TRUEevaluated 22 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 95362 times by 1 test
Evaluated by:
  • sort
22-95362
1833 while (blanks[to_uchar (*line_start)])
blanks[to_uchar (*line_start)]Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 22 times by 1 test
Evaluated by:
  • sort
8-22
1834 line_start++;
executed 8 times by 1 test: line_start++;
Executed by:
  • sort
8
1835 line->keybeg = line_start;-
1836 }
executed 95384 times by 1 test: end of block
Executed by:
  • sort
95384
1837 }-
1838-
1839 line_start = ptr;-
1840 }
executed 185424 times by 1 test: end of block
Executed by:
  • sort
185424
1841-
1842 ptr = ptrlim;-
1843 if (buf->eof)
buf->eofDescription
TRUEevaluated 3196 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 29591 times by 1 test
Evaluated by:
  • sort
3196-29591
1844 break;
executed 3196 times by 1 test: break;
Executed by:
  • sort
3196
1845 }
executed 29591 times by 1 test: end of block
Executed by:
  • sort
29591
1846-
1847 buf->used = ptr - buf->buf;-
1848 buf->nlines = buffer_linelim (buf) - line;-
1849 if (buf->nlines != 0)
buf->nlines != 0Description
TRUEevaluated 5010 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 18 times by 1 test
Evaluated by:
  • sort
18-5010
1850 {-
1851 buf->left = ptr - line_start;-
1852 merge_buffer_size = mergesize + MIN_MERGE_BUFFER_SIZE;-
1853 return true;
executed 5010 times by 1 test: return 1 ;
Executed by:
  • sort
5010
1854 }-
1855-
1856 {-
1857 /* The current input line is too long to fit in the buffer.-
1858 Increase the buffer size and try again, keeping it properly-
1859 aligned. */-
1860 size_t line_alloc = buf->alloc / sizeof (struct line);-
1861 buf->buf = x2nrealloc (buf->buf, &line_alloc, sizeof (struct line));-
1862 buf->alloc = line_alloc * sizeof (struct line);-
1863 }-
1864 }
executed 18 times by 1 test: end of block
Executed by:
  • sort
18
1865}
never executed: end of block
0
1866-
1867/* Table that maps characters to order-of-magnitude values. */-
1868static char const unit_order[UCHAR_LIM] =-
1869 {-
1870#if ! ('K' == 75 && 'M' == 77 && 'G' == 71 && 'T' == 84 && 'P' == 80 \-
1871 && 'E' == 69 && 'Z' == 90 && 'Y' == 89 && 'k' == 107)-
1872 /* This initializer syntax works on all C99 hosts. For now, use-
1873 it only on non-ASCII hosts, to ease the pain of porting to-
1874 pre-C99 ASCII hosts. */-
1875 ['K']=1, ['M']=2, ['G']=3, ['T']=4, ['P']=5, ['E']=6, ['Z']=7, ['Y']=8,-
1876 ['k']=1,-
1877#else-
1878 /* Generate the following table with this command:-
1879 perl -e 'my %a=(k=>1, K=>1, M=>2, G=>3, T=>4, P=>5, E=>6, Z=>7, Y=>8);-
1880 foreach my $i (0..255) {my $c=chr($i); $a{$c} ||= 0;print "$a{$c}, "}'\-
1881 |fmt */-
1882 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1883 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1884 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3,-
1885 0, 0, 0, 1, 0, 2, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0,-
1886 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1887 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1888 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1889 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1890 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1891 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-
1892 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0-
1893#endif-
1894 };-
1895-
1896/* Traverse number given as *number consisting of digits, thousands_sep, and-
1897 decimal_point chars only. Returns the highest digit found in the number,-
1898 or '\0' if no digit has been found. Upon return *number points at the-
1899 character that immediately follows after the given number. */-
1900static unsigned char-
1901traverse_raw_number (char const **number)-
1902{-
1903 char const *p = *number;-
1904 unsigned char ch;-
1905 unsigned char max_digit = '\0';-
1906 bool ends_with_thousands_sep = false;-
1907-
1908 /* Scan to end of number.-
1909 Decimals or separators not followed by digits stop the scan.-
1910 Numbers ending in decimals or separators are thus considered-
1911 to be lacking in units.-
1912 FIXME: add support for multibyte thousands_sep and decimal_point. */-
1913-
1914 while (ISDIGIT (ch = *p++))
((unsigned int...+) - '0' <= 9)Description
TRUEevaluated 530347 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 523030 times by 1 test
Evaluated by:
  • sort
523030-530347
1915 {-
1916 if (max_digit < ch)
max_digit < chDescription
TRUEevaluated 523508 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 6839 times by 1 test
Evaluated by:
  • sort
6839-523508
1917 max_digit = ch;
executed 523508 times by 1 test: max_digit = ch;
Executed by:
  • sort
523508
1918-
1919 /* Allow to skip only one occurrence of thousands_sep to avoid finding-
1920 the unit in the next column in case thousands_sep matches as blank-
1921 and is used as column delimiter. */-
1922 ends_with_thousands_sep = (*p == thousands_sep);-
1923 if (ends_with_thousands_sep)
ends_with_thousands_sepDescription
TRUEnever evaluated
FALSEevaluated 530347 times by 1 test
Evaluated by:
  • sort
0-530347
1924 ++p;
never executed: ++p;
0
1925 }
executed 530347 times by 1 test: end of block
Executed by:
  • sort
530347
1926-
1927 if (ends_with_thousands_sep)
ends_with_thousands_sepDescription
TRUEnever evaluated
FALSEevaluated 523030 times by 1 test
Evaluated by:
  • sort
0-523030
1928 {-
1929 /* thousands_sep not followed by digit is not allowed. */-
1930 *number = p - 2;-
1931 return max_digit;
never executed: return max_digit;
0
1932 }-
1933-
1934 if (ch == decimal_point)
ch == decimal_pointDescription
TRUEevaluated 522458 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 572 times by 1 test
Evaluated by:
  • sort
572-522458
1935 while (ISDIGIT (ch = *p++))
((unsigned int...+) - '0' <= 9)Description
TRUEevaluated 1566900 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 522458 times by 1 test
Evaluated by:
  • sort
522458-1566900
1936 if (max_digit < ch)
max_digit < chDescription
TRUEevaluated 499820 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1067080 times by 1 test
Evaluated by:
  • sort
499820-1067080
1937 max_digit = ch;
executed 499820 times by 1 test: max_digit = ch;
Executed by:
  • sort
499820
1938-
1939 *number = p - 1;-
1940 return max_digit;
executed 523030 times by 1 test: return max_digit;
Executed by:
  • sort
523030
1941}-
1942-
1943/* Return an integer that represents the order of magnitude of the-
1944 unit following the number. The number may contain thousands-
1945 separators and a decimal point, but it may not contain leading blanks.-
1946 Negative numbers get negative orders; zero numbers have a zero order. */-
1947-
1948static int _GL_ATTRIBUTE_PURE-
1949find_unit_order (char const *number)-
1950{-
1951 bool minus_sign = (*number == '-');-
1952 char const *p = number + minus_sign;-
1953 unsigned char max_digit = traverse_raw_number (&p);-
1954 if ('0' < max_digit)
'0' < max_digitDescription
TRUEevaluated 522907 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 79 times by 1 test
Evaluated by:
  • sort
79-522907
1955 {-
1956 unsigned char ch = *p;-
1957 int order = unit_order[ch];-
1958 return (minus_sign ? -order : order);
executed 522907 times by 1 test: return (minus_sign ? -order : order);
Executed by:
  • sort
522907
1959 }-
1960 else-
1961 return 0;
executed 79 times by 1 test: return 0;
Executed by:
  • sort
79
1962}-
1963-
1964/* Compare numbers A and B ending in units with SI or IEC prefixes-
1965 <none/unknown> < K/k < M < G < T < P < E < Z < Y */-
1966-
1967static int-
1968human_numcompare (char const *a, char const *b)-
1969{-
1970 while (blanks[to_uchar (*a)])
blanks[to_uchar (*a)]Description
TRUEevaluated 897 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 261493 times by 1 test
Evaluated by:
  • sort
897-261493
1971 a++;
executed 897 times by 1 test: a++;
Executed by:
  • sort
897
1972 while (blanks[to_uchar (*b)])
blanks[to_uchar (*b)]Description
TRUEevaluated 853 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 261493 times by 1 test
Evaluated by:
  • sort
853-261493
1973 b++;
executed 853 times by 1 test: b++;
Executed by:
  • sort
853
1974-
1975 int diff = find_unit_order (a) - find_unit_order (b);-
1976 return (diff ? diff : strnumcmp (a, b, decimal_point, thousands_sep));
executed 261493 times by 1 test: return (diff ? diff : strnumcmp (a, b, decimal_point, thousands_sep));
Executed by:
  • sort
261493
1977}-
1978-
1979/* Compare strings A and B as numbers without explicitly converting them to-
1980 machine numbers. Comparatively slow for short strings, but asymptotically-
1981 hideously fast. */-
1982-
1983static int-
1984numcompare (char const *a, char const *b)-
1985{-
1986 while (blanks[to_uchar (*a)])
blanks[to_uchar (*a)]Description
TRUEevaluated 922 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 294549 times by 1 test
Evaluated by:
  • sort
922-294549
1987 a++;
executed 922 times by 1 test: a++;
Executed by:
  • sort
922
1988 while (blanks[to_uchar (*b)])
blanks[to_uchar (*b)]Description
TRUEevaluated 933 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 294549 times by 1 test
Evaluated by:
  • sort
933-294549
1989 b++;
executed 933 times by 1 test: b++;
Executed by:
  • sort
933
1990-
1991 return strnumcmp (a, b, decimal_point, thousands_sep);
executed 294549 times by 1 test: return strnumcmp (a, b, decimal_point, thousands_sep);
Executed by:
  • sort
294549
1992}-
1993-
1994/* Work around a problem whereby the long double value returned by glibc's-
1995 strtold ("NaN", ...) contains uninitialized bits: clear all bytes of-
1996 A and B before calling strtold. FIXME: remove this function once-
1997 gnulib guarantees that strtold's result is always well defined. */-
1998static int-
1999nan_compare (char const *sa, char const *sb)-
2000{-
2001 long_double a;-
2002 memset (&a, 0, sizeof a);-
2003 a = strtold (sa, NULL);-
2004-
2005 long_double b;-
2006 memset (&b, 0, sizeof b);-
2007 b = strtold (sb, NULL);-
2008-
2009 return memcmp (&a, &b, sizeof a);
executed 1 time by 1 test: return memcmp (&a, &b, sizeof a);
Executed by:
  • sort
1
2010}-
2011-
2012static int-
2013general_numcompare (char const *sa, char const *sb)-
2014{-
2015 /* FIXME: maybe add option to try expensive FP conversion-
2016 only if A and B can't be compared more cheaply/accurately. */-
2017-
2018 char *ea;-
2019 char *eb;-
2020 long_double a = strtold (sa, &ea);-
2021 long_double b = strtold (sb, &eb);-
2022-
2023 /* Put conversion errors at the start of the collating sequence. */-
2024 if (sa == ea)
sa == eaDescription
TRUEevaluated 14 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 76 times by 1 test
Evaluated by:
  • sort
14-76
2025 return sb == eb ? 0 : -1;
executed 14 times by 1 test: return sb == eb ? 0 : -1;
Executed by:
  • sort
14
2026 if (sb == eb)
sb == ebDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 72 times by 1 test
Evaluated by:
  • sort
4-72
2027 return 1;
executed 4 times by 1 test: return 1;
Executed by:
  • sort
4
2028-
2029 /* Sort numbers in the usual way, where -0 == +0. Put NaNs after-
2030 conversion errors but before numbers; sort them by internal-
2031 bit-pattern, for lack of a more portable alternative. */-
2032 return (a < b ? -1
executed 72 times by 1 test: return (a < b ? -1 : a > b ? 1 : a == b ? 0 : b == b ? -1 : a == a ? 1 : nan_compare (sa, sb));
Executed by:
  • sort
72
2033 : a > b ? 1
executed 72 times by 1 test: return (a < b ? -1 : a > b ? 1 : a == b ? 0 : b == b ? -1 : a == a ? 1 : nan_compare (sa, sb));
Executed by:
  • sort
72
2034 : a == b ? 0
executed 72 times by 1 test: return (a < b ? -1 : a > b ? 1 : a == b ? 0 : b == b ? -1 : a == a ? 1 : nan_compare (sa, sb));
Executed by:
  • sort
72
2035 : b == b ? -1
executed 72 times by 1 test: return (a < b ? -1 : a > b ? 1 : a == b ? 0 : b == b ? -1 : a == a ? 1 : nan_compare (sa, sb));
Executed by:
  • sort
72
2036 : a == a ? 1
executed 72 times by 1 test: return (a < b ? -1 : a > b ? 1 : a == b ? 0 : b == b ? -1 : a == a ? 1 : nan_compare (sa, sb));
Executed by:
  • sort
72
2037 : nan_compare (sa, sb));
executed 72 times by 1 test: return (a < b ? -1 : a > b ? 1 : a == b ? 0 : b == b ? -1 : a == a ? 1 : nan_compare (sa, sb));
Executed by:
  • sort
72
2038}-
2039-
2040/* Return an integer in 1..12 of the month name MONTH.-
2041 Return 0 if the name in S is not recognized. */-
2042-
2043static int-
2044getmonth (char const *month, char **ea)-
2045{-
2046 size_t lo = 0;-
2047 size_t hi = MONTHS_PER_YEAR;-
2048-
2049 while (blanks[to_uchar (*month)])
blanks[to_uchar (*month)]Description
TRUEevaluated 206 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 258 times by 1 test
Evaluated by:
  • sort
206-258
2050 month++;
executed 206 times by 1 test: month++;
Executed by:
  • sort
206
2051-
2052 do-
2053 {-
2054 size_t ix = (lo + hi) / 2;-
2055 char const *m = month;-
2056 char const *n = monthtab[ix].name;-
2057-
2058 for (;; m++, n++)-
2059 {-
2060 if (!*n)
!*nDescription
TRUEevaluated 228 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1454 times by 1 test
Evaluated by:
  • sort
228-1454
2061 {-
2062 if (ea)
eaDescription
TRUEevaluated 12 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 216 times by 1 test
Evaluated by:
  • sort
12-216
2063 *ea = (char *) m;
executed 12 times by 1 test: *ea = (char *) m;
Executed by:
  • sort
12
2064 return monthtab[ix].val;
executed 228 times by 1 test: return monthtab[ix].val;
Executed by:
  • sort
228
2065 }-
2066 if (to_uchar (fold_toupper[to_uchar (*m)]) < to_uchar (*n))
to_uchar (fold... to_uchar (*n)Description
TRUEevaluated 408 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 1046 times by 1 test
Evaluated by:
  • sort
408-1046
2067 {-
2068 hi = ix;-
2069 break;
executed 408 times by 1 test: break;
Executed by:
  • sort
408
2070 }-
2071 else if (to_uchar (fold_toupper[to_uchar (*m)]) > to_uchar (*n))
to_uchar (fold... to_uchar (*n)Description
TRUEevaluated 186 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 860 times by 1 test
Evaluated by:
  • sort
186-860
2072 {-
2073 lo = ix + 1;-
2074 break;
executed 186 times by 1 test: break;
Executed by:
  • sort
186
2075 }-
2076 }
executed 860 times by 1 test: end of block
Executed by:
  • sort
860
2077 }
executed 594 times by 1 test: end of block
Executed by:
  • sort
594
2078 while (lo < hi);
lo < hiDescription
TRUEevaluated 564 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 30 times by 1 test
Evaluated by:
  • sort
30-564
2079-
2080 return 0;
executed 30 times by 1 test: return 0;
Executed by:
  • sort
30
2081}-
2082-
2083/* A randomly chosen MD5 state, used for random comparison. */-
2084static struct md5_ctx random_md5_state;-
2085-
2086/* Initialize the randomly chosen MD5 state. */-
2087-
2088static void-
2089random_md5_state_init (char const *random_source)-
2090{-
2091 unsigned char buf[MD5_DIGEST_SIZE];-
2092 struct randread_source *r = randread_new (random_source, sizeof buf);-
2093 if (! r)
! rDescription
TRUEnever evaluated
FALSEevaluated 15 times by 1 test
Evaluated by:
  • sort
0-15
2094 sort_die (_("open failed"), random_source);
never executed: sort_die ( dcgettext (((void *)0), "open failed" , 5) , random_source);
0
2095 randread (r, buf, sizeof buf);-
2096 if (randread_free (r) != 0)
randread_free (r) != 0Description
TRUEnever evaluated
FALSEevaluated 15 times by 1 test
Evaluated by:
  • sort
0-15
2097 sort_die (_("close failed"), random_source);
never executed: sort_die ( dcgettext (((void *)0), "close failed" , 5) , random_source);
0
2098 md5_init_ctx (&random_md5_state);-
2099 md5_process_bytes (buf, sizeof buf, &random_md5_state);-
2100}
executed 15 times by 1 test: end of block
Executed by:
  • sort
15
2101-
2102/* This is like strxfrm, except it reports any error and exits. */-
2103-
2104static size_t-
2105xstrxfrm (char *restrict dest, char const *restrict src, size_t destsize)-
2106{-
2107 errno = 0;-
2108 size_t translated_size = strxfrm (dest, src, destsize);-
2109-
2110 if (errno)
(*__errno_location ())Description
TRUEnever evaluated
FALSEevaluated 2172 times by 1 test
Evaluated by:
  • sort
0-2172
2111 {-
2112 error (0, errno, _("string transformation failed"));-
2113 error (0, 0, _("set LC_ALL='C' to work around the problem"));-
2114 die (SORT_FAILURE, 0,-
2115 _("the untransformed string was %s"),-
2116 quotearg_n_style (0, locale_quoting_style, src));-
2117 }
never executed: end of block
0
2118-
2119 return translated_size;
executed 2172 times by 1 test: return translated_size;
Executed by:
  • sort
2172
2120}-
2121-
2122/* Compare the keys TEXTA (of length LENA) and TEXTB (of length LENB)-
2123 using one or more random hash functions. TEXTA[LENA] and-
2124 TEXTB[LENB] must be zero. */-
2125-
2126static int-
2127compare_random (char *restrict texta, size_t lena,-
2128 char *restrict textb, size_t lenb)-
2129{-
2130 /* XFRM_DIFF records the equivalent of memcmp on the transformed-
2131 data. This is used to break ties if there is a checksum-
2132 collision, and this is good enough given the astronomically low-
2133 probability of a collision. */-
2134 int xfrm_diff = 0;-
2135-
2136 char stackbuf[4000];-
2137 char *buf = stackbuf;-
2138 size_t bufsize = sizeof stackbuf;-
2139 void *allocated = NULL;-
2140 uint32_t dig[2][MD5_DIGEST_SIZE / sizeof (uint32_t)];-
2141 struct md5_ctx s[2];-
2142 s[0] = s[1] = random_md5_state;-
2143-
2144 if (hard_LC_COLLATE)
hard_LC_COLLATEDescription
TRUEevaluated 1086 times by 1 test
Evaluated by:
  • sort
FALSEevaluated 644249 times by 1 test
Evaluated by:
  • sort
1086-644249
2145 {-
2146 char const *lima = texta + lena;-
2147 char const *limb = textb + lenb;-
2148-
2149 while (true)-
2150 {-
2151 /* Transform the text into the basis of comparison, so that byte-
2152 strings that would otherwise considered to be equal are-
2153 considered equal here even if their bytes differ.-
2154-
2155 Each time through this loop, transform one-
2156 null-terminated string's worth from TEXTA or from TEXTB-
2157 or both. That way, there's no need to store the-
2158 transformation of the whole line, if it contains many-
2159 null-terminated strings. */-
2160-
2161 /* Store the transformed data into a big-enough buffer. */-
2162-
2163 /* A 3X size guess avoids the overhead of calling strxfrm-
2164 twice on typical implementations. Don't worry about-
2165 size_t overflow, as the guess need not be correct. */-
2166 size_t guess_bufsize = 3 * (lena + lenb) + 2;-
2167 if (bufsize < guess_bufsize)
bufsize < guess_bufsizeDescription
TRUEnever evaluated
FALSEevaluated 1086 times by 1 test
Evaluated by:
  • sort
0-1086
2168 {-
2169 bufsize = MAX (guess_bufsize, bufsize * 3 / 2);
(( guess_bufsi...ize * 3 / 2 ))Description
TRUEnever evaluated
FALSEnever evaluated
0
2170 free (allocated);-
2171 buf = allocated = malloc (bufsize);-
2172 if (! buf)
! bufDescription
TRUEnever evaluated
FALSEnever evaluated
0
2173 {-
2174 buf = stackbuf;-
2175 bufsize = sizeof stackbuf;-
2176 }
never executed: end of block
0
2177 }
never executed: end of block
0
2178-
2179 size_t sizea =-
2180 (texta < lima ? xstrxfrm (buf, texta, bufsize) + 1 : 0);
texta < limaDescription
TRUEevaluated 1086 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-1086
2181 bool a_fits = sizea <= bufsize;-
2182 size_t sizeb =-
2183 (textb < limb
textb < limbDescription
TRUEevaluated 1086 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-1086
2184 ? (xstrxfrm ((a_fits ? buf + sizea : NULL), textb,-
2185 (a_fits ? bufsize - sizea : 0))-
2186 + 1)-
2187 : 0);-
2188-
2189 if (! (a_fits && sizea + sizeb <= bufsize))
a_fitsDescription
TRUEevaluated 1086 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
sizea + sizeb <= bufsizeDescription
TRUEevaluated 1086 times by 1 test
Evaluated by:
  • sort
FALSEnever evaluated
0-1086
2190 {-
2191 bufsize = sizea + sizeb;-
2192 if (bufsize < SIZE_MAX / 3)
bufsize < (184...9551615UL) / 3Description
TRUEnever evaluated
FALSEnever evaluated
0
2193 bufsize = bufsize * 3 / 2;
never executed: bufsize = bufsize * 3 / 2;
0
2194 free (allocated);-
2195 buf = allocated = xmalloc (bufsize);-
2196 if (texta < lima)
texta < limaDescription
TRUEnever evaluated
FALSEnever evaluated
0
2197