From 70aaff4872a488819196879dc493442351c6accf Mon Sep 17 00:00:00 2001 From: Alastair Stuart Date: Mon, 3 Jun 2013 11:13:34 -0500 Subject: [PATCH] wc: Added wc --- wc.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 wc.c diff --git a/wc.c b/wc.c new file mode 100644 index 0000000..084efda --- /dev/null +++ b/wc.c @@ -0,0 +1,205 @@ +/* + Copyright © 2013 Alastair Stuart + + This program is open source 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 3 of the License, 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. +*/ + +#include +#include +#include +#include +#include + +#include +#include + +#define VERSION "0.01" + +struct { + bool lines; + bool words; + bool chars; + bool bytes; +} flags; + +size_t total_lines = 0; +size_t total_words = 0; +size_t total_chars = 0; + +void usage(char* program) +{ + printf("Usage: %s [options] [file ...]\n", program); + printf("Counts words, lines, and characters.\n" + "\n" + " -c, --bytes Print the number of bytes.\n" + " -m, --chars Print the number of characters.\n" + " -l, --lines Print the number of lines.\n" + " -w, --words Print the number of words.\n" + "\n" + " --help Print this message.\n" + " --version Show version info.\n" + "\n" + "If no file is given or file is '-', standard input is read.\n"); +} + +void word_count(FILE* file) +{ + size_t lines = 0; + size_t words = 0; + size_t chars = 0; + + int c = !EOF; + int c2 = fgetc(file); + while (c != EOF || c2 != EOF) + { + chars++; + if (c == '\n') { + lines++; + } + + if ((isprint(c) && !isblank(c) && c != '\n') && + (isblank(c2) || c2 == EOF || c2 == '\n')) { + words++; + } + + c = c2; + c2 = fgetc(file); + } + chars--; // reading 2 characters at once + // causes chars to miscount + + total_lines += lines; + total_words += words; + total_chars += chars; + + if (flags.lines) { + printf("%zu\t", lines); + } + if (flags.words) { + printf("%zu\t", words); + } + if (flags.chars) { + printf("%zu\t", chars); + } + if (flags.bytes) { + printf("%zu\t", chars); + } +} + +int main(int argc, char* argv[]) +{ + bool errors = false; + + static struct option long_options[] = { + {"bytes", no_argument, NULL, 'c'}, + {"chars", no_argument, NULL, 'm'}, + {"lines", no_argument, NULL, 'l'}, + {"words", no_argument, NULL, 'w'}, + {"help", no_argument, NULL, 1}, + {"version", no_argument, NULL, 2}, + {NULL, 0, NULL, 0} + }; + + int c = 0; + while ((c = getopt_long(argc, argv, "cmlw", + long_options, NULL)) != -1) + { + switch (c) + { + case 'c': + flags.bytes = true; + break; + case 'm': + flags.chars = true; + break; + case 'l': + flags.lines = true; + break; + case 'w': + flags.words = true; + break; + case 1: + usage(argv[0]); + return 0; + case 2: + printf("wc (mutos) v"VERSION"\n"); + return 0; + default: + fprintf(stderr, "Run '%s --help' for usage.\n", + argv[0]); + return 1; + } + } + + // default columns + if (!flags.bytes && !flags.chars && !flags.lines && !flags.words) { + flags.lines = true; + flags.words = true; + flags.chars = true; + } + + if ((argc - optind) == 0) { + word_count(stdin); + printf("\n"); + } + + FILE* file_array[argc - optind]; + memset(file_array, 0, sizeof(FILE*) * (argc - optind)); + + for (int i = optind, j = 0; i < argc; i++, j++) + { + struct stat s; + stat(argv[i], &s); + + if (strcmp(argv[i], "-") == 0) { + file_array[j] = stdin; + } else if (s.st_mode & S_IFDIR) { // we can't word count a directory + file_array[j] = NULL; + fprintf(stderr, "%s: %s: %s\n", + argv[0], "Is a directory", argv[i]); + errors = true; + } else { + file_array[j] = fopen(argv[i], "r"); + } + } + + size_t num_files = 0; + for (int i = 0; i < (argc - optind); i++) + { + if (file_array[i]) { + word_count(file_array[i]); + printf("%s\n", argv[optind + i]); + num_files++; + } + } + + if (num_files > 1) { + if (flags.lines) { + printf("%zu\t", total_lines); + } + if (flags.words) { + printf("%zu\t", total_words); + } + if (flags.chars) { + printf("%zu\t", total_chars); + } + if (flags.bytes) { + printf("%zu\t", total_chars); + } + printf("total\n"); + } + + if (errors) { + return 1; + } else { + return 0; + } +} -- 2.11.4.GIT