Add a bootstrap procedure, so that the CVS version contains fewer
[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-2006 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 2, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Written by Paul Rubin, phr@ocf.berkeley.edu
19    and David MacKenzie, djm@gnu.ai.mit.edu. */
20 \f
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <getopt.h>
25 #include <sys/types.h>
26
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"
34
35 #if !defined iswspace && !HAVE_ISWSPACE
36 # define iswspace(wc) \
37     ((wc) == to_uchar (wc) && isspace (to_uchar (wc)))
38 #endif
39
40 /* The official name of this program (e.g., no `g' prefix).  */
41 #define PROGRAM_NAME "wc"
42
43 #define AUTHORS "Paul Rubin", "David MacKenzie"
44
45 /* Size of atomic reads. */
46 #define BUFFER_SIZE (16 * 1024)
47
48 /* The name this program was run with. */
49 char *program_name;
50
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;
58
59 /* Which counts to print. */
60 static bool print_lines, print_words, print_chars, print_bytes;
61 static bool print_linelength;
62
63 /* The print width of each count.  */
64 static int number_width;
65
66 /* True if we have ever read the standard input. */
67 static bool have_read_stdin;
68
69 /* The result of calling fstat or stat on a file descriptor or file.  */
70 struct fstatus
71 {
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;
75
76   /* If FAILED is zero, this is the file's status.  */
77   struct stat st;
78 };
79
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
83 {
84   FILES0_FROM_OPTION = CHAR_MAX + 1
85 };
86
87 static struct option const longopts[] =
88 {
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}
98 };
99
100 void
101 usage (int status)
102 {
103   if (status != EXIT_SUCCESS)
104     fprintf (stderr, _("Try `%s --help' for more information.\n"),
105              program_name);
106   else
107     {
108       printf (_("\
109 Usage: %s [OPTION]... [FILE]...\n\
110   or:  %s [OPTION]... --files0-from=F\n\
111 "),
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);
130     }
131   exit (status);
132 }
133
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)
143 {
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)];
147
148   if (print_lines)
149     {
150       printf (format_int, number_width, umaxtostr (lines, buf));
151       format_int = format_sp_int;
152     }
153   if (print_words)
154     {
155       printf (format_int, number_width, umaxtostr (words, buf));
156       format_int = format_sp_int;
157     }
158   if (print_chars)
159     {
160       printf (format_int, number_width, umaxtostr (chars, buf));
161       format_int = format_sp_int;
162     }
163   if (print_bytes)
164     {
165       printf (format_int, number_width, umaxtostr (bytes, buf));
166       format_int = format_sp_int;
167     }
168   if (print_linelength)
169     {
170       printf (format_int, number_width, umaxtostr (linelength, buf));
171     }
172   if (file)
173     printf (" %s", file);
174   putchar ('\n');
175 }
176
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)
182 {
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");
189
190   lines = words = chars = bytes = linelength = 0;
191
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)
196     {
197       count_bytes = print_bytes;
198       count_chars = print_chars;
199     }
200   else
201 #endif
202     {
203       count_bytes = print_bytes | print_chars;
204       count_chars = false;
205     }
206   count_complicated = print_words | print_linelength;
207
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.  */
217
218   if (count_bytes & !count_chars & !print_lines & !count_complicated)
219     {
220       off_t current_pos, end_pos;
221
222       if (0 < fstatus->failed)
223         fstatus->failed = fstat (fd, &fstatus->st);
224
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)
228         {
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;
232         }
233       else
234         {
235           while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
236             {
237               if (bytes_read == SAFE_READ_ERROR)
238                 {
239                   error (0, errno, "%s", file);
240                   ok = false;
241                   break;
242                 }
243               bytes += bytes_read;
244             }
245         }
246     }
247   else if (!count_chars & !count_complicated)
248     {
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)
252         {
253           char *p = buf;
254
255           if (bytes_read == SAFE_READ_ERROR)
256             {
257               error (0, errno, "%s", file);
258               ok = false;
259               break;
260             }
261
262           while ((p = memchr (p, '\n', (buf + bytes_read) - p)))
263             {
264               ++p;
265               ++lines;
266             }
267           bytes += bytes_read;
268         }
269     }
270 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
271 # define SUPPORT_OLD_MBRTOWC 1
272   else if (MB_CUR_MAX > 1)
273     {
274       bool in_word = false;
275       uintmax_t linepos = 0;
276       mbstate_t state;
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
291
292       memset (&state, 0, sizeof (mbstate_t));
293       while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
294         {
295           const char *p;
296 # if SUPPORT_OLD_MBRTOWC
297           mbstate_t backup_state;
298 # endif
299           if (bytes_read == SAFE_READ_ERROR)
300             {
301               error (0, errno, "%s", file);
302               ok = false;
303               break;
304             }
305
306           bytes += bytes_read;
307           p = buf;
308           bytes_read += prev;
309           do
310             {
311               wchar_t wide_char;
312               size_t n;
313
314 # if SUPPORT_OLD_MBRTOWC
315               backup_state = state;
316 # endif
317               n = mbrtowc (&wide_char, p, bytes_read, &state);
318               if (n == (size_t) -2)
319                 {
320 # if SUPPORT_OLD_MBRTOWC
321                   state = backup_state;
322 # endif
323                   break;
324                 }
325               if (n == (size_t) -1)
326                 {
327                   /* Signal repeated errors only once per line.  */
328                   if (!(lines + 1 == last_error_line
329                         && errno == last_error_errno))
330                     {
331                       char line_number_buf[INT_BUFSIZE_BOUND (uintmax_t)];
332                       last_error_line = lines + 1;
333                       last_error_errno = errno;
334                       error (0, errno, "%s:%s", file,
335                              umaxtostr (last_error_line, line_number_buf));
336                       ok = false;
337                     }
338                   p++;
339                   bytes_read--;
340                 }
341               else
342                 {
343                   if (n == 0)
344                     {
345                       wide_char = 0;
346                       n = 1;
347                     }
348                   p += n;
349                   bytes_read -= n;
350                   chars++;
351                   switch (wide_char)
352                     {
353                     case '\n':
354                       lines++;
355                       /* Fall through. */
356                     case '\r':
357                     case '\f':
358                       if (linepos > linelength)
359                         linelength = linepos;
360                       linepos = 0;
361                       goto mb_word_separator;
362                     case '\t':
363                       linepos += 8 - (linepos % 8);
364                       goto mb_word_separator;
365                     case ' ':
366                       linepos++;
367                       /* Fall through. */
368                     case '\v':
369                     mb_word_separator:
370                       words += in_word;
371                       in_word = false;
372                       break;
373                     default:
374                       if (iswprint (wide_char))
375                         {
376                           int width = wcwidth (wide_char);
377                           if (width > 0)
378                             linepos += width;
379                           if (iswspace (wide_char))
380                             goto mb_word_separator;
381                           in_word = true;
382                         }
383                       break;
384                     }
385                 }
386             }
387           while (bytes_read > 0);
388
389 # if SUPPORT_OLD_MBRTOWC
390           if (bytes_read > 0)
391             {
392               if (bytes_read == BUFFER_SIZE)
393                 {
394                   /* Encountered a very long redundant shift sequence.  */
395                   p++;
396                   bytes_read--;
397                 }
398               memmove (buf, p, bytes_read);
399             }
400           prev = bytes_read;
401 # endif
402         }
403       if (linepos > linelength)
404         linelength = linepos;
405       words += in_word;
406     }
407 #endif
408   else
409     {
410       bool in_word = false;
411       uintmax_t linepos = 0;
412
413       while ((bytes_read = safe_read (fd, buf, BUFFER_SIZE)) > 0)
414         {
415           const char *p = buf;
416           if (bytes_read == SAFE_READ_ERROR)
417             {
418               error (0, errno, "%s", file);
419               ok = false;
420               break;
421             }
422
423           bytes += bytes_read;
424           do
425             {
426               switch (*p++)
427                 {
428                 case '\n':
429                   lines++;
430                   /* Fall through. */
431                 case '\r':
432                 case '\f':
433                   if (linepos > linelength)
434                     linelength = linepos;
435                   linepos = 0;
436                   goto word_separator;
437                 case '\t':
438                   linepos += 8 - (linepos % 8);
439                   goto word_separator;
440                 case ' ':
441                   linepos++;
442                   /* Fall through. */
443                 case '\v':
444                 word_separator:
445                   words += in_word;
446                   in_word = false;
447                   break;
448                 default:
449                   if (isprint (to_uchar (p[-1])))
450                     {
451                       linepos++;
452                       if (isspace (to_uchar (p[-1])))
453                         goto word_separator;
454                       in_word = true;
455                     }
456                   break;
457                 }
458             }
459           while (--bytes_read);
460         }
461       if (linepos > linelength)
462         linelength = linepos;
463       words += in_word;
464     }
465
466   if (count_chars < print_chars)
467     chars = bytes;
468
469   write_counts (lines, words, chars, bytes, linelength, file_x);
470   total_lines += lines;
471   total_words += words;
472   total_chars += chars;
473   total_bytes += bytes;
474   if (linelength > max_line_length)
475     max_line_length = linelength;
476
477   return ok;
478 }
479
480 static bool
481 wc_file (char const *file, struct fstatus *fstatus)
482 {
483   if (! file || STREQ (file, "-"))
484     {
485       have_read_stdin = true;
486       if (O_BINARY && ! isatty (STDIN_FILENO))
487         freopen (NULL, "rb", stdin);
488       return wc (STDIN_FILENO, file, fstatus);
489     }
490   else
491     {
492       int fd = open (file, O_RDONLY | O_BINARY);
493       if (fd == -1)
494         {
495           error (0, errno, "%s", file);
496           return false;
497         }
498       else
499         {
500           bool ok = wc (fd, file, fstatus);
501           if (close (fd) != 0)
502             {
503               error (0, errno, "%s", file);
504               return false;
505             }
506           return ok;
507         }
508     }
509 }
510
511 /* Return the file status for the NFILES files addressed by FILE.
512    Optimize the case where only one number is printed, for just one
513    file; in that case we can use a print width of 1, so we don't need
514    to stat the file.  */
515
516 static struct fstatus *
517 get_input_fstatus (int nfiles, char * const *file)
518 {
519   struct fstatus *fstatus = xnmalloc (nfiles, sizeof *fstatus);
520
521   if (nfiles == 1
522       && ((print_lines + print_words + print_chars
523            + print_bytes + print_linelength)
524           == 1))
525     fstatus[0].failed = 1;
526   else
527     {
528       int i;
529
530       for (i = 0; i < nfiles; i++)
531         fstatus[i].failed = (! file[i] || STREQ (file[i], "-")
532                              ? fstat (STDIN_FILENO, &fstatus[i].st)
533                              : stat (file[i], &fstatus[i].st));
534     }
535
536   return fstatus;
537 }
538
539 /* Return a print width suitable for the NFILES files whose status is
540    recorded in FSTATUS.  Optimize the same special case that
541    get_input_fstatus optimizes.  */
542
543 static int
544 compute_number_width (int nfiles, struct fstatus const *fstatus)
545 {
546   int width = 1;
547
548   if (0 < nfiles && fstatus[0].failed <= 0)
549     {
550       int minimum_width = 1;
551       uintmax_t regular_total = 0;
552       int i;
553
554       for (i = 0; i < nfiles; i++)
555         if (! fstatus[i].failed)
556           {
557             if (S_ISREG (fstatus[i].st.st_mode))
558               regular_total += fstatus[i].st.st_size;
559             else
560               minimum_width = 7;
561           }
562
563       for (; 10 <= regular_total; regular_total /= 10)
564         width++;
565       if (width < minimum_width)
566         width = minimum_width;
567     }
568
569   return width;
570 }
571
572
573 int
574 main (int argc, char **argv)
575 {
576   int i;
577   bool ok;
578   int optc;
579   int nfiles;
580   char **files;
581   char *files_from = NULL;
582   struct fstatus *fstatus;
583   struct Tokens tok;
584
585   initialize_main (&argc, &argv);
586   program_name = argv[0];
587   setlocale (LC_ALL, "");
588   bindtextdomain (PACKAGE, LOCALEDIR);
589   textdomain (PACKAGE);
590
591   atexit (close_stdout);
592
593   print_lines = print_words = print_chars = print_bytes = false;
594   print_linelength = false;
595   total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
596
597   while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
598     switch (optc)
599       {
600       case 'c':
601         print_bytes = true;
602         break;
603
604       case 'm':
605         print_chars = true;
606         break;
607
608       case 'l':
609         print_lines = true;
610         break;
611
612       case 'w':
613         print_words = true;
614         break;
615
616       case 'L':
617         print_linelength = true;
618         break;
619
620       case FILES0_FROM_OPTION:
621         files_from = optarg;
622         break;
623
624       case_GETOPT_HELP_CHAR;
625
626       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
627
628       default:
629         usage (EXIT_FAILURE);
630       }
631
632   if (! (print_lines | print_words | print_chars | print_bytes
633          | print_linelength))
634     print_lines = print_words = print_bytes = true;
635
636   if (files_from)
637     {
638       FILE *stream;
639
640       /* When using --files0-from=F, you may not specify any files
641          on the command-line.  */
642       if (optind < argc)
643         {
644           error (0, 0, _("extra operand %s"), quote (argv[optind]));
645           fprintf (stderr, "%s\n",
646                    _("File operands cannot be combined with --files0-from."));
647           usage (EXIT_FAILURE);
648         }
649
650       if (STREQ (files_from, "-"))
651         stream = stdin;
652       else
653         {
654           stream = fopen (files_from, "r");
655           if (stream == NULL)
656             error (EXIT_FAILURE, errno, _("cannot open %s for reading"),
657                    quote (files_from));
658         }
659
660       readtokens0_init (&tok);
661
662       if (! readtokens0 (stream, &tok) || fclose (stream) != 0)
663         error (EXIT_FAILURE, 0, _("cannot read file names from %s"),
664                quote (files_from));
665
666       files = tok.tok;
667       nfiles = tok.n_tok;
668     }
669   else
670     {
671       static char *stdin_only[2];
672       files = (optind < argc ? argv + optind : stdin_only);
673       nfiles = (optind < argc ? argc - optind : 1);
674       stdin_only[0] = NULL;
675     }
676
677   fstatus = get_input_fstatus (nfiles, files);
678   number_width = compute_number_width (nfiles, fstatus);
679
680   ok = true;
681   for (i = 0; i < nfiles; i++)
682     {
683       if (files_from && STREQ (files_from, "-") && STREQ (files[i], "-"))
684         {
685           ok = false;
686           error (0, 0,
687                  _("when reading file names from stdin, "
688                    "no file name of %s allowed"),
689                  quote ("-"));
690           continue;
691         }
692       ok &= wc_file (files[i], &fstatus[i]);
693     }
694
695   if (1 < nfiles)
696     write_counts (total_lines, total_words, total_chars, total_bytes,
697                   max_line_length, _("total"));
698
699   free (fstatus);
700
701   if (have_read_stdin && close (STDIN_FILENO) != 0)
702     error (EXIT_FAILURE, errno, "-");
703
704   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
705 }