home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / a / txtutils / textutil.9 / textutil / textutils-1.9 / src / wc.c < prev   
Encoding:
C/C++ Source or Header  |  1993-10-23  |  5.9 KB  |  291 lines

  1. /* wc - print the number of bytes, words, and lines in files
  2.    Copyright (C) 1985, 1991 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
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Written by Paul Rubin, phr@ocf.berkeley.edu
  19.    and David MacKenzie, djm@gnu.ai.mit.edu. */
  20.  
  21. #ifdef HAVE_CONFIG_H
  22. #if defined (CONFIG_BROKETS)
  23. /* We use <config.h> instead of "config.h" so that a compilation
  24.    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
  25.    (which it would do because it found this file in $srcdir).  */
  26. #include <config.h>
  27. #else
  28. #include "config.h"
  29. #endif
  30. #endif
  31.  
  32. #include <stdio.h>
  33. #include <getopt.h>
  34. #include <sys/types.h>
  35. #include "system.h"
  36. #include "version.h"
  37.  
  38. /* Size of atomic reads. */
  39. #define BUFFER_SIZE (16 * 1024)
  40.  
  41. void error ();
  42.  
  43. static void wc ();
  44. static void wc_file ();
  45. static void write_counts ();
  46.  
  47. /* The name this program was run with. */
  48. char *program_name;
  49.  
  50. /* Cumulative number of lines, words, and chars in all files so far. */
  51. static unsigned long total_lines, total_words, total_chars;
  52.  
  53. /* Which counts to print. */
  54. static int print_lines, print_words, print_chars;
  55.  
  56. /* Nonzero if we have ever read the standard input. */
  57. static int have_read_stdin;
  58.  
  59. /* The error code to return to the system. */
  60. static int exit_status;
  61.  
  62. /* If non-zero, display usage information and exit.  */
  63. static int show_help;
  64.  
  65. /* If non-zero, print the version on standard output then exits.  */
  66. static int show_version;
  67.  
  68. static struct option const longopts[] =
  69. {
  70.   {"bytes", no_argument, NULL, 'c'},
  71.   {"chars", no_argument, NULL, 'c'},
  72.   {"lines", no_argument, NULL, 'l'},
  73.   {"words", no_argument, NULL, 'w'},
  74.   {"help", no_argument, &show_help, 1},
  75.   {"version", no_argument, &show_version, 1},
  76.   {NULL, 0, NULL, 0}
  77. };
  78.  
  79. static void
  80. usage (status)
  81.      int status;
  82. {
  83.   if (status != 0)
  84.     fprintf (stderr, "Try `%s --help' for more information.\n",
  85.          program_name);
  86.   else
  87.     {
  88.       printf ("\
  89. Usage: %s [OPTION]... [FILE]...\n\
  90. ",
  91.           program_name);
  92.       printf ("\
  93. \n\
  94.   -c, --bytes, --chars   print the byte counts\n\
  95.   -l, --lines            print the newline counts\n\
  96.   -w, --words            print the word counts\n\
  97.       --help             display this help and exit\n\
  98.       --version          output version information and exit\n\
  99. \n\
  100. Print lines, words and bytes in that order.  If none of -clw, select\n\
  101. them all.  With no FILE, or when FILE is -, read standard input.\n\
  102. ");
  103.     }
  104.   exit (status);
  105. }
  106.  
  107. void
  108. main (argc, argv)
  109.      int argc;
  110.      char **argv;
  111. {
  112.   int optc;
  113.   int nfiles;
  114.  
  115.   program_name = argv[0];
  116.   exit_status = 0;
  117.   print_lines = print_words = print_chars = 0;
  118.   total_lines = total_words = total_chars = 0;
  119.  
  120.   while ((optc = getopt_long (argc, argv, "clw", longopts, (int *) 0)) != EOF)
  121.     switch (optc)
  122.       {
  123.       case 0:
  124.     break;
  125.  
  126.       case 'c':
  127.     print_chars = 1;
  128.     break;
  129.  
  130.       case 'l':
  131.     print_lines = 1;
  132.     break;
  133.  
  134.       case 'w':
  135.     print_words = 1;
  136.     break;
  137.  
  138.       default:
  139.     usage (1);
  140.       }
  141.  
  142.   if (show_version)
  143.     {
  144.       printf ("%s\n", version_string);
  145.       exit (0);
  146.     }
  147.  
  148.   if (show_help)
  149.     usage (0);
  150.  
  151.   if (print_lines + print_words + print_chars == 0)
  152.     print_lines = print_words = print_chars = 1;
  153.  
  154.   nfiles = argc - optind;
  155.  
  156.   if (nfiles == 0)
  157.     {
  158.       have_read_stdin = 1;
  159.       wc (0, "");
  160.     }
  161.   else
  162.     {
  163.       for (; optind < argc; ++optind)
  164.     wc_file (argv[optind]);
  165.  
  166.       if (nfiles > 1)
  167.     write_counts (total_lines, total_words, total_chars, "total");
  168.     }
  169.  
  170.   if (have_read_stdin && close (0))
  171.     error (1, errno, "-");
  172.  
  173.   exit (exit_status);
  174. }
  175.  
  176. static void
  177. wc_file (file)
  178.      char *file;
  179. {
  180.   if (!strcmp (file, "-"))
  181.     {
  182.       have_read_stdin = 1;
  183.       wc (0, file);
  184.     }
  185.   else
  186.     {
  187.       int fd = open (file, O_RDONLY);
  188.       if (fd == -1)
  189.     {
  190.       error (0, errno, "%s", file);
  191.       exit_status = 1;
  192.       return;
  193.     }
  194.       wc (fd, file);
  195.       if (close (fd))
  196.     {
  197.       error (0, errno, "%s", file);
  198.       exit_status = 1;
  199.     }
  200.     }
  201. }
  202.  
  203. static void
  204. wc (fd, file)
  205.      int fd;
  206.      char *file;
  207. {
  208.   char buf[BUFFER_SIZE];
  209.   register int bytes_read;
  210.   register int in_word = 0;
  211.   register unsigned long lines, words, chars;
  212.   struct stat stats;
  213.  
  214.   lines = words = chars = 0;
  215.  
  216.   if (print_chars && !print_words && !print_lines
  217.       && fstat (fd, &stats) == 0 && S_ISREG (stats.st_mode))
  218.     {
  219.       chars = stats.st_size;
  220.     }
  221.   else
  222.     {
  223.       while ((bytes_read = read (fd, buf, BUFFER_SIZE)) > 0)
  224.     {
  225.       register char *p = buf;
  226.  
  227.       chars += bytes_read;
  228.       do
  229.         {
  230.           switch (*p++)
  231.         {
  232.         case '\n':
  233.           lines++;
  234.           /* Fall through. */
  235.         case '\r':
  236.         case '\f':
  237.         case '\t':
  238.         case '\v':
  239.         case ' ':
  240.           if (in_word)
  241.             {
  242.               in_word = 0;
  243.               words++;
  244.             }
  245.           break;
  246.         default:
  247.           in_word = 1;
  248.           break;
  249.         }
  250.         }
  251.       while (--bytes_read);
  252.     }
  253.       if (bytes_read < 0)
  254.     {
  255.       error (0, errno, "%s", file);
  256.       exit_status = 1;
  257.     }
  258.       if (in_word)
  259.     words++;
  260.     }
  261.  
  262.   write_counts (lines, words, chars, file);
  263.   total_lines += lines;
  264.   total_words += words;
  265.   total_chars += chars;
  266. }
  267.  
  268. static void
  269. write_counts (lines, words, chars, file)
  270.      unsigned long lines, words, chars;
  271.      char *file;
  272. {
  273.   if (print_lines)
  274.     printf ("%7lu", lines);
  275.   if (print_words)
  276.     {
  277.       if (print_lines)
  278.     putchar (' ');
  279.       printf ("%7lu", words);
  280.     }
  281.   if (print_chars)
  282.     {
  283.       if (print_lines || print_words)
  284.     putchar (' ');
  285.       printf ("%7lu", chars);
  286.     }
  287.   if (*file)
  288.     printf (" %s", file);
  289.   putchar ('\n');
  290. }
  291.