#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; }