From 64ee4628e219ef3653d3555b94ba091d12e7bb39 Mon Sep 17 00:00:00 2001 From: Lieuwe Rooijakkers Date: Sun, 14 Jul 2024 16:53:22 +0200 Subject: toilet --- src/toilet.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util/map.c | 2 +- src/util/map.h | 1 + 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/toilet.c diff --git a/src/toilet.c b/src/toilet.c new file mode 100644 index 0000000..24b19a4 --- /dev/null +++ b/src/toilet.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "util/versie.h" +#include "util/error.h" +#include "util/debug.h" +#include "util/map.h" + +static void usage(FILE *f) { + fprintf(f, + "Gebruik: toilet [-nchV] [BESTAND]...\n" + "\n" + "Toon de hoevelheeid regels, woorden en beten for elk BESTAND\n" + "\n" + " -c Geef het aantal beten weer\n" + " -w Geef het aantal woorden weer\n" + " -l Geef het aantal regels weer\n" + " -h Toon deze hulptekst\n" + " -V Toon versienummer\n"); +} + +enum MODE { + M_BYTES, + M_WORDS, + M_LINES, +}; + +// Returns pointer to argument array containing the file names +static char** parse_options(int argc, char **argv, enum MODE *mode) { + int opt; + while ((opt = getopt(argc, argv, "cwlhV")) != -1) { + switch (opt) { + case 'c': + *mode = M_BYTES; + break; + + case 'w': + *mode = M_WORDS; + break; + + case 'l': + *mode = M_LINES; + break; + + case 'h': + usage(stdout); + exit(0); + + case 'V': + drukkedoos_print_versie(stdout, "toilet"); + exit(0); + + case '?': + usage(stderr); + exit(1); + } + } + + return argv + optind; +} + +size_t get_count(enum MODE mode, struct map *map) { + switch (mode) { + case M_BYTES: + return map->sb.st_size; + + case M_WORDS: { + size_t words = 0; + + assert(map->sb.st_size >= 0); + for (size_t i = 0; i < (size_t)map->sb.st_size;) { + size_t previ = i; + while (!isspace(map->addr[i])) i++; + words += i != previ; + while (isspace(map->addr[i])) i++; + } + + return words; + } + + case M_LINES: { + size_t lines = 0; + + while (map->addr != map->end) { + if (*map->addr == '\n') lines++; + map->addr++; + } + + if (*(map->addr - 1) != '\n') { + lines++; + } + + return lines; + } + } +} + +int entry_toilet(int argc, char **argv) { + enum MODE mode; + char **args = parse_options(argc, argv, &mode); + + + while (*args != NULL) { + struct map *map = open_map(*args); + if (map == NULL) { + fprintf(stderr, "toilet: fout bij lezen bestand"); + return 1; + } + + size_t count = get_count(mode, map); + printf("%li %s\n", count, *args); + + close_map(map); + args++; + } + + return 0; +} diff --git a/src/util/map.c b/src/util/map.c index 35e1b49..cd2da42 100644 --- a/src/util/map.c +++ b/src/util/map.c @@ -25,8 +25,8 @@ struct map *open_map(const char *fname) { } struct map *res = calloc(1, sizeof(struct map)); - res->addr = addr; + res->end = addr + sb.st_size; res->sb = sb; res->fd = fd; return res; diff --git a/src/util/map.h b/src/util/map.h index 232720f..67beb9c 100644 --- a/src/util/map.h +++ b/src/util/map.h @@ -2,6 +2,7 @@ struct map { char *addr; + char *end; struct stat sb; int fd; }; -- cgit v1.2.3-70-g09d2