#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 hoeveelheid 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); // (c) Tom Forging 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++; } // handle case if file does not have trailing newline 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; }