home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / useful / dist / gnu / textutils / textutils-1.6-amiga / src / wc.c < prev   
Encoding:
C/C++ Source or Header  |  1993-10-04  |  5.1 KB  |  263 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. #include <stdio.h>
  22. #include <getopt.h>
  23. #include <sys/types.h>
  24. #include "system.h"
  25. #include "version.h"
  26.  
  27. /* Size of atomic reads. */
  28. #define BUFFER_SIZE (16 * 1024)
  29.  
  30. void error ();
  31.  
  32. static void wc ();
  33. static void wc_file ();
  34. static void write_counts ();
  35.  
  36. /* The name this program was run with. */
  37. char *program_name;
  38.  
  39. /* Cumulative number of lines, words, and chars in all files so far. */
  40. static unsigned long total_lines, total_words, total_chars;
  41.  
  42. /* Which counts to print. */
  43. static int print_lines, print_words, print_chars;
  44.  
  45. /* Nonzero if we have ever read the standard input. */
  46. static int have_read_stdin;
  47.  
  48. /* The error code to return to the system. */
  49. static int exit_status;
  50.  
  51. /* If non-zero, display usage information and exit.  */
  52. static int flag_help;
  53.  
  54. /* If non-zero, print the version on standard error.  */
  55. static int flag_version;
  56.  
  57. static struct option const longopts[] =
  58. {
  59.   {"bytes", no_argument, NULL, 'c'},
  60.   {"chars", no_argument, NULL, 'c'},
  61.   {"lines", no_argument, NULL, 'l'},
  62.   {"words", no_argument, NULL, 'w'},
  63.   {"help", no_argument, &flag_help, 1},
  64.   {"version", no_argument, &flag_version, 1},
  65.   {NULL, 0, NULL, 0}
  66. };
  67.  
  68. static void
  69. usage ()
  70. {
  71.   fprintf (stderr, "\
  72. Usage: %s [-clw] [--bytes] [--chars] [--lines] [--words]\n\
  73.        [--help] [--version] [file...]\n",
  74.        program_name);
  75.   exit (1);
  76. }
  77.  
  78. void
  79. main (argc, argv)
  80.      int argc;
  81.      char **argv;
  82. {
  83.   int optc;
  84.   int nfiles;
  85.  
  86.   program_name = argv[0];
  87.   exit_status = 0;
  88.   print_lines = print_words = print_chars = 0;
  89.   total_lines = total_words = total_chars = 0;
  90.  
  91.   while ((optc = getopt_long (argc, argv, "clw", longopts, (int *) 0)) != EOF)
  92.     switch (optc)
  93.       {
  94.       case 0:
  95.     break;
  96.  
  97.       case 'c':
  98.     print_chars = 1;
  99.     break;
  100.  
  101.       case 'l':
  102.     print_lines = 1;
  103.     break;
  104.  
  105.       case 'w':
  106.     print_words = 1;
  107.     break;
  108.  
  109.       default:
  110.     usage ();
  111.       }
  112.  
  113.   if (flag_version)
  114.     {
  115.       fprintf (stderr, "%s\n", version_string);
  116.       exit (0);
  117.     }
  118.  
  119.   if (flag_help)
  120.     usage ();
  121.  
  122.   if (print_lines + print_words + print_chars == 0)
  123.     print_lines = print_words = print_chars = 1;
  124.  
  125.   nfiles = argc - optind;
  126.  
  127.   if (nfiles == 0)
  128.     {
  129.       have_read_stdin = 1;
  130.       wc (0, "");
  131.     }
  132.   else
  133.     {
  134.       for (; optind < argc; ++optind)
  135.     wc_file (argv[optind]);
  136.  
  137.       if (nfiles > 1)
  138.     write_counts (total_lines, total_words, total_chars, "total");
  139.     }
  140.  
  141.   if (have_read_stdin && close (0))
  142.     error (1, errno, "-");
  143.  
  144.   exit (exit_status);
  145. }
  146.  
  147. static void
  148. wc_file (file)
  149.      char *file;
  150. {
  151.   if (!strcmp (file, "-"))
  152.     {
  153.       have_read_stdin = 1;
  154.       wc (0, file);
  155.     }
  156.   else
  157.     {
  158.       int fd = open (file, O_RDONLY);
  159.       if (fd == -1)
  160.     {
  161.       error (0, errno, "%s", file);
  162.       exit_status = 1;
  163.       return;
  164.     }
  165.       wc (fd, file);
  166.       if (close (fd))
  167.     {
  168.       error (0, errno, "%s", file);
  169.       exit_status = 1;
  170.     }
  171.     }
  172. }
  173.  
  174. char buf[BUFFER_SIZE];        /* Move buffer off stack; David Gay */
  175.  
  176. static void
  177. wc (fd, file)
  178.      int fd;
  179.      char *file;
  180. {
  181.   register int bytes_read;
  182.   register int in_word = 0;
  183.   register unsigned long lines, words, chars;
  184.   struct stat stats;
  185.  
  186.   lines = words = chars = 0;
  187.  
  188.   if (print_chars && !print_words && !print_lines
  189.       && fstat (fd, &stats) == 0 && S_ISREG (stats.st_mode))
  190.     {
  191.       chars = stats.st_size;
  192.     }
  193.   else
  194.     {
  195.       while ((bytes_read = read (fd, buf, BUFFER_SIZE)) > 0)
  196.     {
  197.       register char *p = buf;
  198.  
  199.       chars += bytes_read;
  200.       do
  201.         {
  202.           switch (*p++)
  203.         {
  204.         case '\n':
  205.           lines++;
  206.           /* Fall through. */
  207.         case '\r':
  208.         case '\f':
  209.         case '\t':
  210.         case '\v':
  211.         case ' ':
  212.           if (in_word)
  213.             {
  214.               in_word = 0;
  215.               words++;
  216.             }
  217.           break;
  218.         default:
  219.           in_word = 1;
  220.           break;
  221.         }
  222.         }
  223.       while (--bytes_read);
  224.     }
  225.       if (bytes_read < 0)
  226.     {
  227.       error (0, errno, "%s", file);
  228.       exit_status = 1;
  229.     }
  230.       if (in_word)
  231.     words++;
  232.     }
  233.  
  234.   write_counts (lines, words, chars, file);
  235.   total_lines += lines;
  236.   total_words += words;
  237.   total_chars += chars;
  238. }
  239.  
  240. static void
  241. write_counts (lines, words, chars, file)
  242.      unsigned long lines, words, chars;
  243.      char *file;
  244. {
  245.   if (print_lines)
  246.     printf ("%7lu", lines);
  247.   if (print_words)
  248.     {
  249.       if (print_lines)
  250.     putchar (' ');
  251.       printf ("%7lu", words);
  252.     }
  253.   if (print_chars)
  254.     {
  255.       if (print_lines || print_words)
  256.     putchar (' ');
  257.       printf ("%7lu", chars);
  258.     }
  259.   if (*file)
  260.     printf (" %s", file);
  261.   putchar ('\n');
  262. }
  263.