#include #include #include #include #include #include #include #include #include #include "util/debug.h" #include "util/error.h" #include "util/versie.h" static char *shufrange = NULL; static char **lines = NULL; static size_t nlines = 0; static void shuf_lines() { size_t *js = calloc(nlines, sizeof(size_t)); errno = 0; if (getrandom(js, nlines*sizeof(size_t), 0) == -1) exit(1); for (ssize_t i = nlines - 1; i > 0; i--) { size_t j = js[i] % (nlines-1); char *x = lines[i]; lines[i] = lines[j]; lines[j] = x; } free(js); } static void usage(FILE *f) { fprintf(f, "Gebruik: hus [-hV] [BESTAND]\n" " hus -i LA-HO [-hV]\n" "\n" "Hussel de regels van het gegeven bestand.\n" "Als er geen bestand gegeven is, of bestand is -, hussel dan de regels op standaard invoer.\n" "\n" " -i LA-HO Genereer regels van laag naar hoog en hussel deze\n" " -h Toon deze hulptekst\n" " -V Toon versienummer\n"); } static char** parse_options(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "i:hV")) != -1) { switch (opt) { case 'i': shufrange = optarg; break; case 'h': usage(stdout); exit(0); case 'V': drukkedoos_print_versie(stdout); exit(0); case '?': fprintf(stderr, "hus: Ongeldige optie: -%c\n", optopt); usage(stderr); exit(1); } } return argv + optind; } static int exec_shufrange() { assert(shufrange != NULL); char *seploc = NULL; if ((seploc = strchr(shufrange, '-')) != NULL) { *seploc = '\0'; const long long start = strtoll(shufrange, NULL, 10); const long long end = strtoll(seploc+1, NULL, 10); if (start > end) { fprintf(stderr, "hus: HO groter dan LA\n"); return 1; } nlines = end - start + 1; lines = calloc(nlines, sizeof(char*)); for (long long i = 0; i <= start+end; i++) { long long n = i + start; asprintf(lines + i, "%lld", n); } } else { fprintf(stderr, "hus: geen LA en HO waarde opgegeven\n"); return 1; } return 0; } static int exec_shufstream(FILE *restrict stream) { size_t cap = 1 << 8; lines = malloc(sizeof(char*)*cap); char *line = NULL; size_t linen = 0; ssize_t nread = 0; while ((errno = 0, nread = getline(&line, &linen, stream)) != -1) { if (nread > 0 && line[nread-1] == '\n') line[--nread] = '\0'; if (nlines == cap) { cap *= 2; lines = realloc(lines, sizeof(char*)*cap); } lines[nlines] = strdup(line); nlines++; } free(line); return 0; } int entry_hus(int argc, char **argv) { int res; #define CHECK(f) if ((res = f) != 0) return res; char **args = parse_options(argc, argv); // count the amount of arguments provided size_t nargs; for (nargs = 0; args[nargs] != NULL; nargs++); if (shufrange) { CHECK(exec_shufrange()); } else if (nargs == 0 || (nargs == 1 && strcmp(args[0], "-") == 0)) { CHECK(exec_shufstream(stdin)); } else if (nargs == 1) { FILE *stream = fopen(args[0], "r"); if (stream == NULL) { fprintf(stderr, "hus: %s: kon bestand niet openen\n", args[0]); return 1; } CHECK(exec_shufstream(stream)); fclose(stream); } else { fprintf(stderr, "hus: teveel argumenten gegeven\n"); return 1; } shuf_lines(); for (size_t i = 0; i < nlines; i++) { printf("%s\n", lines[i]); } return 0; }