From c40f79737a4ce6ae0cd8bd6ea7f302217333e486 Mon Sep 17 00:00:00 2001 From: Charles Cabergs Date: Sat, 22 Aug 2020 19:43:03 +0200 Subject: Added Makefile --- shuf.c | 237 ----------------------------------------------------------------- 1 file changed, 237 deletions(-) delete mode 100644 shuf.c (limited to 'shuf.c') diff --git a/shuf.c b/shuf.c deleted file mode 100644 index 5b4808a..0000000 --- a/shuf.c +++ /dev/null @@ -1,237 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include -#include - -#define NUMBER_LEN(x) strlen(#x); - -static char *g_name = "shuf"; - -void fatal(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - fprintf(stderr, "%s: ", g_name); - vfprintf(stderr, format, ap); - fputc('\n', stderr); - va_end(ap); - exit(EXIT_FAILURE); -} - -long parse_ulong(char *str, char *error_msg) -{ - char *end; - long ret; - - errno = 0; - ret = strtol(str, &end, 10); - if (errno != 0 || ret < 0 || *end != '\0') - fatal("%s '%s'", error_msg, optarg); - return ret; -} - -typedef struct -{ - char **data; - size_t len; - size_t cap; -} t_lines; - -#define INITIAL_CAPACITY 64 - -void lines_init(t_lines *lines) -{ - lines->len = 0; - lines->cap = INITIAL_CAPACITY; - lines->data = malloc(lines->cap * sizeof(char*)); - if (lines->data == NULL) - fatal("%s", strerror(errno)); -} - -void lines_destroy(t_lines *lines) -{ - for (size_t i = 0; i < lines->len; i++) - free(lines->data[i]); - free(lines->data); -} - -#define GROWTH_FACTOR 2 - -void lines_push(t_lines *lines, char *line) -{ - if (lines->len >= lines->cap) - { - lines->cap *= GROWTH_FACTOR; - lines->data = realloc(lines->data, lines->cap * sizeof(char*)); - if (lines->data == NULL) - fatal("%s", strerror(errno)); - } - lines->data[lines->len] = line; - lines->len++; -} - -#define RANDOM_FILEPATH "/dev/random" - -int main(int argc, char **argv) -{ - int option; - long max_output = -1; - char *output_filepath = NULL; - bool repeat = false; - bool echo = false; - char delimiter = '\n'; - long range_start = -1; - long range_stop = -1; - - while ((option = getopt(argc, argv, "ei:n:o:rz")) != -1) - { - - switch (option) - { - case 'e': echo = true; break; - case 'r': repeat = true; break; - case 'o': output_filepath = optarg; break; - case 'z': delimiter = '\0'; break; - - case 'i': - { - char *hyphen = strchr(optarg, '-'); - if (hyphen == NULL) - fatal("invalid input range '%s'", optarg); - *hyphen = '\0'; - range_start = parse_ulong(optarg, "invalid input range"); - *hyphen = '-'; - range_stop = parse_ulong(hyphen + 1, "invalid input range"); - if (range_start > range_stop) - fatal("invalid input range '%s'", optarg); - break; - } - - case 'n': - max_output = parse_ulong(optarg, "invalid line count"); - break; - } - - } - if (range_start != -1 && echo) - fatal("cannot combine -e and -i options"); - if (range_start != -1 && optind != argc) - fatal("extra operand '%s'", argv[optind]); - if (!echo && argc - optind > 1) - fatal("extra operand '%s'", argv[optind]); - - unsigned int seed; - FILE *seed_file = fopen(RANDOM_FILEPATH, "r"); - if (seed_file == NULL) - fatal("%s: %s", RANDOM_FILEPATH, strerror(errno)); - fread(&seed, sizeof(seed), 1, seed_file); - srand(seed); - - t_lines lines; - lines_init(&lines); - - if (range_start != -1) - { - size_t buf_len = NUMBER_LEN(LONG_MAX); - for (; range_start <= range_stop; range_start++) - { - char *line = malloc(buf_len * sizeof(char)); - if (line == NULL) - fatal("%s", strerror(errno)); - sprintf(line, "%ld", range_start); - lines_push(&lines, line); - } - } - else if (echo) - { - for (; optind < argc; optind++) - { - char *line = strdup(argv[optind]); - if (line == NULL) - fatal("%s", strerror(errno)); - lines_push(&lines, line); - } - } - else - { - FILE *input = stdin; - if (optind != argc) - { - input = fopen(argv[optind], "r"); - if (input == NULL) - fatal("%s: %s", argv[optind], strerror(errno)); - } - - char *line = NULL; - size_t line_size = 0; - errno = 0; - while (getdelim(&line, &line_size, delimiter, input) != -1) - { - lines_push(&lines, line); - line = NULL; - line_size = 0; - } - if (errno != 0) - { - fclose(input); - fatal("%s: %s", argv[optind], strerror(errno)); - } - fclose(input); - } - - if (lines.len == 0) - { - lines_destroy(&lines); - return EXIT_SUCCESS; - } - for (size_t i = lines.len - 1; i > 0; i--) - { - size_t j = rand() % i; - char *tmp = lines.data[i]; - lines.data[i] = lines.data[j]; - lines.data[j] = tmp; - } - - FILE *output = stdout; - if (output_filepath != NULL) - { - output = fopen(output_filepath, "w"); - if (output == NULL) - fatal("%s: %s", output_filepath, strerror(errno)); - } - - if (repeat) - { - for (size_t i = 0; true; i = (i + 1) % lines.len) - { - if (fputs(lines.data[i], output) == EOF) - break; - if (echo || range_start != -1) - if (fputc('\n', output) == EOF) - break; - } - } - else - { - for (size_t i = 0; - max_output == -1 ? (i < lines.len) : (i < (unsigned long)max_output); - i++) - { - if (fputs(lines.data[i], output) == EOF) - break; - if (echo || range_start != -1) - if (fputc('\n', output) == EOF) - break; - } - } - fclose(output); - - lines_destroy(&lines); - return EXIT_SUCCESS; -} -- cgit