build: support fully excluding stdbuf from the build
[coreutils/ericb.git] / src / wc.c
blob6df7feddfcdeb7e841a2e2b9664cb51342186aa2
1 /* wc - print the number of lines, words, and bytes in files
2 Copyright (C) 1985, 1991, 1995-2010 Free Software Foundation, Inc.
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.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Paul Rubin, phr@ocf.berkeley.edu
18 and David MacKenzie, djm@gnu.ai.mit.edu. */
20 #include <config.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include <getopt.h>
25 #include <sys/types.h>
26 #include <wchar.h>
27 #include <wctype.h>
29 #include "system.h"
30 #include "argv-iter.h"
31 #include "error.h"
32 #include "mbchar.h"
33 #include "physmem.h"
34 #include "quote.h"
35 #include "quotearg.h"
36 #include "readtokens0.h"
37 #include "safe-read.h"
38 #include "xfreopen.h"
40 #if !defined iswspace && !HAVE_ISWSPACE
41 # define iswspace(wc) \
42 ((wc) == to_uchar (wc) && isspace (to_uchar (wc)))
43 #endif
45 /* The official name of this program (e.g., no `g' prefix). */
46 #define PROGRAM_NAME "wc"
48 #define AUTHORS \
49 proper_name ("Paul Rubin"), \
50 proper_name ("David MacKenzie")
52 /* Size of atomic reads. */
53 #define BUFFER_SIZE (16 * 1024)
55 /* Cumulative number of lines, words, chars and bytes in all files so far.
56 max_line_length is the maximum over all files processed so far. */
57 static uintmax_t total_lines;
58 static uintmax_t total_words;
59 static uintmax_t total_chars;
60 static uintmax_t total_bytes;
61 static uintmax_t max_line_length;
63 /* Which counts to print. */
64 static bool print_lines, print_words, print_chars, print_bytes;
65 static bool print_linelength;
67 /* The print width of each count. */
68 static int number_width;
70 /* True if we have ever read the standard input. */
71 static bool have_read_stdin;
73 /* The result of calling fstat or stat on a file descriptor or file. */
74 struct fstatus
76 /* If positive, fstat or stat has not been called yet. Otherwise,
77 this is the value returned from fstat or stat. */
78 int failed;
80 /* If FAILED is zero, this is the file's status. */
81 struct stat st;
84 /* For long options that have no equivalent short option, use a
85 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
86 enum
88 FILES0_FROM_OPTION = CHAR_MAX + 1
91 static struct option const longopts[] =
93 {"bytes", no_argument, NULL, 'c'},
94 {"chars", no_argument, NULL, 'm'},
95 {"lines", no_argument, NULL, 'l'},
96 {"words", no_argument, NULL, 'w'},
97 {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
98 {"max-line-length", no_argument, NULL, 'L'},
99 {GETOPT_HELP_OPTION_DECL},
100 {GETOPT_VERSION_OPTION_DECL},
101 {NULL, 0, NULL, 0}
104 void
105 usage (int status)
107 if (status != EXIT_SUCCESS)
108 fprintf (stderr, _("Try `%s --help' for more information.\n"),
109 program_name);
110 else
112 printf (_("\
113 Usage: %s [OPTION]... [FILE]...\n\
114 or: %s [OPTION]... --files0-from=F\n\
116 program_name, program_name);
117 fputs (_("\
118 Print newline, word, and byte counts for each FILE, and a total line if\n\
119 more than one FILE is specified. With no FILE, or when FILE is -,\n\
120 read standard input. A word is a non-zero-length sequence of characters\n\
121 delimited by white space.\n\
122 -c, --bytes print the byte counts\n\
123 -m, --chars print the character counts\n\
124 -l, --lines print the newline counts\n\
125 "), stdout);
126 fputs (_("\
127 --files0-from=F read input from the files specified by\n\
128 NUL-terminated names in file F;\n\
129 If F is - then read names from standard input\n\
130 -L, --max-line-length print the length of the longest line\n\
131 -w, --words print the word counts\n\
132 "), stdout);
133 fputs (HELP_OPTION_DESCRIPTION, stdout);
134 fputs (VERSION_OPTION_DESCRIPTION, stdout);
135 emit_ancillary_info ();
137 exit (status);
140 /* FILE is the name of the file (or NULL for standard input)
141 associated with the specified counters. */
142 static void
143 write_counts (uintmax_t lines,
144 uintmax_t words,
145 uintmax_t chars,
146 uintmax_t bytes,
147 uintmax_t linelength,
148 const char *file)
150 static char const format_sp_int[] = " %*s";
151 char const *format_int = format_sp_int + 1;
152 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
154 if (print_lines)
156 printf (format_int, number_width, umaxtostr (lines, buf));
157 format_int = format_sp_int;
159 if (print_words)
161 printf (format_int, number_width, umaxtostr (words, buf));
162 format_int = format_sp_int;
164 if (print_chars)
166 printf (format_int, number_width, umaxtostr (chars, buf));
167 format_int = format_sp_int;
169 if (print_bytes)
171 printf (format_int, number_width, umaxtostr (bytes, buf));
172 format_int = format_sp_int;
174 if (print_linelength)
176 printf (format_int, number_width, umaxtostr (linelength, buf));
178 if (file)
179 printf (" %s", file);
180 putchar ('\n');
183 /* Count words. FILE_X is the name of the file (or NULL for standard
184 input) that is open on descriptor FD. *FSTATUS is its status.
185 Return true if successful. */
186 static bool
187 wc (int fd, char const *file_x, struct fstatus *fstatus)
189 bool ok = true;
190 char buf[BUFFER_SIZE + 1];
191 size_t bytes_read;
192 uintmax_t lines, words, chars, bytes, linelength;
193 bool count_bytes, count_chars, count_complicated;
194 char const *file = file_x ? file_x : _("standard input");
196 lines = words = chars = bytes = linelength = 0;
198 /* If in the current locale, chars are equivalent to bytes, we prefer
199 counting bytes, because that's easier. */
200 #if MB_LEN_MAX > 1
201 if (MB_CUR_MAX > 1)
203 count_bytes = print_bytes;
204 count_chars = print_chars;
206 else
207 #endif
209 count_bytes = print_bytes || print_chars;
210 count_chars = false;
212 count_complicated = print_words || print_linelength;
214 /* When counting only bytes, save some line- and word-counting
215 overhead. If FD is a `regular' Unix file, using lseek is enough
216 to get its `size' in bytes. Otherwise, read blocks of BUFFER_SIZE
217 bytes at a time until EOF. Note that the `size' (number of bytes)
218 that wc reports is smaller than stats.st_size when the file is not
219 positioned at its beginning. That's why the lseek calls below are
220 necessary. For example the command
221 `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
222 should make wc report `0' bytes. */
224 if (count_bytes && !count_chars && !print_lines && !count_complicated)
226 off_t current_pos, end_pos;
228 if (0 < fstatus->failed)
229 fstatus->failed = fstat (fd, &fstatus->st);
231 if (! fstatus->failed && S_ISREG (fstatus->st.st_mode)
232 && (current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
233 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
235 /* Be careful here. The current position may actually be
236 beyond the end of the file. As in the example above. */
237 bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
239 else
241 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
243 if (bytes_read == SAFE_READ_ERROR)
245 error (0, errno, "%s", file);
246 ok = false;
247 break;
249 bytes += bytes_read;
253 else if (!count_chars && !count_complicated)
255 /* Use a separate loop when counting only lines or lines and bytes --
256 but not chars or words. */
257 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
259 char *p = buf;
261 if (bytes_read == SAFE_READ_ERROR)
263 error (0, errno, "%s", file);
264 ok = false;
265 break;
268 while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
270 ++p;
271 ++lines;
273 bytes += bytes_read;
276 #if MB_LEN_MAX > 1
277 # define SUPPORT_OLD_MBRTOWC 1
278 else if (MB_CUR_MAX > 1)
280 bool in_word = false;
281 uintmax_t linepos = 0;
282 DECLARE_ZEROED_AGGREGATE (mbstate_t, state);
283 bool in_shift = false;
284 # if SUPPORT_OLD_MBRTOWC
285 /* Back-up the state before each multibyte character conversion and
286 move the last incomplete character of the buffer to the front
287 of the buffer. This is needed because we don't know whether
288 the `mbrtowc' function updates the state when it returns -2, -
289 this is the ISO C 99 and glibc-2.2 behaviour - or not - amended
290 ANSI C, glibc-2.1 and Solaris 5.7 behaviour. We don't have an
291 autoconf test for this, yet. */
292 size_t prev = 0; /* number of bytes carried over from previous round */
293 # else
294 const size_t prev = 0;
295 # endif
297 while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
299 const char *p;
300 # if SUPPORT_OLD_MBRTOWC
301 mbstate_t backup_state;
302 # endif
303 if (bytes_read == SAFE_READ_ERROR)
305 error (0, errno, "%s", file);
306 ok = false;
307 break;
310 bytes += bytes_read;
311 p = buf;
312 bytes_read += prev;
315 wchar_t wide_char;
316 size_t n;
318 if (!in_shift && is_basic (*p))
320 /* Handle most ASCII characters quickly, without calling
321 mbrtowc(). */
322 n = 1;
323 wide_char = *p;
325 else
327 in_shift = true;
328 # if SUPPORT_OLD_MBRTOWC
329 backup_state = state;
330 # endif
331 n = mbrtowc (&wide_char, p, bytes_read, &state);
332 if (n == (size_t) -2)
334 # if SUPPORT_OLD_MBRTOWC
335 state = backup_state;
336 # endif
337 break;
339 if (n == (size_t) -1)
341 /* Remember that we read a byte, but don't complain
342 about the error. Because of the decoding error,
343 this is a considered to be byte but not a
344 character (that is, chars is not incremented). */
345 p++;
346 bytes_read--;
347 continue;
349 if (mbsinit (&state))
350 in_shift = false;
351 if (n == 0)
353 wide_char = 0;
354 n = 1;
357 p += n;
358 bytes_read -= n;
359 chars++;
360 switch (wide_char)
362 case '\n':
363 lines++;
364 /* Fall through. */
365 case '\r':
366 case '\f':
367 if (linepos > linelength)
368 linelength = linepos;
369 linepos = 0;
370 goto mb_word_separator;
371 case '\t':
372 linepos += 8 - (linepos % 8);
373 goto mb_word_separator;
374 case ' ':
375 linepos++;
376 /* Fall through. */
377 case '\v':
378 mb_word_separator:
379 words += in_word;
380 in_word = false;
381 break;
382 default:
383 if (iswprint (wide_char))
385 int width = wcwidth (wide_char);
386 if (width > 0)
387 linepos += width;
388 if (iswspace (wide_char))
389 goto mb_word_separator;
390 in_word = true;
392 break;
395 while (bytes_read > 0);
397 # if SUPPORT_OLD_MBRTOWC
398 if (bytes_read > 0)
400 if (bytes_read == BUFFER_SIZE)
402 /* Encountered a very long redundant shift sequence. */
403 p++;
404 bytes_read--;
406 memmove (buf, p, bytes_read);
408 prev = bytes_read;
409 # endif
411 if (linepos > linelength)
412 linelength = linepos;
413 words += in_word;
415 #endif
416 else
418 bool in_word = false;
419 uintmax_t linepos = 0;
421 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
423 const char *p = buf;
424 if (bytes_read == SAFE_READ_ERROR)
426 error (0, errno, "%s", file);
427 ok = false;
428 break;
431 bytes += bytes_read;
434 switch (*p++)
436 case '\n':
437 lines++;
438 /* Fall through. */
439 case '\r':
440 case '\f':
441 if (linepos > linelength)
442 linelength = linepos;
443 linepos = 0;
444 goto word_separator;
445 case '\t':
446 linepos += 8 - (linepos % 8);
447 goto word_separator;
448 case ' ':
449 linepos++;
450 /* Fall through. */
451 case '\v':
452 word_separator:
453 words += in_word;
454 in_word = false;
455 break;
456 default:
457 if (isprint (to_uchar (p[-1])))
459 linepos++;
460 if (isspace (to_uchar (p[-1])))
461 goto word_separator;
462 in_word = true;
464 break;
467 while (--bytes_read);
469 if (linepos > linelength)
470 linelength = linepos;
471 words += in_word;
474 if (count_chars < print_chars)
475 chars = bytes;
477 write_counts (lines, words, chars, bytes, linelength, file_x);
478 total_lines += lines;
479 total_words += words;
480 total_chars += chars;
481 total_bytes += bytes;
482 if (linelength > max_line_length)
483 max_line_length = linelength;
485 return ok;
488 static bool
489 wc_file (char const *file, struct fstatus *fstatus)
491 if (! file || STREQ (file, "-"))
493 have_read_stdin = true;
494 if (O_BINARY && ! isatty (STDIN_FILENO))
495 xfreopen (NULL, "rb", stdin);
496 return wc (STDIN_FILENO, file, fstatus);
498 else
500 int fd = open (file, O_RDONLY | O_BINARY);
501 if (fd == -1)
503 error (0, errno, "%s", file);
504 return false;
506 else
508 bool ok = wc (fd, file, fstatus);
509 if (close (fd) != 0)
511 error (0, errno, "%s", file);
512 return false;
514 return ok;
519 /* Return the file status for the NFILES files addressed by FILE.
520 Optimize the case where only one number is printed, for just one
521 file; in that case we can use a print width of 1, so we don't need
522 to stat the file. Handle the case of (nfiles == 0) in the same way;
523 that happens when we don't know how long the list of file names will be. */
525 static struct fstatus *
526 get_input_fstatus (int nfiles, char *const *file)
528 struct fstatus *fstatus = xnmalloc (nfiles ? nfiles : 1, sizeof *fstatus);
530 if (nfiles == 0
531 || (nfiles == 1
532 && ((print_lines + print_words + print_chars
533 + print_bytes + print_linelength)
534 == 1)))
535 fstatus[0].failed = 1;
536 else
538 int i;
540 for (i = 0; i < nfiles; i++)
541 fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
542 ? fstat (STDIN_FILENO, &fstatus[i].st)
543 : stat (file[i], &fstatus[i].st));
546 return fstatus;
549 /* Return a print width suitable for the NFILES files whose status is
550 recorded in FSTATUS. Optimize the same special case that
551 get_input_fstatus optimizes. */
553 static int
554 compute_number_width (int nfiles, struct fstatus const *fstatus)
556 int width = 1;
558 if (0 < nfiles && fstatus[0].failed <= 0)
560 int minimum_width = 1;
561 uintmax_t regular_total = 0;
562 int i;
564 for (i = 0; i < nfiles; i++)
565 if (! fstatus[i].failed)
567 if (S_ISREG (fstatus[i].st.st_mode))
568 regular_total += fstatus[i].st.st_size;
569 else
570 minimum_width = 7;
573 for (; 10 <= regular_total; regular_total /= 10)
574 width++;
575 if (width < minimum_width)
576 width = minimum_width;
579 return width;
584 main (int argc, char **argv)
586 bool ok;
587 int optc;
588 int nfiles;
589 char **files;
590 char *files_from = NULL;
591 struct fstatus *fstatus;
592 struct Tokens tok;
594 initialize_main (&argc, &argv);
595 set_program_name (argv[0]);
596 setlocale (LC_ALL, "");
597 bindtextdomain (PACKAGE, LOCALEDIR);
598 textdomain (PACKAGE);
600 atexit (close_stdout);
602 /* Line buffer stdout to ensure lines are written atomically and immediately
603 so that processes running in parallel do not intersperse their output. */
604 setvbuf (stdout, NULL, _IOLBF, 0);
606 print_lines = print_words = print_chars = print_bytes = false;
607 print_linelength = false;
608 total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
610 while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
611 switch (optc)
613 case 'c':
614 print_bytes = true;
615 break;
617 case 'm':
618 print_chars = true;
619 break;
621 case 'l':
622 print_lines = true;
623 break;
625 case 'w':
626 print_words = true;
627 break;
629 case 'L':
630 print_linelength = true;
631 break;
633 case FILES0_FROM_OPTION:
634 files_from = optarg;
635 break;
637 case_GETOPT_HELP_CHAR;
639 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
641 default:
642 usage (EXIT_FAILURE);
645 if (! (print_lines || print_words || print_chars || print_bytes
646 || print_linelength))
647 print_lines = print_words = print_bytes = true;
649 bool read_tokens = false;
650 struct argv_iterator *ai;
651 if (files_from)
653 FILE *stream;
655 /* When using --files0-from=F, you may not specify any files
656 on the command-line. */
657 if (optind < argc)
659 error (0, 0, _("extra operand %s"), quote (argv[optind]));
660 fprintf (stderr, "%s\n",
661 _("file operands cannot be combined with --files0-from"));
662 usage (EXIT_FAILURE);
665 if (STREQ (files_from, "-"))
666 stream = stdin;
667 else
669 stream = fopen (files_from, "r");
670 if (stream == NULL)
671 error (EXIT_FAILURE, errno, _("cannot open %s for reading"),
672 quote (files_from));
675 /* Read the file list into RAM if we can detect its size and that
676 size is reasonable. Otherwise, we'll read a name at a time. */
677 struct stat st;
678 if (fstat (fileno (stream), &st) == 0
679 && S_ISREG (st.st_mode)
680 && st.st_size <= MIN (10 * 1024 * 1024, physmem_available () / 2))
682 read_tokens = true;
683 readtokens0_init (&tok);
684 if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
685 error (EXIT_FAILURE, 0, _("cannot read file names from %s"),
686 quote (files_from));
687 files = tok.tok;
688 nfiles = tok.n_tok;
689 ai = argv_iter_init_argv (files);
691 else
693 files = NULL;
694 nfiles = 0;
695 ai = argv_iter_init_stream (stream);
698 else
700 static char *stdin_only[] = { NULL };
701 files = (optind < argc ? argv + optind : stdin_only);
702 nfiles = (optind < argc ? argc - optind : 1);
703 ai = argv_iter_init_argv (files);
706 fstatus = get_input_fstatus (nfiles, files);
707 number_width = compute_number_width (nfiles, fstatus);
709 int i;
710 ok = true;
711 for (i = 0; /* */; i++)
713 bool skip_file = false;
714 enum argv_iter_err ai_err;
715 char *file_name = argv_iter (ai, &ai_err);
716 if (ai_err == AI_ERR_EOF)
717 break;
718 if (!file_name)
720 switch (ai_err)
722 case AI_ERR_READ:
723 error (0, errno, _("%s: read error"), quote (files_from));
724 skip_file = true;
725 continue;
726 case AI_ERR_MEM:
727 xalloc_die ();
728 default:
729 assert (!"unexpected error code from argv_iter");
732 if (files_from && STREQ (files_from, "-") && STREQ (file_name, "-"))
734 /* Give a better diagnostic in an unusual case:
735 printf - | wc --files0-from=- */
736 error (0, 0, _("when reading file names from stdin, "
737 "no file name of %s allowed"),
738 quote (file_name));
739 skip_file = true;
742 if (!file_name[0])
744 /* Diagnose a zero-length file name. When it's one
745 among many, knowing the record number may help.
746 FIXME: currently print the record number only with
747 --files0-from=FILE. Maybe do it for argv, too? */
748 if (files_from == NULL)
749 error (0, 0, "%s", _("invalid zero-length file name"));
750 else
752 /* Using the standard `filename:line-number:' prefix here is
753 not totally appropriate, since NUL is the separator, not NL,
754 but it might be better than nothing. */
755 unsigned long int file_number = argv_iter_n_args (ai);
756 error (0, 0, "%s:%lu: %s", quotearg_colon (files_from),
757 file_number, _("invalid zero-length file name"));
759 skip_file = true;
762 if (skip_file)
763 ok = false;
764 else
765 ok &= wc_file (file_name, &fstatus[nfiles ? i : 0]);
768 /* No arguments on the command line is fine. That means read from stdin.
769 However, no arguments on the --files0-from input stream is an error
770 means don't read anything. */
771 if (ok && !files_from && argv_iter_n_args (ai) == 0)
772 ok &= wc_file (NULL, &fstatus[0]);
774 if (read_tokens)
775 readtokens0_free (&tok);
777 if (1 < argv_iter_n_args (ai))
778 write_counts (total_lines, total_words, total_chars, total_bytes,
779 max_line_length, _("total"));
781 argv_iter_free (ai);
783 free (fstatus);
785 if (have_read_stdin && close (STDIN_FILENO) != 0)
786 error (EXIT_FAILURE, errno, "-");
788 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);