diff options
| -rw-r--r-- | src/toilet.c | 123 | ||||
| -rw-r--r-- | src/util/map.c | 2 | ||||
| -rw-r--r-- | src/util/map.h | 1 | 
3 files changed, 125 insertions, 1 deletions
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 <assert.h> +#include <ctype.h> +#include <getopt.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#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;  };  | 
