From d93e07620b6b09ea341031fe3a1aae0d2d97714e Mon Sep 17 00:00:00 2001 From: Lieuwe Rooijakkers Date: Mon, 19 Aug 2024 01:50:35 +0200 Subject: Revert "toilet: fix segfault in word count" This reverts back to commit 7298453390da42d4fcd21d2911e2d14b2187ceff. --- src/toilet.c | 105 +++++++++++++++++++++-------------------------------------- 1 file changed, 38 insertions(+), 67 deletions(-) diff --git a/src/toilet.c b/src/toilet.c index ff51ba8..de32003 100644 --- a/src/toilet.c +++ b/src/toilet.c @@ -1,11 +1,9 @@ #include #include -#include #include #include #include #include -#include #include #include #include @@ -13,7 +11,7 @@ #include "util/debug.h" #include "util/error.h" -#include "util/loop_args.h" +#include "util/loop_files.h" #include "util/map.h" #include "util/versie.h" @@ -21,8 +19,6 @@ static int modeMap; -#define BUF_SIZE 4096 - static void usage(FILE *f) { fprintf(f, "Gebruik: toilet [-nchV] [BESTAND]...\n" @@ -77,91 +73,66 @@ static char** parse_options(int argc, char **argv, int *modeMap) { return argv + optind; } -static size_t count_lines(char *fname, FILE *f) { - size_t nlines = 0; - bool last_was_nl = false; - - while (!feof(f)) { - static char buf[BUF_SIZE]; - const size_t n = fread(buf, 1, BUF_SIZE, f); - - for (size_t i = 0; i < n; i++) { - last_was_nl = false; - if (buf[i] == '\n') { - nlines++; - last_was_nl = true; - } - } - } +static size_t get_count(enum MODE mode, struct filebuf *fb) { + switch (mode) { + case M_BYTES: + return fb->sz; - if (!last_was_nl) nlines++; + case M_WORDS: { +#define IN(i) (i < fb->sz) - if (errno != 0) { - printf("toilet: fout bij lezen uit bestand '%s'\n", fname); - exit(1); - } + size_t words = 0; - rewind(f); - return nlines; -} - -static size_t count_words(FILE *f) { - size_t nwords = 0; + // (c) Tom Forging + for (size_t i = 0; IN(i);) { + size_t previ = i; + while (IN(i) && !isspace(fb->buf[i])) i++; + words += i != previ; + while (IN(i) && isspace(fb->buf[i])) i++; + } - while (!feof(f)) { - static char buf[BUF_SIZE]; - const size_t n = fread(buf, 1, BUF_SIZE, f); + return words; - // (c) Tom Forging - for (size_t i = 0; isz) { + if (fb->buf[i] == '\n') lines++; + i++; + } - case M_WORDS: - return count_words(f); + // handle case if file does not have trailing newline + if (fb->buf[i - 1] != '\n') { + lines++; + } - case M_LINES: - return count_lines(fname, f); + return lines; + } default: assert(false); } } -static int process(char *fname, bool isstdin) { - FILE *f = isstdin ? stdin : fopen(fname, "rb"); - +static int process(struct filebuf *fb, char *fname, bool) { for (enum MODE mode = 1; mode <= M_BYTES; mode <<= 1) { if (mode & modeMap) { - const size_t count = get_count(mode, fname, f); + const size_t count = get_count(mode, fb); printf("%li ", count); } } - - if (fname != NULL) printf("%s", fname); - putchar('\n'); - - if (!isstdin) fclose(f); + printf("%s\n", fname); + free_filebuf(fb); return 0; } +// TODO: be smarter, toilet doesn't have to read the whole file in memory (for +// unmappable files) + int entry_toilet(int argc, char **argv) { modeMap = 0; char **args = parse_options(argc, argv, &modeMap); @@ -169,5 +140,5 @@ int entry_toilet(int argc, char **argv) { modeMap = INT_MAX; } - return loop_args(args, process); + return loop_files(args, process); } -- cgit v1.2.3-70-g09d2