diff options
-rw-r--r-- | Maakbestand | 2 | ||||
-rw-r--r-- | src/toilet.c | 78 |
2 files changed, 69 insertions, 11 deletions
diff --git a/Maakbestand b/Maakbestand index cf87dd4..d4f3360 100644 --- a/Maakbestand +++ b/Maakbestand @@ -11,7 +11,7 @@ else endif CFLAGS += -D_GNU_SOURCE -DDRUKKEDOOS_VERSIE=\"$(VERSION)\" CFLAGS += -Isrc -I. -LDFLAGS := +LDFLAGS := -lm OBJDIR := obj TARGET := drukkedoos diff --git a/src/toilet.c b/src/toilet.c index c66896a..6d95427 100644 --- a/src/toilet.c +++ b/src/toilet.c @@ -2,6 +2,7 @@ #include <ctype.h> #include <getopt.h> #include <limits.h> +#include <tgmath.h> #include <pwd.h> #include <stdbool.h> #include <stdlib.h> @@ -19,8 +20,13 @@ static int modeMap; -// lines, words, bytes -static size_t totals[3] = {0}; +struct finfo { + size_t values[3]; + char *fname; +}; +static struct finfo *finfo = NULL; +static size_t finfolen = 0; +static size_t finfocap = 0; static void usage(FILE *f) { fprintf(f, @@ -132,16 +138,41 @@ static int mlog2(int val) { #undef C } +static void init_finfo(int argc) { + assert(finfo == NULL); + argc += 1; // one more for the total tally + if (argc < 8) argc = 8; + + finfo = calloc(argc, sizeof(struct finfo)); + finfocap = argc; +} + +static struct finfo *add_fname(char *fname) { + assert(finfo != NULL); + + if (finfolen == finfocap) { + finfocap *= 2; + finfo = realloc(finfo, sizeof(struct finfo)*finfocap); + } + + struct finfo *ptr = finfo + finfolen; + ptr->values[0] = 0; + ptr->values[1] = 0; + ptr->values[2] = 0; + ptr->fname = fname; + + finfolen++; + return ptr; +} + static int process(struct filebuf *fb, char *fname, bool) { + struct finfo *finfo = add_fname(fname); + for (enum MODE mode = 1; mode <= M_BYTES; mode <<= 1) { if (mode & modeMap) { - const size_t count = get_count(mode, fb); - printf("% 10li ", count); - - totals[mlog2(mode)] += count; + finfo->values[mlog2(mode)] = get_count(mode, fb); } } - printf("%s\n", fname); free_filebuf(fb); return 0; } @@ -150,6 +181,8 @@ static int process(struct filebuf *fb, char *fname, bool) { // unmappable files) int entry_toilet(int argc, char **argv) { + init_finfo(argc); + modeMap = 0; char **args = parse_options(argc, argv, &modeMap); if (modeMap == 0) { @@ -158,10 +191,35 @@ int entry_toilet(int argc, char **argv) { const int res = loop_files(args, process); - for (size_t i = 0; i < 3; i++) { - printf("% 10li ", totals[i]); + // tally file totals + { + struct finfo *ptr = add_fname("total"); + + for (size_t i = 0; i < 3; i++) { + for (size_t j = 0; j < finfolen; j++) { + ptr->values[i] += finfo[j].values[i]; + } + } } - puts("totaal"); + + // calculate required padding + int pad[3] = {0}; + for (size_t i = 0; i < finfolen; i++) { + for (size_t j = 0; j < 3; j++) { + const int sz = ceill(log10l(finfo[i].values[j])) + 1; + if (sz > pad[j]) pad[j] = sz; + } + } + + // print all results + for (size_t i = 0; i < finfolen; i++) { + struct finfo *ptr = finfo + i; + for (size_t j = 0; j < 3; j++) { + printf("% *li ", pad[j], ptr->values[j]); + } + printf("%s\n", ptr->fname); + } + return res; } |