diff options
author | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2024-08-19 01:50:35 +0200 |
---|---|---|
committer | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2024-08-19 01:51:29 +0200 |
commit | d93e07620b6b09ea341031fe3a1aae0d2d97714e (patch) | |
tree | eec7db1b965073d1de87541e85180811d6a8cce7 | |
parent | de98360cbf57ae882bd926964305bbc0da6d537e (diff) |
Revert "toilet: fix segfault in word count"
This reverts back to commit 7298453390da42d4fcd21d2911e2d14b2187ceff.
-rw-r--r-- | src/toilet.c | 105 |
1 files 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 <assert.h> #include <ctype.h> -#include <errno.h> #include <getopt.h> #include <limits.h> #include <pwd.h> #include <stdbool.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -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; i<n;) { - size_t previ = i; - while (i<n && !isspace(buf[i])) i++; - nwords += i != previ; - while (i<n && isspace(buf[i])) i++; +#undef IN } - } - rewind(f); - return nwords; -} + case M_LINES: { + size_t lines = 0; + size_t i = 0; -static size_t get_count(enum MODE mode, char *fname, FILE *f) { - switch (mode) { - case M_BYTES: { - fseek(f, 0, SEEK_END); - long offset = ftell(f); - rewind(f); - return offset; - } + while (i != fb->sz) { + 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); } |