add "const" attribute, where possible
[platform/upstream/coreutils.git] / src / wc.c
1 /* wc - print the number of lines, words, and bytes in files
2    Copyright (C) 85, 91, 1995-2008 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 <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Paul Rubin, phr@ocf.berkeley.edu
18    and David MacKenzie, djm@gnu.ai.mit.edu. */
19 \f
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <getopt.h>
24 #include <sys/types.h>
25 #include <wchar.h>
26 #include <wctype.h>
27
28 #include "system.h"
29 #include "error.h"
30 #include "inttostr.h"
31 #include "mbchar.h"
32 #include "quote.h"
33 #include "quotearg.h"
34 #include "readtokens0.h"
35 #include "safe-read.h"
36
37 #if !defined iswspace && !HAVE_ISWSPACE
38 # define iswspace(wc) \
39     ((wc) == to_uchar (wc) && isspace (to_uchar (wc)))
40 #endif
41
42 /* The official name of this program (e.g., no `g' prefix).  */
43 #define PROGRAM_NAME "wc"
44
45 #define AUTHORS \
46   proper_name ("Paul Rubin"), \
47   proper_name ("David MacKenzie")
48
49 /* Size of atomic reads. */
50 #define BUFFER_SIZE (16 * 1024)
51
52 /* Cumulative number of lines, words, chars and bytes in all files so far.
53    max_line_length is the maximum over all files processed so far.  */
54 static uintmax_t total_lines;
55 static uintmax_t total_words;
56 static uintmax_t total_chars;
57 static uintmax_t total_bytes;
58 static uintmax_t max_line_length;
59
60 /* Which counts to print. */
61 static bool print_lines, print_words, print_chars, print_bytes;
62 static bool print_linelength;
63
64 /* The print width of each count.  */
65 static int number_width;
66
67 /* True if we have ever read the standard input. */
68 static bool have_read_stdin;
69
70 /* The result of calling fstat or stat on a file descriptor or file.  */
71 struct fstatus
72 {
73   /* If positive, fstat or stat has not been called yet.  Otherwise,
74      this is the value returned from fstat or stat.  */
75   int failed;
76
77   /* If FAILED is zero, this is the file's status.  */
78   struct stat st;
79 };
80
81 /* For long options that have no equivalent short option, use a
82    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
83 enum
84 {
85   FILES0_FROM_OPTION = CHAR_MAX + 1
86 };
87
88 static const struct option const longopts[] =
89 {
90   {"bytes", no_argument, NULL, 'c'},
91   {"chars", no_argument, NULL, 'm'},
92   {"lines", no_argument, NULL, 'l'},
93   {"words", no_argument, NULL, 'w'},
94   {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
95   {"max-line-length", no_argument, NULL, 'L'},
96   {GETOPT_HELP_OPTION_DECL},
97   {GETOPT_VERSION_OPTION_DECL},
98   {NULL, 0, NULL, 0}
99 };
100
101 void
102 usage (int status)
103 {
104   if (status != EXIT_SUCCESS)
105     fprintf (stderr, _("Try `%s --help' for more information.\n"),
106              program_name);
107   else
108     {
109       printf (_("\
110 Usage: %s [OPTION]... [FILE]...\n\
111   or:  %s [OPTION]... --files0-from=F\n\
112 "),
113               program_name, program_name);
114       fputs (_("\
115 Print newline, word, and byte counts for each FILE, and a total line if\n\
116 more than one FILE is specified.  With no FILE, or when FILE is -,\n\
117 read standard input.\n\
118   -c, --bytes            print the byte counts\n\
119   -m, --chars            print the character counts\n\
120   -l, --lines            print the newline counts\n\
121 "), stdout);
122       fputs (_("\
123       --files0-from=F    read input from the files specified by\n\
124                            NUL-terminated names in file F\n\
125   -L, --max-line-length  print the length of the longest line\n\
126   -w, --words            print the word counts\n\
127 "), stdout);
128       fputs (HELP_OPTION_DESCRIPTION, stdout);
129       fputs (VERSION_OPTION_DESCRIPTION, stdout);
130       emit_bug_reporting_address ();
131     }
132   exit (status);
133 }
134
135 /* FILE is the name of the file (or NULL for standard input)
136    associated with the specified counters.  */
137 static void
138 write_counts (uintmax_t lines,
139               uintmax_t words,
140               uintmax_t chars,
141               uintmax_t bytes,
142               uintmax_t linelength,
143               const char *file)
144 {
145   static char const format_sp_int[] = " %*s";
146   char const *format_int = format_sp_int + 1;
147   char buf[INT_BUFSIZE_BOUND (uintmax_t)];
148
149   if (print_lines)
150     {
151       printf (format_int, number_width, umaxtostr (lines, buf));
152       format_int = format_sp_int;
153     }
154   if (print_words)
155     {
156       printf (format_int, number_width, umaxtostr (words, buf));
157       format_int = format_sp_int;
158     }
159   if (print_chars)
160     {
161       printf (format_int, number_width, umaxtostr (chars, buf));
162       format_int = format_sp_int;
163     }
164   if (print_bytes)
165     {
166       printf (format_int, number_width, umaxtostr (bytes, buf));
167       format_int = format_sp_int;
168     }
169   if (print_linelength)
170     {
171       printf (format_int, number_width, umaxtostr (linelength, buf));
172     }
173   if (file)
174     printf (" %s", file);
175   putchar ('\n');
176 }
177
178 /* Count words.  FILE_X is the name of the file (or NULL for standard
179    input) that is open on descriptor FD.  *FSTATUS is its status.
180    Return true if successful.  */
181 static bool
182 wc (int fd, char const *file_x, struct fstatus *fstatus)
183 {
184   bool ok = true;
185   char buf[BUFFER_SIZE + 1];
186   size_t bytes_read;
187   uintmax_t lines, words, chars, bytes, linelength;
188   bool count_bytes, count_chars, count_complicated;
189   char const *file = file_x ? file_x : _("standard input");
190
191   lines = words = chars = bytes = linelength = 0;
192
193   /* If in the current locale, chars are equivalent to bytes, we prefer
194      counting bytes, because that's easier.  */
195 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
196   if (MB_CUR_MAX > 1)
197     {
198       count_bytes = print_bytes;
199       count_chars = print_chars;
200     }
201   else
202 #endif
203     {
204       count_bytes = print_bytes | print_chars;
205       count_chars = false;
206     }
207   count_complicated = print_words | print_linelength;
208
209   /* When counting only bytes, save some line- and word-counting
210      overhead.  If FD is a `regular' Unix file, using lseek is enough
211      to get its `size' in bytes.  Otherwise, read blocks of BUFFER_SIZE
212      bytes at a time until EOF.  Note that the `size' (number of bytes)
213      that wc reports is smaller than stats.st_size when the file is not
214      positioned at its beginning.  That's why the lseek calls below are
215      necessary.  For example the command
216      `(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group'
217      should make wc report `0' bytes.  */
218
219   if (count_bytes & !count_chars & !print_lines & !count_complicated)
220     {
221       off_t current_pos, end_pos;
222
223       if (0 < fstatus->failed)
224         fstatus->failed = fstat (fd, &fstatus->st);
225
226       if (! fstatus->failed && S_ISREG (fstatus->st.st_mode)
227           && (current_pos = lseek (fd, (off_t) 0, SEEK_CUR)) != -1
228           && (end_pos = lseek (fd, (off_t) 0, SEEK_END)) != -1)
229         {
230           /* Be careful here.  The current position may actually be
231              beyond the end of the file.  As in the example above.  */
232           bytes = end_pos < current_pos ? 0 : end_pos - current_pos;
233         }
234       else
235         {
236           while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
237             {
238               if (bytes_read == SAFE_READ_ERROR)
239                 {
240                   error (0, errno, "%s", file);
241                   ok = false;
242                   break;
243                 }
244               bytes += bytes_read;
245             }
246         }
247     }
248   else if (!count_chars & !count_complicated)
249     {
250       /* Use a separate loop when counting only lines or lines and bytes --
251          but not chars or words.  */
252       while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
253         {
254           char *p = buf;
255
256           if (bytes_read == SAFE_READ_ERROR)
257             {
258               error (0, errno, "%s", file);
259               ok = false;
260               break;
261             }
262
263           while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
264             {
265               ++p;
266               ++lines;
267             }
268           bytes += bytes_read;
269         }
270     }
271 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
272 # define SUPPORT_OLD_MBRTOWC 1
273   else if (MB_CUR_MAX > 1)
274     {
275       bool in_word = false;
276       uintmax_t linepos = 0;
277       mbstate_t state = { 0, };
278       bool in_shift = false;
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
291
292       while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
293         {
294           const char *p;
295 # if SUPPORT_OLD_MBRTOWC
296           mbstate_t backup_state;
297 # endif
298           if (bytes_read == SAFE_READ_ERROR)
299             {
300               error (0, errno, "%s", file);
301               ok = false;
302               break;
303             }
304
305           bytes += bytes_read;
306           p = buf;
307           bytes_read += prev;
308           do
309             {
310               wchar_t wide_char;
311               size_t n;
312
313               if (!in_shift && is_basic (*p))
314                 {
315                   /* Handle most ASCII characters quickly, without calling
316                      mbrtowc().  */
317                   n = 1;
318                   wide_char = *p;
319                 }
320               else
321                 {
322                   in_shift = true;
323 # if SUPPORT_OLD_MBRTOWC
324                   backup_state = state;
325 # endif
326                   n = mbrtowc (&wide_char, p, bytes_read, &state);
327                   if (n == (size_t) -2)
328                     {
329 # if SUPPORT_OLD_MBRTOWC
330                       state = backup_state;
331 # endif
332                       break;
333                     }
334                   if (n == (size_t) -1)
335                     {
336                       /* Remember that we read a byte, but don't complain
337                          about the error.  Because of the decoding error,
338                          this is a considered to be byte but not a
339                          character (that is, chars is not incremented).  */
340                       p++;
341                       bytes_read--;
342                       continue;
343                     }
344                   if (mbsinit (&state))
345                     in_shift = false;
346                   if (n == 0)
347                     {
348                       wide_char = 0;
349                       n = 1;
350                     }
351                 }
352               p += n;
353               bytes_read -= n;
354               chars++;
355               switch (wide_char)
356                 {
357                 case '\n':
358                   lines++;
359                   /* Fall through. */
360                 case '\r':
361                 case '\f':
362                   if (linepos > linelength)
363                     linelength = linepos;
364                   linepos = 0;
365                   goto mb_word_separator;
366                 case '\t':
367                   linepos += 8 - (linepos % 8);
368                   goto mb_word_separator;
369                 case ' ':
370                   linepos++;
371                   /* Fall through. */
372                 case '\v':
373                 mb_word_separator:
374                   words += in_word;
375                   in_word = false;
376                   break;
377                 default:
378                   if (iswprint (wide_char))
379                     {
380                       int width = wcwidth (wide_char);
381                       if (width > 0)
382                         linepos += width;
383                       if (iswspace (wide_char))
384                         goto mb_word_separator;
385                       in_word = true;
386                     }
387                   break;
388                 }
389             }
390           while (bytes_read > 0);
391
392 # if SUPPORT_OLD_MBRTOWC
393           if (bytes_read > 0)
394             {
395               if (bytes_read == BUFFER_SIZE)
396                 {
397                   /* Encountered a very long redundant shift sequence.  */
398                   p++;
399                   bytes_read--;
400                 }
401               memmove (buf, p, bytes_read);
402             }
403           prev = bytes_read;
404 # endif
405         }
406       if (linepos > linelength)
407         linelength = linepos;
408       words += in_word;
409     }
410 #endif
411   else
412     {
413       bool in_word = false;
414       uintmax_t linepos = 0;
415
416       while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
417         {
418           const char *p = buf;
419           if (bytes_read == SAFE_READ_ERROR)
420             {
421               error (0, errno, "%s", file);
422               ok = false;
423               break;
424             }
425
426           bytes += bytes_read;
427           do
428             {
429               switch (*p++)
430                 {
431                 case '\n':
432                   lines++;
433                   /* Fall through. */
434                 case '\r':
435                 case '\f':
436                   if (linepos > linelength)
437                     linelength = linepos;
438                   linepos = 0;
439                   goto word_separator;
440                 case '\t':
441                   linepos += 8 - (linepos % 8);
442                   goto word_separator;
443                 case ' ':
444                   linepos++;
445                   /* Fall through. */
446                 case '\v':
447                 word_separator:
448                   words += in_word;
449                   in_word = false;
450                   break;
451                 default:
452                   if (isprint (to_uchar (p[-1])))
453                     {
454                       linepos++;
455                       if (isspace (to_uchar (p[-1])))
456                         goto word_separator;
457                       in_word = true;
458                     }
459                   break;
460                 }
461             }
462           while (--bytes_read);
463         }
464       if (linepos > linelength)
465         linelength = linepos;
466       words += in_word;
467     }
468
469   if (count_chars < print_chars)
470     chars = bytes;
471
472   write_counts (lines, words, chars, bytes, linelength, file_x);
473   total_lines += lines;
474   total_words += words;
475   total_chars += chars;
476   total_bytes += bytes;
477   if (linelength > max_line_length)
478     max_line_length = linelength;
479
480   return ok;
481 }
482
483 static bool
484 wc_file (char const *file, struct fstatus *fstatus)
485 {
486   if (! file || STREQ (file, "-"))
487     {
488       have_read_stdin = true;
489       if (O_BINARY && ! isatty (STDIN_FILENO))
490         freopen (NULL, "rb", stdin);
491       return wc (STDIN_FILENO, file, fstatus);
492     }
493   else
494     {
495       int fd = open (file, O_RDONLY | O_BINARY);
496       if (fd == -1)
497         {
498           error (0, errno, "%s", file);
499           return false;
500         }
501       else
502         {
503           bool ok = wc (fd, file, fstatus);
504           if (close (fd) != 0)
505             {
506               error (0, errno, "%s", file);
507               return false;
508             }
509           return ok;
510         }
511     }
512 }
513
514 /* Return the file status for the NFILES files addressed by FILE.
515    Optimize the case where only one number is printed, for just one
516    file; in that case we can use a print width of 1, so we don't need
517    to stat the file.  */
518
519 static struct fstatus *
520 get_input_fstatus (int nfiles, char * const *file)
521 {
522   struct fstatus *fstatus = xnmalloc (nfiles, sizeof *fstatus);
523
524   if (nfiles == 1
525       && ((print_lines + print_words + print_chars
526            + print_bytes + print_linelength)
527           == 1))
528     fstatus[0].failed = 1;
529   else
530     {
531       int i;
532
533       for (i = 0; i < nfiles; i++)
534         fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
535                              ? fstat (STDIN_FILENO, &fstatus[i].st)
536                              : stat (file[i], &fstatus[i].st));
537     }
538
539   return fstatus;
540 }
541
542 /* Return a print width suitable for the NFILES files whose status is
543    recorded in FSTATUS.  Optimize the same special case that
544    get_input_fstatus optimizes.  */
545
546 static int
547 compute_number_width (int nfiles, struct fstatus const *fstatus)
548 {
549   int width = 1;
550
551   if (0 < nfiles && fstatus[0].failed <= 0)
552     {
553       int minimum_width = 1;
554       uintmax_t regular_total = 0;
555       int i;
556
557       for (i = 0; i < nfiles; i++)
558         if (! fstatus[i].failed)
559           {
560             if (S_ISREG (fstatus[i].st.st_mode))
561               regular_total += fstatus[i].st.st_size;
562             else
563               minimum_width = 7;
564           }
565
566       for (; 10 <= regular_total; regular_total /= 10)
567         width++;
568       if (width < minimum_width)
569         width = minimum_width;
570     }
571
572   return width;
573 }
574
575
576 int
577 main (int argc, char **argv)
578 {
579   int i;
580   bool ok;
581   int optc;
582   int nfiles;
583   char **files;
584   char *files_from = NULL;
585   struct fstatus *fstatus;
586   struct Tokens tok;
587
588   initialize_main (&argc, &argv);
589   set_program_name (argv[0]);
590   setlocale (LC_ALL, "");
591   bindtextdomain (PACKAGE, LOCALEDIR);
592   textdomain (PACKAGE);
593
594   atexit (close_stdout);
595
596   print_lines = print_words = print_chars = print_bytes = false;
597   print_linelength = false;
598   total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
599
600   while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
601     switch (optc)
602       {
603       case 'c':
604         print_bytes = true;
605         break;
606
607       case 'm':
608         print_chars = true;
609         break;
610
611       case 'l':
612         print_lines = true;
613         break;
614
615       case 'w':
616         print_words = true;
617         break;
618
619       case 'L':
620         print_linelength = true;
621         break;
622
623       case FILES0_FROM_OPTION:
624         files_from = optarg;
625         break;
626
627       case_GETOPT_HELP_CHAR;
628
629       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
630
631       default:
632         usage (EXIT_FAILURE);
633       }
634
635   if (! (print_lines | print_words | print_chars | print_bytes
636          | print_linelength))
637     print_lines = print_words = print_bytes = true;
638
639   if (files_from)
640     {
641       FILE *stream;
642
643       /* When using --files0-from=F, you may not specify any files
644          on the command-line.  */
645       if (optind < argc)
646         {
647           error (0, 0, _("extra operand %s"), quote (argv[optind]));
648           fprintf (stderr, "%s\n",
649                    _("file operands cannot be combined with --files0-from"));
650           usage (EXIT_FAILURE);
651         }
652
653       if (STREQ (files_from, "-"))
654         stream = stdin;
655       else
656         {
657           stream = fopen (files_from, "r");
658           if (stream == NULL)
659             error (EXIT_FAILURE, errno, _("cannot open %s for reading"),
660                    quote (files_from));
661         }
662
663       readtokens0_init (&tok);
664
665       if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
666         error (EXIT_FAILURE, 0, _("cannot read file names from %s"),
667                quote (files_from));
668
669       files = tok.tok;
670       nfiles = tok.n_tok;
671     }
672   else
673     {
674       static char *stdin_only[2];
675       files = (optind < argc ? argv + optind : stdin_only);
676       nfiles = (optind < argc ? argc - optind : 1);
677       stdin_only[0] = NULL;
678     }
679
680   fstatus = get_input_fstatus (nfiles, files);
681   number_width = compute_number_width (nfiles, fstatus);
682
683   ok = true;
684   for (i = 0; i < nfiles; i++)
685     {
686       if (files[i])
687         {
688           if (files_from && STREQ (files_from, "-") && STREQ (files[i], "-"))
689             {
690               ok = false;
691               /* Give a better diagnostic in an unusual case:
692                  printf - | wc --files0-from=- */
693               error (0, 0, _("when reading file names from stdin, "
694                              "no file name of %s allowed"),
695                      quote ("-"));
696               continue;
697             }
698
699           /* Diagnose a zero-length file name.  When it's one
700              among many, knowing the record number may help.  */
701           if (files[i][0] == '\0')
702             {
703               ok = false;
704               if (files_from)
705                 {
706                   /* Using the standard `filename:line-number:' prefix here is
707                      not totally appropriate, since NUL is the separator, not NL,
708                      but it might be better than nothing.  */
709                   unsigned long int file_number = i + 1;
710                   error (0, 0, "%s:%lu: %s", quotearg_colon (files_from),
711                          file_number, _("invalid zero-length file name"));
712                 }
713               else
714                 error (0, 0, "%s", _("invalid zero-length file name"));
715               continue;
716             }
717         }
718
719       ok &= wc_file (files[i], &fstatus[i]);
720     }
721
722   if (1 < nfiles)
723     write_counts (total_lines, total_words, total_chars, total_bytes,
724                   max_line_length, _("total"));
725
726   free (fstatus);
727
728   if (have_read_stdin && close (STDIN_FILENO) != 0)
729     error (EXIT_FAILURE, errno, "-");
730
731   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
732 }