*** empty log message ***
[coreutils.git] / src / wc.c
blob332f32dc4a57327fbbc69c63ef340df44c5e5079
1 /* wc - print the number of lines, words, and bytes in files
2 Copyright (C) 85, 91, 1995-2006 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 2, or (at your option)
7 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, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18 /* Written by Paul Rubin, phr@ocf.berkeley.edu
19 and David MacKenzie, djm@gnu.ai.mit.edu. */
21 #include <config.h>
23 #include <stdio.h>
24 #include <getopt.h>
25 #include <sys/types.h>
27 #include "system.h"
28 #include "error.h"
29 #include "inttostr.h"
30 #include "quote.h"
31 #include "readtokens0.h"
32 #include "safe-read.h"
33 #include "wcwidth.h"
35 #if !defined iswspace && !HAVE_ISWSPACE
36 # define iswspace(wc) \
37 ((wc) == to_uchar (wc) && isspace (to_uchar (wc)))
38 #endif
40 /* The official name of this program (e.g., no `g' prefix). */
41 #define PROGRAM_NAME "wc"
43 #define AUTHORS "Paul Rubin", "David MacKenzie"
45 /* Size of atomic reads. */
46 #define BUFFER_SIZE (16 * 1024)
48 /* The name this program was run with. */
49 char *program_name;
51 /* Cumulative number of lines, words, chars and bytes in all files so far.
52 max_line_length is the maximum over all files processed so far. */
53 static uintmax_t total_lines;
54 static uintmax_t total_words;
55 static uintmax_t total_chars;
56 static uintmax_t total_bytes;
57 static uintmax_t max_line_length;
59 /* Which counts to print. */
60 static bool print_lines, print_words, print_chars, print_bytes;
61 static bool print_linelength;
63 /* The print width of each count. */
64 static int number_width;
66 /* True if we have ever read the standard input. */
67 static bool have_read_stdin;
69 /* The result of calling fstat or stat on a file descriptor or file. */
70 struct fstatus
72 /* If positive, fstat or stat has not been called yet. Otherwise,
73 this is the value returned from fstat or stat. */
74 int failed;
76 /* If FAILED is zero, this is the file's status. */
77 struct stat st;
80 /* For long options that have no equivalent short option, use a
81 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
82 enum
84 FILES0_FROM_OPTION = CHAR_MAX + 1
87 static struct option const longopts[] =
89 {"bytes", no_argument, NULL, 'c'},
90 {"chars", no_argument, NULL, 'm'},
91 {"lines", no_argument, NULL, 'l'},
92 {"words", no_argument, NULL, 'w'},
93 {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
94 {"max-line-length", no_argument, NULL, 'L'},
95 {GETOPT_HELP_OPTION_DECL},
96 {GETOPT_VERSION_OPTION_DECL},
97 {NULL, 0, NULL, 0}
100 void
101 usage (int status)
103 if (status != EXIT_SUCCESS)
104 fprintf (stderr, _("Try `%s --help' for more information.\n"),
105 program_name);
106 else
108 printf (_("\
109 Usage: %s [OPTION]... [FILE]...\n\
110 or: %s [OPTION]... --files0-from=F\n\
112 program_name, program_name);
113 fputs (_("\
114 Print newline, word, and byte counts for each FILE, and a total line if\n\
115 more than one FILE is specified. With no FILE, or when FILE is -,\n\
116 read standard input.\n\
117 -c, --bytes print the byte counts\n\
118 -m, --chars print the character counts\n\
119 -l, --lines print the newline counts\n\
120 "), stdout);
121 fputs (_("\
122 --files0-from=F read input from the files specified by\n\
123 NUL-terminated names in file F\n\
124 -L, --max-line-length print the length of the longest line\n\
125 -w, --words print the word counts\n\
126 "), stdout);
127 fputs (HELP_OPTION_DESCRIPTION, stdout);
128 fputs (VERSION_OPTION_DESCRIPTION, stdout);
129 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
131 exit (status);
134 /* FILE is the name of the file (or NULL for standard input)
135 associated with the specified counters. */
136 static void
137 write_counts (uintmax_t lines,
138 uintmax_t words,
139 uintmax_t chars,
140 uintmax_t bytes,
141 uintmax_t linelength,
142 const char *file)
144 static char const format_sp_int[] = " %*s";
145 char const *format_int = format_sp_int + 1;
146 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
148 if (print_lines)
150 printf (format_int, number_width, umaxtostr (lines, buf));
151 format_int = format_sp_int;
153 if (print_words)
155 printf (format_int, number_width, umaxtostr (words, buf));
156 format_int = format_sp_int;
158 if (print_chars)
160 printf (format_int, number_width, umaxtostr (chars, buf));
161 format_int = format_sp_int;
163 if (print_bytes)
165 printf (format_int, number_width, umaxtostr (bytes, buf));
166 format_int = format_sp_int;
168 if (print_linelength)
170 printf (format_int, number_width, umaxtostr (linelength, buf));
172 if (file)
173 printf (" %s", file);
174 putchar ('\n');
177 /* Count words. FILE_X is the name of the file (or NULL for standard
178 input) that is open on descriptor FD. *FSTATUS is its status.
179 Return true if successful. */
180 static bool
181 wc (int fd, char const *file_x, struct fstatus *fstatus)
183 bool ok = true;
184 char buf[BUFFER_SIZE + 1];
185 size_t bytes_read;
186 uintmax_t lines, words, chars, bytes, linelength;
187 bool count_bytes, count_chars, count_complicated;
188 char const *file = file_x ? file_x : _("standard input");
190 lines = words = chars = bytes = linelength = 0;
192 /* If in the current locale, chars are equivalent to bytes, we prefer
193 counting bytes, because that's easier. */
194 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
195 if (MB_CUR_MAX > 1)
197 count_bytes = print_bytes;
198 count_chars = print_chars;
200 else
201 #endif
203 count_bytes = print_bytes | print_chars;
204 count_chars = false;
206 count_complicated = print_words | print_linelength;
208 /* When counting only bytes, save some line- and word-counting
209 overhead. If FD is a `regular' Unix file, using lseek is enough
210 to get its `size' in bytes. Otherwise, read blocks of BUFFER_SIZE
211 bytes at a time until EOF. Note that the `size' (number of bytes)
212 that wc reports is smaller than stats.st_size when the file is not
213 positioned at its beginning. That's why the lseek calls below are
214 necessary. For example the command
215 `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
216 should make wc report `0' bytes. */
218 if (count_bytes & !count_chars & !print_lines & !count_complicated)
220 off_t current_pos, end_pos;
222 if (0 < fstatus->failed)
223 fstatus->failed = fstat (fd, &fstatus->st);
225 if (! fstatus->failed && S_ISREG (fstatus->st.st_mode)
226 && (current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
227 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
229 /* Be careful here. The current position may actually be
230 beyond the end of the file. As in the example above. */
231 bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
233 else
235 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
237 if (bytes_read == SAFE_READ_ERROR)
239 error (0, errno, "%s", file);
240 ok = false;
241 break;
243 bytes += bytes_read;
247 else if (!count_chars & !count_complicated)
249 /* Use a separate loop when counting only lines or lines and bytes --
250 but not chars or words. */
251 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
253 char *p = buf;
255 if (bytes_read == SAFE_READ_ERROR)
257 error (0, errno, "%s", file);
258 ok = false;
259 break;
262 while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
264 ++p;
265 ++lines;
267 bytes += bytes_read;
270 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
271 # define SUPPORT_OLD_MBRTOWC 1
272 else if (MB_CUR_MAX > 1)
274 bool in_word = false;
275 uintmax_t linepos = 0;
276 mbstate_t state = { 0, };
277 uintmax_t last_error_line = 0;
278 int last_error_errno = 0;
279 # if SUPPORT_OLD_MBRTOWC
280 /* Back-up the state before each multibyte character conversion and
281 move the last incomplete character of the buffer to the front
282 of the buffer. This is needed because we don't know whether
283 the `mbrtowc' function updates the state when it returns -2, -
284 this is the ISO C 99 and glibc-2.2 behaviour - or not - amended
285 ANSI C, glibc-2.1 and Solaris 5.7 behaviour. We don't have an
286 autoconf test for this, yet. */
287 size_t prev = 0; /* number of bytes carried over from previous round */
288 # else
289 const size_t prev = 0;
290 # endif
292 while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
294 const char *p;
295 # if SUPPORT_OLD_MBRTOWC
296 mbstate_t backup_state;
297 # endif
298 if (bytes_read == SAFE_READ_ERROR)
300 error (0, errno, "%s", file);
301 ok = false;
302 break;
305 bytes += bytes_read;
306 p = buf;
307 bytes_read += prev;
310 wchar_t wide_char;
311 size_t n;
313 # if SUPPORT_OLD_MBRTOWC
314 backup_state = state;
315 # endif
316 n = mbrtowc (&wide_char, p, bytes_read, &state);
317 if (n == (size_t) -2)
319 # if SUPPORT_OLD_MBRTOWC
320 state = backup_state;
321 # endif
322 break;
324 if (n == (size_t) -1)
326 /* Signal repeated errors only once per line. */
327 if (!(lines + 1 == last_error_line
328 && errno == last_error_errno))
330 char line_number_buf[INT_BUFSIZE_BOUND (uintmax_t)];
331 last_error_line = lines + 1;
332 last_error_errno = errno;
333 error (0, errno, "%s:%s", file,
334 umaxtostr (last_error_line, line_number_buf));
335 ok = false;
337 p++;
338 bytes_read--;
340 else
342 if (n == 0)
344 wide_char = 0;
345 n = 1;
347 p += n;
348 bytes_read -= n;
349 chars++;
350 switch (wide_char)
352 case '\n':
353 lines++;
354 /* Fall through. */
355 case '\r':
356 case '\f':
357 if (linepos > linelength)
358 linelength = linepos;
359 linepos = 0;
360 goto mb_word_separator;
361 case '\t':
362 linepos += 8 - (linepos % 8);
363 goto mb_word_separator;
364 case ' ':
365 linepos++;
366 /* Fall through. */
367 case '\v':
368 mb_word_separator:
369 words += in_word;
370 in_word = false;
371 break;
372 default:
373 if (iswprint (wide_char))
375 int width = wcwidth (wide_char);
376 if (width > 0)
377 linepos += width;
378 if (iswspace (wide_char))
379 goto mb_word_separator;
380 in_word = true;
382 break;
386 while (bytes_read > 0);
388 # if SUPPORT_OLD_MBRTOWC
389 if (bytes_read > 0)
391 if (bytes_read == BUFFER_SIZE)
393 /* Encountered a very long redundant shift sequence. */
394 p++;
395 bytes_read--;
397 memmove (buf, p, bytes_read);
399 prev = bytes_read;
400 # endif
402 if (linepos > linelength)
403 linelength = linepos;
404 words += in_word;
406 #endif
407 else
409 bool in_word = false;
410 uintmax_t linepos = 0;
412 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
414 const char *p = buf;
415 if (bytes_read == SAFE_READ_ERROR)
417 error (0, errno, "%s", file);
418 ok = false;
419 break;
422 bytes += bytes_read;
425 switch (*p++)
427 case '\n':
428 lines++;
429 /* Fall through. */
430 case '\r':
431 case '\f':
432 if (linepos > linelength)
433 linelength = linepos;
434 linepos = 0;
435 goto word_separator;
436 case '\t':
437 linepos += 8 - (linepos % 8);
438 goto word_separator;
439 case ' ':
440 linepos++;
441 /* Fall through. */
442 case '\v':
443 word_separator:
444 words += in_word;
445 in_word = false;
446 break;
447 default:
448 if (isprint (to_uchar (p[-1])))
450 linepos++;
451 if (isspace (to_uchar (p[-1])))
452 goto word_separator;
453 in_word = true;
455 break;
458 while (--bytes_read);
460 if (linepos > linelength)
461 linelength = linepos;
462 words += in_word;
465 if (count_chars < print_chars)
466 chars = bytes;
468 write_counts (lines, words, chars, bytes, linelength, file_x);
469 total_lines += lines;
470 total_words += words;
471 total_chars += chars;
472 total_bytes += bytes;
473 if (linelength > max_line_length)
474 max_line_length = linelength;
476 return ok;
479 static bool
480 wc_file (char const *file, struct fstatus *fstatus)
482 if (! file || STREQ (file, "-"))
484 have_read_stdin = true;
485 if (O_BINARY && ! isatty (STDIN_FILENO))
486 freopen (NULL, "rb", stdin);
487 return wc (STDIN_FILENO, file, fstatus);
489 else
491 int fd = open (file, O_RDONLY | O_BINARY);
492 if (fd == -1)
494 error (0, errno, "%s", file);
495 return false;
497 else
499 bool ok = wc (fd, file, fstatus);
500 if (close (fd) != 0)
502 error (0, errno, "%s", file);
503 return false;
505 return ok;
510 /* Return the file status for the NFILES files addressed by FILE.
511 Optimize the case where only one number is printed, for just one
512 file; in that case we can use a print width of 1, so we don't need
513 to stat the file. */
515 static struct fstatus *
516 get_input_fstatus (int nfiles, char * const *file)
518 struct fstatus *fstatus = xnmalloc (nfiles, sizeof *fstatus);
520 if (nfiles == 1
521 && ((print_lines + print_words + print_chars
522 + print_bytes + print_linelength)
523 == 1))
524 fstatus[0].failed = 1;
525 else
527 int i;
529 for (i = 0; i < nfiles; i++)
530 fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
531 ? fstat (STDIN_FILENO, &fstatus[i].st)
532 : stat (file[i], &fstatus[i].st));
535 return fstatus;
538 /* Return a print width suitable for the NFILES files whose status is
539 recorded in FSTATUS. Optimize the same special case that
540 get_input_fstatus optimizes. */
542 static int
543 compute_number_width (int nfiles, struct fstatus const *fstatus)
545 int width = 1;
547 if (0 < nfiles && fstatus[0].failed <= 0)
549 int minimum_width = 1;
550 uintmax_t regular_total = 0;
551 int i;
553 for (i = 0; i < nfiles; i++)
554 if (! fstatus[i].failed)
556 if (S_ISREG (fstatus[i].st.st_mode))
557 regular_total += fstatus[i].st.st_size;
558 else
559 minimum_width = 7;
562 for (; 10 <= regular_total; regular_total /= 10)
563 width++;
564 if (width < minimum_width)
565 width = minimum_width;
568 return width;
573 main (int argc, char **argv)
575 int i;
576 bool ok;
577 int optc;
578 int nfiles;
579 char **files;
580 char *files_from = NULL;
581 struct fstatus *fstatus;
582 struct Tokens tok;
584 initialize_main (&argc, &argv);
585 program_name = argv[0];
586 setlocale (LC_ALL, "");
587 bindtextdomain (PACKAGE, LOCALEDIR);
588 textdomain (PACKAGE);
590 atexit (close_stdout);
592 print_lines = print_words = print_chars = print_bytes = false;
593 print_linelength = false;
594 total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
596 while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
597 switch (optc)
599 case 'c':
600 print_bytes = true;
601 break;
603 case 'm':
604 print_chars = true;
605 break;
607 case 'l':
608 print_lines = true;
609 break;
611 case 'w':
612 print_words = true;
613 break;
615 case 'L':
616 print_linelength = true;
617 break;
619 case FILES0_FROM_OPTION:
620 files_from = optarg;
621 break;
623 case_GETOPT_HELP_CHAR;
625 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
627 default:
628 usage (EXIT_FAILURE);
631 if (! (print_lines | print_words | print_chars | print_bytes
632 | print_linelength))
633 print_lines = print_words = print_bytes = true;
635 if (files_from)
637 FILE *stream;
639 /* When using --files0-from=F, you may not specify any files
640 on the command-line. */
641 if (optind < argc)
643 error (0, 0, _("extra operand %s"), quote (argv[optind]));
644 fprintf (stderr, "%s\n",
645 _("File operands cannot be combined with --files0-from."));
646 usage (EXIT_FAILURE);
649 if (STREQ (files_from, "-"))
650 stream = stdin;
651 else
653 stream = fopen (files_from, "r");
654 if (stream == NULL)
655 error (EXIT_FAILURE, errno, _("cannot open %s for reading"),
656 quote (files_from));
659 readtokens0_init (&tok);
661 if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
662 error (EXIT_FAILURE, 0, _("cannot read file names from %s"),
663 quote (files_from));
665 files = tok.tok;
666 nfiles = tok.n_tok;
668 else
670 static char *stdin_only[2];
671 files = (optind < argc ? argv + optind : stdin_only);
672 nfiles = (optind < argc ? argc - optind : 1);
673 stdin_only[0] = NULL;
676 fstatus = get_input_fstatus (nfiles, files);
677 number_width = compute_number_width (nfiles, fstatus);
679 ok = true;
680 for (i = 0; i < nfiles; i++)
682 if (files_from && STREQ (files_from, "-") && STREQ (files[i], "-"))
684 ok = false;
685 error (0, 0,
686 _("when reading file names from stdin, "
687 "no file name of %s allowed"),
688 quote ("-"));
689 continue;
691 ok &= wc_file (files[i], &fstatus[i]);
694 if (1 < nfiles)
695 write_counts (total_lines, total_words, total_chars, total_bytes,
696 max_line_length, _("total"));
698 free (fstatus);
700 if (have_read_stdin && close (STDIN_FILENO) != 0)
701 error (EXIT_FAILURE, errno, "-");
703 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);