.
[coreutils.git] / src / wc.c
blob091c04386fbb21953fa4e7c3746c0f63f0859025
1 /* wc - print the number of bytes, words, and lines in files
2 Copyright (C) 85, 91, 1995-2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 /* Get mbstate_t, mbrtowc(), wcwidth(). */
28 #if HAVE_WCHAR_H
29 # include <wchar.h>
30 #endif
32 /* Get iswprint(), iswspace(). */
33 #if HAVE_WCTYPE_H
34 # include <wctype.h>
35 #endif
36 #if !defined iswprint && !HAVE_ISWPRINT
37 # define iswprint(wc) 1
38 #endif
39 #if !defined iswspace && !HAVE_ISWSPACE
40 # define iswspace(wc) \
41 ((wc) == (unsigned char) (wc) && ISSPACE ((unsigned char) (wc)))
42 #endif
44 /* Include this after wctype.h so that we `#undef' ISPRINT
45 (from Solaris's euc.h, from widec.h, from wctype.h) before
46 redefining and using it. */
47 #include "system.h"
49 #include "error.h"
50 #include "inttostr.h"
51 #include "safe-read.h"
53 /* Some systems, like BeOS, have multibyte encodings but lack mbstate_t. */
54 #if HAVE_MBRTOWC && defined mbstate_t
55 # define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
56 #endif
58 #ifndef HAVE_DECL_WCWIDTH
59 "this configure-time declaration test was not run"
60 #endif
61 #if !HAVE_DECL_WCWIDTH
62 extern int wcwidth ();
63 #endif
65 /* If wcwidth() doesn't exist, assume all printable characters have
66 width 1. */
67 #if !defined wcwidth && !HAVE_WCWIDTH
68 # define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1)
69 #endif
71 /* The official name of this program (e.g., no `g' prefix). */
72 #define PROGRAM_NAME "wc"
74 #define AUTHORS "Paul Rubin", "David MacKenzie"
76 /* Size of atomic reads. */
77 #define BUFFER_SIZE (16 * 1024)
79 /* The name this program was run with. */
80 char *program_name;
82 /* Cumulative number of lines, words, chars and bytes in all files so far.
83 max_line_length is the maximum over all files processed so far. */
84 static uintmax_t total_lines;
85 static uintmax_t total_words;
86 static uintmax_t total_chars;
87 static uintmax_t total_bytes;
88 static uintmax_t max_line_length;
90 /* Which counts to print. */
91 static int print_lines, print_words, print_chars, print_bytes;
92 static int print_linelength;
94 /* The print width of each count. */
95 static int number_width;
97 /* Nonzero if we have ever read the standard input. */
98 static int have_read_stdin;
100 /* The error code to return to the system. */
101 static int exit_status;
103 /* The result of calling fstat or stat on a file descriptor or file. */
104 struct fstatus
106 /* If positive, fstat or stat has not been called yet. Otherwise,
107 this is the value returned from fstat or stat. */
108 int failed;
110 /* If FAILED is zero, this is the file's status. */
111 struct stat st;
115 static struct option const longopts[] =
117 {"bytes", no_argument, NULL, 'c'},
118 {"chars", no_argument, NULL, 'm'},
119 {"lines", no_argument, NULL, 'l'},
120 {"words", no_argument, NULL, 'w'},
121 {"max-line-length", no_argument, NULL, 'L'},
122 {GETOPT_HELP_OPTION_DECL},
123 {GETOPT_VERSION_OPTION_DECL},
124 {NULL, 0, NULL, 0}
127 void
128 usage (int status)
130 if (status != EXIT_SUCCESS)
131 fprintf (stderr, _("Try `%s --help' for more information.\n"),
132 program_name);
133 else
135 printf (_("\
136 Usage: %s [OPTION]... [FILE]...\n\
138 program_name);
139 fputs (_("\
140 Print newline, word, and byte counts for each FILE, and a total line if\n\
141 more than one FILE is specified. With no FILE, or when FILE is -,\n\
142 read standard input.\n\
143 -c, --bytes print the byte counts\n\
144 -m, --chars print the character counts\n\
145 -l, --lines print the newline counts\n\
146 "), stdout);
147 fputs (_("\
148 -L, --max-line-length print the length of the longest line\n\
149 -w, --words print the word counts\n\
150 "), stdout);
151 fputs (HELP_OPTION_DESCRIPTION, stdout);
152 fputs (VERSION_OPTION_DESCRIPTION, stdout);
153 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
155 exit (status);
158 /* FILE is the name of the file (or NULL for standard input)
159 associated with the specified counters. */
160 static void
161 write_counts (uintmax_t lines,
162 uintmax_t words,
163 uintmax_t chars,
164 uintmax_t bytes,
165 uintmax_t linelength,
166 const char *file)
168 static char const format_sp_int[] = " %*s";
169 char const *format_int = format_sp_int + 1;
170 char buf[INT_BUFSIZE_BOUND (uintmax_t)];
172 if (print_lines)
174 printf (format_int, number_width, umaxtostr (lines, buf));
175 format_int = format_sp_int;
177 if (print_words)
179 printf (format_int, number_width, umaxtostr (words, buf));
180 format_int = format_sp_int;
182 if (print_chars)
184 printf (format_int, number_width, umaxtostr (chars, buf));
185 format_int = format_sp_int;
187 if (print_bytes)
189 printf (format_int, number_width, umaxtostr (bytes, buf));
190 format_int = format_sp_int;
192 if (print_linelength)
194 printf (format_int, number_width, umaxtostr (linelength, buf));
196 if (file)
197 printf (" %s", file);
198 putchar ('\n');
201 /* FILE_X is the name of the file (or NULL for standard input) that is
202 open on descriptor FD. */
203 static void
204 wc (int fd, char const *file_x, struct fstatus *fstatus)
206 char buf[BUFFER_SIZE + 1];
207 size_t bytes_read;
208 uintmax_t lines, words, chars, bytes, linelength;
209 int count_bytes, count_chars, count_complicated;
210 char const *file = file_x ? file_x : _("standard input");
212 lines = words = chars = bytes = linelength = 0;
214 /* If in the current locale, chars are equivalent to bytes, we prefer
215 counting bytes, because that's easier. */
216 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
217 if (MB_CUR_MAX > 1)
219 count_bytes = print_bytes;
220 count_chars = print_chars;
222 else
223 #endif
225 count_bytes = print_bytes + print_chars;
226 count_chars = 0;
228 count_complicated = print_words + print_linelength;
230 /* We need binary input, since `wc' relies on `lseek' and byte counts. */
231 SET_BINARY (fd);
233 /* When counting only bytes, save some line- and word-counting
234 overhead. If FD is a `regular' Unix file, using lseek is enough
235 to get its `size' in bytes. Otherwise, read blocks of BUFFER_SIZE
236 bytes at a time until EOF. Note that the `size' (number of bytes)
237 that wc reports is smaller than stats.st_size when the file is not
238 positioned at its beginning. That's why the lseek calls below are
239 necessary. For example the command
240 `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
241 should make wc report `0' bytes. */
243 if (count_bytes && !count_chars && !print_lines && !count_complicated)
245 off_t current_pos, end_pos;
247 if (0 < fstatus->failed)
248 fstatus->failed = fstat (fd, &fstatus->st);
250 if (! fstatus->failed && S_ISREG (fstatus->st.st_mode)
251 && (current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
252 && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
254 /* Be careful here. The current position may actually be
255 beyond the end of the file. As in the example above. */
256 bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
258 else
260 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
262 if (bytes_read == SAFE_READ_ERROR)
264 error (0, errno, "%s", file);
265 exit_status = 1;
266 break;
268 bytes += bytes_read;
272 else if (!count_chars && !count_complicated)
274 /* Use a separate loop when counting only lines or lines and bytes --
275 but not chars or words. */
276 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
278 register char *p = buf;
280 if (bytes_read == SAFE_READ_ERROR)
282 error (0, errno, "%s", file);
283 exit_status = 1;
284 break;
287 while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
289 ++p;
290 ++lines;
292 bytes += bytes_read;
295 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
296 # define SUPPORT_OLD_MBRTOWC 1
297 else if (MB_CUR_MAX > 1)
299 int in_word = 0;
300 uintmax_t linepos = 0;
301 mbstate_t state;
302 uintmax_t last_error_line = 0;
303 int last_error_errno = 0;
304 # if SUPPORT_OLD_MBRTOWC
305 /* Back-up the state before each multibyte character conversion and
306 move the last incomplete character of the buffer to the front
307 of the buffer. This is needed because we don't know whether
308 the `mbrtowc' function updates the state when it returns -2, -
309 this is the ISO C 99 and glibc-2.2 behaviour - or not - amended
310 ANSI C, glibc-2.1 and Solaris 5.7 behaviour. We don't have an
311 autoconf test for this, yet. */
312 size_t prev = 0; /* number of bytes carried over from previous round */
313 # else
314 const size_t prev = 0;
315 # endif
317 memset (&state, 0, sizeof (mbstate_t));
318 while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
320 const char *p;
321 # if SUPPORT_OLD_MBRTOWC
322 mbstate_t backup_state;
323 # endif
324 if (bytes_read == SAFE_READ_ERROR)
326 error (0, errno, "%s", file);
327 exit_status = 1;
328 break;
331 bytes += bytes_read;
332 p = buf;
333 bytes_read += prev;
336 wchar_t wide_char;
337 size_t n;
339 # if SUPPORT_OLD_MBRTOWC
340 backup_state = state;
341 # endif
342 n = mbrtowc (&wide_char, p, bytes_read, &state);
343 if (n == (size_t) -2)
345 # if SUPPORT_OLD_MBRTOWC
346 state = backup_state;
347 # endif
348 break;
350 if (n == (size_t) -1)
352 /* Signal repeated errors only once per line. */
353 if (!(lines + 1 == last_error_line
354 && errno == last_error_errno))
356 char line_number_buf[INT_BUFSIZE_BOUND (uintmax_t)];
357 last_error_line = lines + 1;
358 last_error_errno = errno;
359 error (0, errno, "%s:%s", file,
360 umaxtostr (last_error_line, line_number_buf));
362 p++;
363 bytes_read--;
365 else
367 if (n == 0)
369 wide_char = 0;
370 n = 1;
372 p += n;
373 bytes_read -= n;
374 chars++;
375 switch (wide_char)
377 case '\n':
378 lines++;
379 /* Fall through. */
380 case '\r':
381 case '\f':
382 if (linepos > linelength)
383 linelength = linepos;
384 linepos = 0;
385 goto mb_word_separator;
386 case '\t':
387 linepos += 8 - (linepos % 8);
388 goto mb_word_separator;
389 case ' ':
390 linepos++;
391 /* Fall through. */
392 case '\v':
393 mb_word_separator:
394 if (in_word)
396 in_word = 0;
397 words++;
399 break;
400 default:
401 if (iswprint (wide_char))
403 int width = wcwidth (wide_char);
404 if (width > 0)
405 linepos += width;
406 if (iswspace (wide_char))
407 goto mb_word_separator;
408 in_word = 1;
410 break;
414 while (bytes_read > 0);
416 # if SUPPORT_OLD_MBRTOWC
417 if (bytes_read > 0)
419 if (bytes_read == BUFFER_SIZE)
421 /* Encountered a very long redundant shift sequence. */
422 p++;
423 bytes_read--;
425 memmove (buf, p, bytes_read);
427 prev = bytes_read;
428 # endif
430 if (linepos > linelength)
431 linelength = linepos;
432 if (in_word)
433 words++;
435 #endif
436 else
438 int in_word = 0;
439 uintmax_t linepos = 0;
441 while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
443 const char *p = buf;
444 if (bytes_read == SAFE_READ_ERROR)
446 error (0, errno, "%s", file);
447 exit_status = 1;
448 break;
451 bytes += bytes_read;
454 switch (*p++)
456 case '\n':
457 lines++;
458 /* Fall through. */
459 case '\r':
460 case '\f':
461 if (linepos > linelength)
462 linelength = linepos;
463 linepos = 0;
464 goto word_separator;
465 case '\t':
466 linepos += 8 - (linepos % 8);
467 goto word_separator;
468 case ' ':
469 linepos++;
470 /* Fall through. */
471 case '\v':
472 word_separator:
473 if (in_word)
475 in_word = 0;
476 words++;
478 break;
479 default:
480 if (ISPRINT ((unsigned char) p[-1]))
482 linepos++;
483 if (ISSPACE ((unsigned char) p[-1]))
484 goto word_separator;
485 in_word = 1;
487 break;
490 while (--bytes_read);
492 if (linepos > linelength)
493 linelength = linepos;
494 if (in_word)
495 words++;
498 if (count_chars < print_chars)
499 chars = bytes;
501 write_counts (lines, words, chars, bytes, linelength, file_x);
502 total_lines += lines;
503 total_words += words;
504 total_chars += chars;
505 total_bytes += bytes;
506 if (linelength > max_line_length)
507 max_line_length = linelength;
510 static void
511 wc_file (char const *file, struct fstatus *fstatus)
513 if (STREQ (file, "-"))
515 have_read_stdin = 1;
516 wc (STDIN_FILENO, file, fstatus);
518 else
520 int fd = open (file, O_RDONLY);
521 if (fd == -1)
523 error (0, errno, "%s", file);
524 exit_status = 1;
525 return;
527 wc (fd, file, fstatus);
528 if (close (fd))
530 error (0, errno, "%s", file);
531 exit_status = 1;
536 /* Return the file status for the NFILES files addressed by FILE.
537 Optimize the case where only one number is printed, for just one
538 file; in that case we can use a print width of 1, so we don't need
539 to stat the file. */
541 static struct fstatus *
542 get_input_fstatus (int nfiles, char * const *file)
544 struct fstatus *fstatus = xmalloc (nfiles * sizeof *fstatus);
546 if (nfiles == 1
547 && ((print_lines + print_words + print_chars
548 + print_bytes + print_linelength)
549 == 1))
550 fstatus[0].failed = 1;
551 else
553 int i;
555 for (i = 0; i < nfiles; i++)
556 fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
557 ? fstat (STDIN_FILENO, &fstatus[i].st)
558 : stat (file[i], &fstatus[i].st));
561 return fstatus;
564 /* Return a print width suitable for the NFILES files whose status is
565 recorded in FSTATUS. Optimize the same special case that
566 get_input_fstatus optimizes. */
568 static int
569 compute_number_width (int nfiles, struct fstatus const *fstatus)
571 int width = 1;
573 if (fstatus[0].failed <= 0)
575 int minimum_width = 1;
576 uintmax_t regular_total = 0;
577 int i;
579 for (i = 0; i < nfiles; i++)
580 if (! fstatus[i].failed)
582 if (S_ISREG (fstatus[i].st.st_mode))
583 regular_total += fstatus[i].st.st_size;
584 else
585 minimum_width = 7;
588 for (; 10 <= regular_total; regular_total /= 10)
589 width++;
590 if (width < minimum_width)
591 width = minimum_width;
594 return width;
599 main (int argc, char **argv)
601 int optc;
602 int nfiles;
603 struct fstatus *fstatus;
605 initialize_main (&argc, &argv);
606 program_name = argv[0];
607 setlocale (LC_ALL, "");
608 bindtextdomain (PACKAGE, LOCALEDIR);
609 textdomain (PACKAGE);
611 atexit (close_stdout);
613 exit_status = 0;
614 print_lines = print_words = print_chars = print_bytes = print_linelength = 0;
615 total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
617 while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
618 switch (optc)
620 case 0:
621 break;
623 case 'c':
624 print_bytes = 1;
625 break;
627 case 'm':
628 print_chars = 1;
629 break;
631 case 'l':
632 print_lines = 1;
633 break;
635 case 'w':
636 print_words = 1;
637 break;
639 case 'L':
640 print_linelength = 1;
641 break;
643 case_GETOPT_HELP_CHAR;
645 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
647 default:
648 usage (EXIT_FAILURE);
651 if (print_lines + print_words + print_chars + print_bytes + print_linelength
652 == 0)
653 print_lines = print_words = print_bytes = 1;
655 nfiles = argc - optind;
656 nfiles += (nfiles == 0);
658 fstatus = get_input_fstatus (nfiles, argv + optind);
659 number_width = compute_number_width (nfiles, fstatus);
661 if (! argv[optind])
663 have_read_stdin = 1;
664 wc (STDIN_FILENO, NULL, &fstatus[0]);
666 else
668 int i;
669 for (i = 0; i < nfiles; i++)
670 wc_file (argv[optind + i], &fstatus[i]);
672 if (nfiles > 1)
673 write_counts (total_lines, total_words, total_chars, total_bytes,
674 max_line_length, _("total"));
677 free (fstatus);
679 if (have_read_stdin && close (STDIN_FILENO) != 0)
680 error (EXIT_FAILURE, errno, "-");
682 exit (exit_status == 0 ? EXIT_SUCCESS : EXIT_FAILURE);