id: fix infinite loop on some systems
[coreutils/ericb.git] / src / wc.c
blobe6ffd1a5822af9d881782f94c298a430b45fe4f9
1 /* wc - print the number of lines, words, and bytes in files
2 Copyright (C) 85, 91, 1995-2009 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.\n\
121 -c, --bytes print the byte counts\n\
122 -m, --chars print the character counts\n\
123 -l, --lines print the newline counts\n\
124 "), stdout);
125 fputs (_("\
126 --files0-from=F read input from the files specified by\n\
127 NUL-terminated names in file F;\n\
128 If F is - then read names from standard input\n\
129 -L, --max-line-length print the length of the longest line\n\
130 -w, --words print the word counts\n\
131 "), stdout);
132 fputs (HELP_OPTION_DESCRIPTION, stdout);
133 fputs (VERSION_OPTION_DESCRIPTION, stdout);
134 emit_bug_reporting_address ();
136 exit (status);
139 /* FILE is the name of the file (or NULL for standard input)
140 associated with the specified counters. */
141 static void
142 write_counts (uintmax_t lines,
143 uintmax_t words,
144 uintmax_t chars,
145 uintmax_t bytes,
146 uintmax_t linelength,
147 const char *file)
149 static char const format_sp_int[] = " %*s";
150 char const *format_int = format_sp_int + 1;
151 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
153 if (print_lines)
155 printf (format_int, number_width, umaxtostr (lines, buf));
156 format_int = format_sp_int;
158 if (print_words)
160 printf (format_int, number_width, umaxtostr (words, buf));
161 format_int = format_sp_int;
163 if (print_chars)
165 printf (format_int, number_width, umaxtostr (chars, buf));
166 format_int = format_sp_int;
168 if (print_bytes)
170 printf (format_int, number_width, umaxtostr (bytes, buf));
171 format_int = format_sp_int;
173 if (print_linelength)
175 printf (format_int, number_width, umaxtostr (linelength, buf));
177 if (file)
178 printf (" %s", file);
179 putchar ('\n');
182 /* Count words. FILE_X is the name of the file (or NULL for standard
183 input) that is open on descriptor FD. *FSTATUS is its status.
184 Return true if successful. */
185 static bool
186 wc (int fd, char const *file_x, struct fstatus *fstatus)
188 bool ok = true;
189 char buf[BUFFER_SIZE + 1];
190 size_t bytes_read;
191 uintmax_t lines, words, chars, bytes, linelength;
192 bool count_bytes, count_chars, count_complicated;
193 char const *file = file_x ? file_x : _("standard input");
195 lines = words = chars = bytes = linelength = 0;
197 /* If in the current locale, chars are equivalent to bytes, we prefer
198 counting bytes, because that's easier. */
199 #if MB_LEN_MAX > 1
200 if (MB_CUR_MAX > 1)
202 count_bytes = print_bytes;
203 count_chars = print_chars;
205 else
206 #endif
208 count_bytes = print_bytes | print_chars;
209 count_chars = false;
211 count_complicated = print_words | print_linelength;
213 /* When counting only bytes, save some line- and word-counting
214 overhead. If FD is a `regular' Unix file, using lseek is enough
215 to get its `size' in bytes. Otherwise, read blocks of BUFFER_SIZE
216 bytes at a time until EOF. Note that the `size' (number of bytes)
217 that wc reports is smaller than stats.st_size when the file is not
218 positioned at its beginning. That's why the lseek calls below are
219 necessary. For example the command
220 `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
221 should make wc report `0' bytes. */
223 if (count_bytes & !count_chars & !print_lines & !count_complicated)
225 off_t current_pos, end_pos;
227 if (0 < fstatus->failed)
228 fstatus->failed = fstat (fd, &fstatus->st);
230 if (! fstatus->failed && S_ISREG (fstatus->st.st_mode)
231 && (current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
232 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
234 /* Be careful here. The current position may actually be
235 beyond the end of the file. As in the example above. */
236 bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
238 else
240 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
242 if (bytes_read == SAFE_READ_ERROR)
244 error (0, errno, "%s", file);
245 ok = false;
246 break;
248 bytes += bytes_read;
252 else if (!count_chars && !count_complicated)
254 /* Use a separate loop when counting only lines or lines and bytes --
255 but not chars or words. */
256 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
258 char *p = buf;
260 if (bytes_read == SAFE_READ_ERROR)
262 error (0, errno, "%s", file);
263 ok = false;
264 break;
267 while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
269 ++p;
270 ++lines;
272 bytes += bytes_read;
275 #if MB_LEN_MAX > 1
276 # define SUPPORT_OLD_MBRTOWC 1
277 else if (MB_CUR_MAX > 1)
279 bool in_word = false;
280 uintmax_t linepos = 0;
281 DECLARE_ZEROED_AGGREGATE (mbstate_t, state);
282 bool in_shift = false;
283 # if SUPPORT_OLD_MBRTOWC
284 /* Back-up the state before each multibyte character conversion and
285 move the last incomplete character of the buffer to the front
286 of the buffer. This is needed because we don't know whether
287 the `mbrtowc' function updates the state when it returns -2, -
288 this is the ISO C 99 and glibc-2.2 behaviour - or not - amended
289 ANSI C, glibc-2.1 and Solaris 5.7 behaviour. We don't have an
290 autoconf test for this, yet. */
291 size_t prev = 0; /* number of bytes carried over from previous round */
292 # else
293 const size_t prev = 0;
294 # endif
296 while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
298 const char *p;
299 # if SUPPORT_OLD_MBRTOWC
300 mbstate_t backup_state;
301 # endif
302 if (bytes_read == SAFE_READ_ERROR)
304 error (0, errno, "%s", file);
305 ok = false;
306 break;
309 bytes += bytes_read;
310 p = buf;
311 bytes_read += prev;
314 wchar_t wide_char;
315 size_t n;
317 if (!in_shift && is_basic (*p))
319 /* Handle most ASCII characters quickly, without calling
320 mbrtowc(). */
321 n = 1;
322 wide_char = *p;
324 else
326 in_shift = true;
327 # if SUPPORT_OLD_MBRTOWC
328 backup_state = state;
329 # endif
330 n = mbrtowc (&wide_char, p, bytes_read, &state);
331 if (n == (size_t) -2)
333 # if SUPPORT_OLD_MBRTOWC
334 state = backup_state;
335 # endif
336 break;
338 if (n == (size_t) -1)
340 /* Remember that we read a byte, but don't complain
341 about the error. Because of the decoding error,
342 this is a considered to be byte but not a
343 character (that is, chars is not incremented). */
344 p++;
345 bytes_read--;
346 continue;
348 if (mbsinit (&state))
349 in_shift = false;
350 if (n == 0)
352 wide_char = 0;
353 n = 1;
356 p += n;
357 bytes_read -= n;
358 chars++;
359 switch (wide_char)
361 case '\n':
362 lines++;
363 /* Fall through. */
364 case '\r':
365 case '\f':
366 if (linepos > linelength)
367 linelength = linepos;
368 linepos = 0;
369 goto mb_word_separator;
370 case '\t':
371 linepos += 8 - (linepos % 8);
372 goto mb_word_separator;
373 case ' ':
374 linepos++;
375 /* Fall through. */
376 case '\v':
377 mb_word_separator:
378 words += in_word;
379 in_word = false;
380 break;
381 default:
382 if (iswprint (wide_char))
384 int width = wcwidth (wide_char);
385 if (width > 0)
386 linepos += width;
387 if (iswspace (wide_char))
388 goto mb_word_separator;
389 in_word = true;
391 break;
394 while (bytes_read > 0);
396 # if SUPPORT_OLD_MBRTOWC
397 if (bytes_read > 0)
399 if (bytes_read == BUFFER_SIZE)
401 /* Encountered a very long redundant shift sequence. */
402 p++;
403 bytes_read--;
405 memmove (buf, p, bytes_read);
407 prev = bytes_read;
408 # endif
410 if (linepos > linelength)
411 linelength = linepos;
412 words += in_word;
414 #endif
415 else
417 bool in_word = false;
418 uintmax_t linepos = 0;
420 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
422 const char *p = buf;
423 if (bytes_read == SAFE_READ_ERROR)
425 error (0, errno, "%s", file);
426 ok = false;
427 break;
430 bytes += bytes_read;
433 switch (*p++)
435 case '\n':
436 lines++;
437 /* Fall through. */
438 case '\r':
439 case '\f':
440 if (linepos > linelength)
441 linelength = linepos;
442 linepos = 0;
443 goto word_separator;
444 case '\t':
445 linepos += 8 - (linepos % 8);
446 goto word_separator;
447 case ' ':
448 linepos++;
449 /* Fall through. */
450 case '\v':
451 word_separator:
452 words += in_word;
453 in_word = false;
454 break;
455 default:
456 if (isprint (to_uchar (p[-1])))
458 linepos++;
459 if (isspace (to_uchar (p[-1])))
460 goto word_separator;
461 in_word = true;
463 break;
466 while (--bytes_read);
468 if (linepos > linelength)
469 linelength = linepos;
470 words += in_word;
473 if (count_chars < print_chars)
474 chars = bytes;
476 write_counts (lines, words, chars, bytes, linelength, file_x);
477 total_lines += lines;
478 total_words += words;
479 total_chars += chars;
480 total_bytes += bytes;
481 if (linelength > max_line_length)
482 max_line_length = linelength;
484 return ok;
487 static bool
488 wc_file (char const *file, struct fstatus *fstatus)
490 if (! file || STREQ (file, "-"))
492 have_read_stdin = true;
493 if (O_BINARY && ! isatty (STDIN_FILENO))
494 xfreopen (NULL, "rb", stdin);
495 return wc (STDIN_FILENO, file, fstatus);
497 else
499 int fd = open (file, O_RDONLY | O_BINARY);
500 if (fd == -1)
502 error (0, errno, "%s", file);
503 return false;
505 else
507 bool ok = wc (fd, file, fstatus);
508 if (close (fd) != 0)
510 error (0, errno, "%s", file);
511 return false;
513 return ok;
518 /* Return the file status for the NFILES files addressed by FILE.
519 Optimize the case where only one number is printed, for just one
520 file; in that case we can use a print width of 1, so we don't need
521 to stat the file. Handle the case of (nfiles == 0) in the same way;
522 that happens when we don't know how long the list of file names will be. */
524 static struct fstatus *
525 get_input_fstatus (int nfiles, char *const *file)
527 struct fstatus *fstatus = xnmalloc (nfiles ? nfiles : 1, sizeof *fstatus);
529 if (nfiles == 0
530 || (nfiles == 1
531 && ((print_lines + print_words + print_chars
532 + print_bytes + print_linelength)
533 == 1)))
534 fstatus[0].failed = 1;
535 else
537 int i;
539 for (i = 0; i < nfiles; i++)
540 fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
541 ? fstat (STDIN_FILENO, &fstatus[i].st)
542 : stat (file[i], &fstatus[i].st));
545 return fstatus;
548 /* Return a print width suitable for the NFILES files whose status is
549 recorded in FSTATUS. Optimize the same special case that
550 get_input_fstatus optimizes. */
552 static int
553 compute_number_width (int nfiles, struct fstatus const *fstatus)
555 int width = 1;
557 if (0 < nfiles && fstatus[0].failed <= 0)
559 int minimum_width = 1;
560 uintmax_t regular_total = 0;
561 int i;
563 for (i = 0; i < nfiles; i++)
564 if (! fstatus[i].failed)
566 if (S_ISREG (fstatus[i].st.st_mode))
567 regular_total += fstatus[i].st.st_size;
568 else
569 minimum_width = 7;
572 for (; 10 <= regular_total; regular_total /= 10)
573 width++;
574 if (width < minimum_width)
575 width = minimum_width;
578 return width;
583 main (int argc, char **argv)
585 bool ok;
586 int optc;
587 int nfiles;
588 char **files;
589 char *files_from = NULL;
590 struct fstatus *fstatus;
591 struct Tokens tok;
593 initialize_main (&argc, &argv);
594 set_program_name (argv[0]);
595 setlocale (LC_ALL, "");
596 bindtextdomain (PACKAGE, LOCALEDIR);
597 textdomain (PACKAGE);
599 atexit (close_stdout);
601 print_lines = print_words = print_chars = print_bytes = false;
602 print_linelength = false;
603 total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
605 while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
606 switch (optc)
608 case 'c':
609 print_bytes = true;
610 break;
612 case 'm':
613 print_chars = true;
614 break;
616 case 'l':
617 print_lines = true;
618 break;
620 case 'w':
621 print_words = true;
622 break;
624 case 'L':
625 print_linelength = true;
626 break;
628 case FILES0_FROM_OPTION:
629 files_from = optarg;
630 break;
632 case_GETOPT_HELP_CHAR;
634 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
636 default:
637 usage (EXIT_FAILURE);
640 if (! (print_lines | print_words | print_chars | print_bytes
641 | print_linelength))
642 print_lines = print_words = print_bytes = true;
644 bool read_tokens = false;
645 struct argv_iterator *ai;
646 if (files_from)
648 FILE *stream;
650 /* When using --files0-from=F, you may not specify any files
651 on the command-line. */
652 if (optind < argc)
654 error (0, 0, _("extra operand %s"), quote (argv[optind]));
655 fprintf (stderr, "%s\n",
656 _("file operands cannot be combined with --files0-from"));
657 usage (EXIT_FAILURE);
660 if (STREQ (files_from, "-"))
661 stream = stdin;
662 else
664 stream = fopen (files_from, "r");
665 if (stream == NULL)
666 error (EXIT_FAILURE, errno, _("cannot open %s for reading"),
667 quote (files_from));
670 /* Read the file list into RAM if we can detect its size and that
671 size is reasonable. Otherwise, we'll read a name at a time. */
672 struct stat st;
673 if (fstat (fileno (stream), &st) == 0
674 && S_ISREG (st.st_mode)
675 && st.st_size <= MIN (10 * 1024 * 1024, physmem_available () / 2))
677 read_tokens = true;
678 readtokens0_init (&tok);
679 if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
680 error (EXIT_FAILURE, 0, _("cannot read file names from %s"),
681 quote (files_from));
682 files = tok.tok;
683 nfiles = tok.n_tok;
684 ai = argv_iter_init_argv (files);
686 else
688 files = NULL;
689 nfiles = 0;
690 ai = argv_iter_init_stream (stream);
693 else
695 static char *stdin_only[] = { NULL };
696 files = (optind < argc ? argv + optind : stdin_only);
697 nfiles = (optind < argc ? argc - optind : 1);
698 ai = argv_iter_init_argv (files);
701 fstatus = get_input_fstatus (nfiles, files);
702 number_width = compute_number_width (nfiles, fstatus);
704 int i;
705 ok = true;
706 for (i = 0; /* */; i++)
708 bool skip_file = false;
709 enum argv_iter_err ai_err;
710 char *file_name = argv_iter (ai, &ai_err);
711 if (ai_err == AI_ERR_EOF)
712 break;
713 if (!file_name)
715 switch (ai_err)
717 case AI_ERR_READ:
718 error (0, errno, _("%s: read error"), quote (files_from));
719 skip_file = true;
720 continue;
721 case AI_ERR_MEM:
722 xalloc_die ();
723 default:
724 assert (!"unexpected error code from argv_iter");
727 if (files_from && STREQ (files_from, "-") && STREQ (file_name, "-"))
729 /* Give a better diagnostic in an unusual case:
730 printf - | wc --files0-from=- */
731 error (0, 0, _("when reading file names from stdin, "
732 "no file name of %s allowed"),
733 quote (file_name));
734 skip_file = true;
737 if (!file_name[0])
739 /* Diagnose a zero-length file name. When it's one
740 among many, knowing the record number may help.
741 FIXME: currently print the record number only with
742 --files0-from=FILE. Maybe do it for argv, too? */
743 if (files_from == NULL)
744 error (0, 0, "%s", _("invalid zero-length file name"));
745 else
747 /* Using the standard `filename:line-number:' prefix here is
748 not totally appropriate, since NUL is the separator, not NL,
749 but it might be better than nothing. */
750 unsigned long int file_number = argv_iter_n_args (ai);
751 error (0, 0, "%s:%lu: %s", quotearg_colon (files_from),
752 file_number, _("invalid zero-length file name"));
754 skip_file = true;
757 if (skip_file)
758 ok = false;
759 else
760 ok &= wc_file (file_name, &fstatus[nfiles ? i : 0]);
763 /* No arguments on the command line is fine. That means read from stdin.
764 However, no arguments on the --files0-from input stream is an error
765 means don't read anything. */
766 if (ok && !files_from && argv_iter_n_args (ai) == 0)
767 ok &= wc_file (NULL, &fstatus[0]);
769 if (read_tokens)
770 readtokens0_free (&tok);
772 if (1 < argv_iter_n_args (ai))
773 write_counts (total_lines, total_words, total_chars, total_bytes,
774 max_line_length, _("total"));
776 argv_iter_free (ai);
778 free (fstatus);
780 if (have_read_stdin && close (STDIN_FILENO) != 0)
781 error (EXIT_FAILURE, errno, "-");
783 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);