diff options
Diffstat (limited to 'src/wc.c')
-rw-r--r-- | src/wc.c | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/wc.c b/src/wc.c new file mode 100644 index 000000000..72d6ea665 --- /dev/null +++ b/src/wc.c @@ -0,0 +1,231 @@ +/* wc - print the number of bytes, words, and lines in files + Copyright (C) 1985, 1991 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Written by Paul Rubin, phr@ocf.berkeley.edu + and David MacKenzie, djm@gnu.ai.mit.edu. */ + +#include <stdio.h> +#include <getopt.h> +#include <sys/types.h> +#include "system.h" + +/* Size of atomic reads. */ +#define BUFFER_SIZE (16 * 1024) + +void error (); +void wc (); +void wc_file (); +void write_counts (); + +/* Cumulative number of lines, words, and chars in all files so far. */ +unsigned long total_lines, total_words, total_chars; + +/* Which counts to print. */ +int print_lines, print_words, print_chars; + +/* Nonzero if we have ever read the standard input. */ +int have_read_stdin; + +/* The name this program was run with. */ +char *program_name; + +/* The error code to return to the system. */ +int exit_status; + +struct option longopts[] = +{ + {"bytes", 0, NULL, 'c'}, + {"chars", 0, NULL, 'c'}, + {"lines", 0, NULL, 'l'}, + {"words", 0, NULL, 'w'}, + {NULL, 0, NULL, 0} +}; + +void +main (argc, argv) + int argc; + char **argv; +{ + int optc; + int nfiles; + + program_name = argv[0]; + exit_status = 0; + print_lines = print_words = print_chars = 0; + total_lines = total_words = total_chars = 0; + + while ((optc = getopt_long (argc, argv, "clw", longopts, (int *) 0)) != EOF) + switch (optc) + { + case 'c': + print_chars = 1; + break; + + case 'l': + print_lines = 1; + break; + + case 'w': + print_words = 1; + break; + + default: + fprintf (stderr, "\ +Usage: %s [-clw] [--bytes] [--chars] [--lines] [--words] [file...]\n", argv[0]); + exit (1); + } + + if (print_lines + print_words + print_chars == 0) + print_lines = print_words = print_chars = 1; + + nfiles = argc - optind; + + if (nfiles == 0) + { + have_read_stdin = 1; + wc (0, ""); + } + else + { + for (; optind < argc; ++optind) + wc_file (argv[optind]); + + if (nfiles > 1) + write_counts (total_lines, total_words, total_chars, "total"); + } + + if (have_read_stdin && close (0)) + error (1, errno, "-"); + + exit (exit_status); +} + +void +wc_file (file) + char *file; +{ + if (!strcmp (file, "-")) + { + have_read_stdin = 1; + wc (0, file); + } + else + { + int fd = open (file, O_RDONLY); + if (fd == -1) + { + error (0, errno, "%s", file); + exit_status = 1; + return; + } + wc (fd, file); + if (close (fd)) + { + error (0, errno, "%s", file); + exit_status = 1; + } + } +} + +void +wc (fd, file) + int fd; + char *file; +{ + char buf[BUFFER_SIZE]; + register int bytes_read; + register int in_word = 0; + register unsigned long lines, words, chars; + struct stat stats; + + lines = words = chars = 0; + + if (print_chars && !print_words && !print_lines + && fstat (fd, &stats) == 0 && S_ISREG (stats.st_mode)) + { + chars = stats.st_size; + } + else + { + while ((bytes_read = read (fd, buf, BUFFER_SIZE)) > 0) + { + register char *p = buf; + + chars += bytes_read; + do + { + switch (*p++) + { + case '\n': + lines++; + /* Fall through. */ + case '\r': + case '\f': + case '\t': + case '\v': + case ' ': + if (in_word) + { + in_word = 0; + words++; + } + break; + default: + in_word = 1; + break; + } + } + while (--bytes_read); + } + if (bytes_read < 0) + { + error (0, errno, "%s", file); + exit_status = 1; + } + if (in_word) + words++; + } + + write_counts (lines, words, chars, file); + total_lines += lines; + total_words += words; + total_chars += chars; +} + +void +write_counts (lc, wc, cc, file) + unsigned long lc, wc, cc; + char *file; +{ + if (print_lines) + printf ("%7lu", lc); + if (print_words) + { + if (print_lines) + putchar (' '); + printf ("%7lu", wc); + } + if (print_chars) + { + if (print_lines || print_words) + putchar (' '); + printf ("%7lu", cc); + } + if (*file) + printf (" %s", file); + putchar ('\n'); +} |