From d8f2c10b7108fff6b7e437291093a1cadc15ab9f Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Sat, 6 May 2023 00:39:44 -0400 Subject: refactor --- command/wc.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 command/wc.c (limited to 'command/wc.c') diff --git a/command/wc.c b/command/wc.c new file mode 100644 index 0000000..3150045 --- /dev/null +++ b/command/wc.c @@ -0,0 +1,161 @@ +#include "command.h" +#include "lslib.h" + +#include +#include + +static struct { + bool newlines; + bool words; + bool characters; + bool bytes; + bool longest_line; + bool has_flags; +} flags; + +static int lines = 0; +static int words = 0; +static int chars = 0; +static int bytes = 0; +static int logst = 0; + +static void list(int l, int w, int c, int b, int lg) { + if (flags.newlines) { + printf("\t%d", l); + } + if (flags.words) { + printf("\t%d", w); + } + if (flags.characters) { + printf("\t%d", c); + } + if (flags.bytes) { + printf("\t%d", b); + } + if (flags.longest_line) { + printf("\t%d", lg); + } +} + +#define BS 1024 + +static bool is_delimiter(char c) { + return c == ' ' || c == '\t' || c == '\n'; +} + +static void run_wc(FILE* file) { + int l = 0, w = 0, c = 0, b = 0, lg = 0; + + bool in_word = false; + int current_length = 0; + + int read; + char buf[BS]; + while ((read = fread(buf, 1, 1024, file)) > 0) { + int i; + for (i = 0; i < read; i++) { + char ch = buf[i]; + b++; + if (ch == '\n') { + l++; + lg = lg > current_length ? lg : current_length; + current_length = 0; + } else { + current_length++; + } + if (isprint(ch) || is_delimiter(ch)) c++; + if (in_word && is_delimiter(ch)) { + in_word = false; + w++; + } else if (!in_word && !is_delimiter(ch) && isprint(ch)) { + in_word = true; + } + } + } + if (in_word) w++; + lg = lg > current_length ? lg : current_length; + list(l, w, c, b, lg); + lines += l; + words += w; + chars += c; + bytes += b; + logst += lg; + if (file != stdin) + fclose(file); +} + +static void help(void) { + printf("Usage: wc [-cmlwL] [FILE]...\n\n"); + printf("Count lines, words, and bytes for FILEs (or stdin)\n\n"); + printf("\t-c Count bytes\n"); + printf("\t-m Count characters\n"); + printf("\t-l Count newlines\n"); + printf("\t-w Count words\n"); + printf("\t-L Print longest line length\n"); + exit(EXIT_SUCCESS); +} + +static int short_arg(char c, char* next) { + UNUSED(next); + switch (c) { + case 'c': + flags.bytes = true; + break; + case 'm': + flags.characters = true; + break; + case 'l': + flags.newlines = true; + break; + case 'w': + flags.words = true; + break; + case 'L': + flags.longest_line = true; + break; + default: + return ARG_INVALID; + } + flags.has_flags = true; + return ARG_UNUSED; +} + +COMMAND(wc) { + + int start, i; + + flags.newlines = false; + flags.words = false; + flags.characters = false; + flags.bytes = false; + flags.longest_line = false; + flags.has_flags = false; + + + start = parse_args(argc, argv, help, short_arg, NULL); + + if (!flags.has_flags) { + flags.newlines = true; + flags.words = true; + flags.characters = true; + } + + if (argc - start < 1) { + run_wc(stdin); + printf("\n"); + return EXIT_SUCCESS; + } + + for (i = start; i < argc; i++) { + FILE* file = get_file(argv[i], "r"); + run_wc(file); + printf("\t%s\n", argv[i]); + } + + if (argc - start > 1) { + list(lines, words, chars, bytes, logst); + printf("\ttotal\n"); + } + + return EXIT_SUCCESS; +} -- cgit v1.2.3-freya