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