aboutsummaryrefslogtreecommitdiff
path: root/src/remembering-c.c
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2021-06-27 08:16:17 -0300
committerEuAndreh <eu@euandre.org>2021-06-27 08:16:17 -0300
commitf29de2217171a7e94320b5e754b930dc63e116f7 (patch)
tree16b92cd97efbc1f6a3b17e0e6efd02af78fc658a /src/remembering-c.c
parentMakefile: Remove $(LDLIBS) (diff)
downloadremembering-f29de2217171a7e94320b5e754b930dc63e116f7.tar.gz
remembering-f29de2217171a7e94320b5e754b930dc63e116f7.tar.xz
src/remembering-c.c: Restart C version
Diffstat (limited to 'src/remembering-c.c')
-rw-r--r--src/remembering-c.c965
1 files changed, 66 insertions, 899 deletions
diff --git a/src/remembering-c.c b/src/remembering-c.c
index 2dda122..3f66473 100644
--- a/src/remembering-c.c
+++ b/src/remembering-c.c
@@ -2,942 +2,109 @@
#define _POSIX_C_SOURCE 200809L
#endif
-/*
-#include <errno.h>
-#include <libgen.h>
-#include <stdio.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#include <sys/stat.h>
#include <unistd.h>
-#ifdef FALLIBLE
-#include <fallible.h>
-#include <fallible/alloc.h>
-#include <fallible/string.h>
-#endif
-
-#ifdef TEST
-#include <assert.h>
-
-static void testing(const char *message) {
- fprintf(stderr, "testing: %s...", message);
-}
-
-static void test_ok() {
- fprintf(stderr, " OK.\n");
-}
-
-static FILE *testfile() {
- char filename[] = "remembering-test.XXXXXX";
-
- errno = 0;
- int fd = mkstemp(filename);
- if (fd == -1) {
- perror("tmpfile mkstemp");
- return NULL;
- }
-
- errno = 0;
- FILE *f = fdopen(fd, "w");
- if (!f) {
- perror("tmpfile fdopen");
- close(fd);
- return NULL;
- }
-
- return f;
-}
-
-static char *testdir() {
- char dirname[] = "remembering-test.XXXXXX";
-
- errno = 0;
- char *dircpy = malloc(strlen(dirname) + 1);
- if (!dircpy) {
- perror("malloc");
- return NULL;
- }
-
- errno = 0;
- char *dir = mkdtemp(dirname);
- if (!dir) {
- perror("mkdtemp");
- free(dircpy);
- return NULL;
- }
-
- strcpy(dircpy, dir);
-
- return dircpy;
-}
-
-static void assert_file_contents(const char *const filename, const char *const contents) {
-
-}
-#endif
+const int EXIT_ERROR = 1;
+const int EXIT_USAGE = 2;
-static int print_usage(FILE *stream, char *name) {
- errno = 0;
- fprintf(stream, "Usage: %s -p PROFILE -c 'COMMAND'\n",
- name ? name : "remembering");
- if (errno) {
- perror("fprintf");
+int usage(FILE *stream) {
+ const char *const msg = "Usage: remembering -p PROFILE -c COMMAND\n";
+ if (fprintf(stream, msg) < 0) {
+ perror("usage()");
return -1;
}
return 0;
}
-#ifdef TEST
-static void print_usage_test() {
- {
- testing("print_usage a-name");
- FILE *f = testfile();
- if (!f) {
- exit(EXIT_FAILURE);
- }
-
- int ret = print_usage(f, "a-name");
- fclose(f);
- if (ret) {
- exit(EXIT_FAILURE);
- }
-
- assert_file_contents(f, "Usage: a-name -p PROFILE -c 'COMMAND'\n");
-
- test_ok();
- }
- {
- testing("print_usage NULL");
- FILE *f = testfile();
- if (!f) {
- exit(EXIT_FAILURE);
- }
-
- int ret = print_usage(f, NULL);
- fclose(f);
- if (ret) {
- exit(EXIT_FAILURE);
- }
-
- assert_file_contents(f, "Usage: remembering -p PROFILE -c 'COMMAND'\n");
-
- test_ok();
- }
-}
-#endif
-
-static void print_help(FILE *stream) {
- const char *help_text =
- "\n"
- "Options:\n"
- " -p PROFILE profile to be used for gathering and storing data\n"
- " -c 'COMMAND' command to be run, reading from STDIN, writing to "
- "STDOUT\n"
- " -h show this help\n"
- " -V print program version\n"
- "See remembering(1) manpages for more information.\n";
- fprintf(stream, "%s", help_text);
-}
-
-static void print_missing(FILE *stream, char *text) {
- fprintf(stream, "Missing option: %s\n", text);
-}
-
-static void print_version(FILE *stream) {
- fprintf(stream, "remembering-%s %s\n", VERSION, DATE);
-}
-
-static int get_options(FILE *out, FILE *err, int argc, char *argv[],
- char **command, char **profile) {
- for (int i = 0; i < argc; i++) {
- if (strcmp(argv[i], "--help") == 0) {
- print_usage(out, argv[0]);
- print_help(out);
- return 1;
- } else if (strcmp(argv[i], "--version")) {
- print_version(out);
- return 1;
- }
- }
-
- char *profilearg = NULL;
- char *commandarg = NULL;
- int option;
- while ((option = getopt(argc, argv, "c:p:hV")) != -1) {
- switch (option) {
- case 'c':
- commandarg = optarg;
- break;
- case 'p':
- profilearg = optarg;
- break;
- case 'h':
- print_usage(out, argv[0]);
- print_help(out);
- return 1;
- case 'V':
- print_version(out);
- return 1;
- }
- }
-
- if (!commandarg) {
- print_missing(err, "-c 'COMMAND'");
- print_usage(err, argv[0]);
- return -1;
- }
-
- if (!profilearg) {
- print_missing(err, "-p 'PROFILE'");
- print_usage(err, argv[0]);
- return 1;
- }
-
- *command = strdup(commandarg);
- if (!*command) {
- perror("strdup");
+int help(FILE *stream) {
+ const char *const msg =
+ "Options:\n"
+ " -p, PROFILE profile to be used for gathering and storing data\n"
+ " -c, COMMAND commant to be run, reading from STDIN, writing to STDOUT\n"
+ " -h, --help show this help\n"
+ " -V, --version print the version number\n"
+ "\nSee \"man remembering\" for more information\n";
+ if (fprintf(stream, msg) < 0) {
+ perror("help()");
return -1;
}
- *profile = strdup(profilearg);
- if (!*profile) {
- perror("strdup");
- free(*command);
- return -1;
- }
-
return 0;
}
-#ifdef FALLIBLE
-static int fallible_get_options(FILE *out, FILE *err, int argc, char *argv[],
- char **command, char **profile,
- const char *const filename, int lineno) {
- if (fallible_should_fail(filename, lineno)) {
+int version(FILE *stream) {
+ const char *const msg = "remembering-" VERSION " " DATE "\n";
+ if (fprintf(stream, msg) < 0) {
+ perror("version()");
return -1;
}
- return get_options(out, err, argc, argv, command, profile);
-}
-
-#define get_options(out, err, argc, argv, command, profile) \
- fallible_get_options(out, err, argc, argv, command, profile, __FILE__, \
- __LINE__)
-#endif
-
-#ifdef TEST
-int arrlen(char **argv) {
- int count = 0;
- while (argv[count] != NULL) {
- count++;
- }
- return count;
-}
-
-void get_options_test() {
- {
- testing("get_options when given -h, -V and --help");
- FILE *f = tmpfile();
- if (!f) {
- exit(EXIT_FAILURE);
- }
-
- char *argvs[13][6] = {
- {"--help", NULL},
- {"other", "arguments before", "--help", NULL},
- {"some", "--help", "arguments after", NULL},
- {"--help", "all", "arguments after", NULL},
- {"-h", NULL},
- {"-V", NULL},
- {"-hc", "1", NULL},
- {"-hp", "2", NULL},
- {"-hV", NULL},
- {"-Vh", NULL},
- {"-p", "p", "-h", NULL},
- {"-p", "p", "-c", "c", "-h", NULL},
- {NULL},
- };
- int rows = 0;
- while (argvs[rows][0] != NULL) {
- rows++;
- }
-
-#ifdef DISABLE
- int ret;
- char *command = NULL;
- char *profile = NULL;
- for (int i = 0; i < rows; i++) {
- char **argv = argvs[i];
- ret = get_options(f, f, arrlen(argvs[i]), argv, &command, &profile);
- if (ret == -1) {
- fclose(f);
- exit(EXIT_FAILURE);
- }
-
- assert(command == NULL);
- assert(profile == NULL);
- assert(ret == 1);
- }
-#endif
-
- fclose(f);
- test_ok();
- }
- // { "" },
-}
-#endif
-
-static int mkdir_p(char *path, mode_t mode) {
- struct stat s;
- if (stat(path, &s) == 0 && S_ISDIR(s.st_mode)) {
- return 0;
- }
-
- char *parent = dirname(path);
- int ret = mkdir_p(parent, mode);
- if (ret) {
- return ret;
- }
- return mkdir(path, mode);
-}
-
-#ifdef FALLIBLE
-static int fallible_mkdir_p(char *path, mode_t mode, const char *const filename,
- int lineno) {
- if (fallible_should_fail(filename, lineno)) {
- return -1;
- }
- return mkdir_p(path, mode);
-}
-
-#define mkdir_p(path, mode) fallible_mkdir_p(path, mode, __FILE__, __LINE__)
-#endif
-
-#ifdef TEST
-static void mkdir_p_test() {
-{
-testing("mkdir_p a single directory");
-
-char *dir = tmpdir();
-if (!dir) {
-exit(EXIT_FAILURE);
-}
-
-int ret = mkdir_p(dir, 0755);
-if (ret) {
-free(dir);
-exit(EXIT_FAILURE);
-}
-
-free(dir);
-test_ok();
-}
-{
-testing("mkdir_p nested directories");
-
-const char *const dir_suffix = "/a/b/c/d/e";
-char *dir_prefix = tmpdir();
-if (!dir_prefix) {
-exit(EXIT_FAILURE);
-}
-
- char *dir = malloc(strlen(dir_prefix) + strlen(dir_suffix) + 1);
- if (!dir) {
- free(dir_prefix);
- exit(EXIT_FAILURE);
- }
-
- strcpy(dir, dir_prefix);
- strcat(dir, dir_suffix);
-
-int ret = mkdir_p(dir, 0755);
-if (ret) {
- free(dir);
- free(dir_prefix);
-exit(EXIT_FAILURE);
-}
-
- free(dir);
- free(dir_prefix);
-test_ok();
-}
-}
-#endif
-
-static char *expand_profile_name(const char *const profile_name) {
- char *prefix = NULL;
- char *env_prefix = getenv("XDG_DATA_HOME");
- if (env_prefix) {
- prefix = strdup(env_prefix);
- if (!prefix) {
- return NULL;
- }
- } else {
- char *home = getenv("HOME");
- char *path = "/.local/share/remembering";
- prefix = malloc(strlen(home) + strlen(path) + 1);
- if (!prefix) {
- return NULL;
- }
- strcpy(prefix, home);
- strcat(prefix, path);
- }
- char *separator = "/";
- char *expanded_profile =
- malloc(strlen(prefix) + strlen(separator) + strlen(profile_name) + 1);
- if (!expanded_profile) {
- free(prefix);
- return NULL;
- }
- strcpy(expanded_profile, prefix);
- strcat(expanded_profile, separator);
- strcat(expanded_profile, profile_name);
-
- free(prefix);
-
- errno = 0;
- int ret = mkdir_p(dirname(expanded_profile), 0755);
- if (ret) {
- perror("mkdir_p");
- return NULL;
- }
- return expanded_profile;
-}
-
-#ifdef FALLIBLE
-static char *fallible_expand_profile_name(const char *const profile_name,
- const char *const filename,
- int lineno) {
- if (fallible_should_fail(filename, lineno)) {
- return NULL;
- }
- return expand_profile_name(profile_name);
-}
-
-#define expand_profile_name(profile_name) \
- fallible_expand_profile_name(profile_name, __FILE__, __LINE__)
-#endif
-
-#ifdef TEST
-static void expand_profile_name_test() {
- {
- testing("expand_profile_name");
- if (0) {
- expand_profile_name("oij");
- }
- test_ok();
- }
-}
-#endif
-
-static const size_t RANKINGS_INITIAL_SIZE = 100;
-static const int RANKINGS_GROWTH_MULTIPLIER = 2;
-
-struct Rankings {
- size_t count;
- size_t size;
- char **values;
- int *ranks;
-};
-
-static struct Rankings *rankings_new() {
- struct Rankings *r = malloc(sizeof(struct Rankings));
- if (!r) {
- return NULL;
- }
- r->count = 0;
- r->size = RANKINGS_INITIAL_SIZE;
- r->values = malloc(r->size * sizeof(char *));
- if (!r->values) {
- free(r);
- return NULL;
- }
- r->ranks = malloc(r->size * sizeof(int));
- if (!r->ranks) {
- free(r->values);
- free(r);
- return NULL;
- }
- return r;
-}
-
-#ifdef FALLIBLE
-static struct Rankings *fallible_rankings_new(const char *const filename,
- int lineno) {
- if (fallible_should_fail(filename, lineno)) {
- return NULL;
- }
- return rankings_new();
-}
-
-#define rankings_new() fallible_rankings_new(__FILE__, __LINE__)
-#endif
-
-static void rankings_free(struct Rankings *r) {
- if (!r) {
- return;
- }
- for (size_t i = 0; i < r->count; i++) {
- free(r->values[i]);
- }
- free(r->values);
- free(r->ranks);
- free(r);
-}
-
-static int rankings_insert(struct Rankings *r, char *value, int rank) {
- if (r->count == r->size) {
- r->size *= RANKINGS_GROWTH_MULTIPLIER;
- char **new_values = realloc(r->values, r->size * sizeof(char *));
- if (!new_values) {
- return -1;
- }
- r->values = new_values;
- int *new_ranks = realloc(r->ranks, r->size * sizeof(int));
- if (!new_ranks) {
- return -1;
- }
- r->ranks = new_ranks;
- }
- r->values[r->count] = value;
- r->ranks[r->count] = rank;
- r->count++;
return 0;
}
-#ifdef FALLIBLE
-static int fallible_rankings_insert(struct Rankings *r, char *value, int rank,
- const char *const filename, int lineno) {
- if (fallible_should_fail(filename, lineno)) {
- return -1;
- }
- return rankings_insert(r, value, rank);
-}
-
-#define rankings_insert(r, value, rank) \
- fallible_rankings_insert(r, value, rank, __FILE__, __LINE__)
-#endif
-
-#ifdef TEST
-static void rankings_test() {
- {
- testing("struct Rankings expands its size when needed");
- struct Rankings *r = rankings_new();
- if (!r) {
- exit(EXIT_FAILURE);
- }
- size_t some_limit = RANKINGS_INITIAL_SIZE + 1;
- int ret;
- for (size_t i = 0; i < some_limit; i++) {
- char *s = strdup("some string");
- ret = rankings_insert(r, s, i);
- if (ret) {
- free(s);
- rankings_free(r);
- exit(EXIT_FAILURE);
- }
- }
-
- assert(r->size == RANKINGS_INITIAL_SIZE * RANKINGS_GROWTH_MULTIPLIER);
- assert(r->count == some_limit);
-
- rankings_free(r);
- test_ok();
- }
-
- {
- testing("an empty Rankings doesn't leak");
- struct Rankings *r = rankings_new();
- if (!r) {
- exit(EXIT_FAILURE);
- }
-
- assert(r->size == RANKINGS_INITIAL_SIZE);
- assert(r->count == 0);
-
- rankings_free(r);
- test_ok();
- }
-}
-#endif
-
-static const char RANKING_DELIMITER = ':';
-
-int parse_ranked_line(FILE *stream, const char *entry, char **value,
- int *rank) {
- char *value_substr = strchr(entry, RANKING_DELIMITER);
- if (value_substr == NULL) {
- fprintf(stream, "WARN: Missing delimiter ('%c') in line: %s\n",
- RANKING_DELIMITER, entry);
- return -1;
- }
-
- int rank_strlen = value_substr - entry;
- char *rank_str = strndup(entry, rank_strlen);
- if (!rank_str) {
+int missing(FILE *stream, const char *const argument) {
+ const char *const msg = "Missing option: %s\n";
+ if (fprintf(stream, msg, argument) < 0) {
+ perror("missing()");
return -1;
}
- *rank = atoi(rank_str);
- free(rank_str);
-
- *value = malloc(strlen(value_substr) + 1);
- if (!*value) {
- return -1;
- }
- strcpy(*value, entry + (rank_strlen + 1 / * RANKING_DELIMITER * /));
-
return 0;
}
-#ifdef FALLIBLE
-int fallible_parse_ranked_line(FILE *stream, const char *entry, char **value,
- int *rank, const char *const filename,
- int lineno) {
- if (fallible_should_fail(filename, lineno)) {
- return -1;
- }
- return parse_ranked_line(stream, entry, value, rank);
-}
-
-#define parse_ranked_line(stream, entry, value, rank) \
- fallible_parse_ranked_line(stream, entry, value, rank, __FILE__, __LINE__)
-#endif
-
+int main(int argc, char *argv[]) {
#ifdef TEST
-static void parse_ranked_line_test() {
- {
- testing("parse_ranked_line with an empty string");
- FILE *f = tmpfile();
- if (!f) {
- exit(EXIT_FAILURE);
- }
-
- char *value;
- int rank;
- int ret = parse_ranked_line(f, "", &value, &rank);
- assert(ret == -1);
- fclose(f);
- test_ok();
- }
- {
- testing("parse_ranked_line when RANKING DELIMITER is missing");
- FILE *f = tmpfile();
- if (!f) {
- exit(EXIT_FAILURE);
- }
-
- char *value;
- int rank, ret;
-
- ret = parse_ranked_line(f, "0 command", &value, &rank);
- assert(ret == -1);
-
- ret = parse_ranked_line(f, "1", &value, &rank);
- assert(ret == -1);
-
- fclose(f);
- test_ok();
- }
- {
- testing("parse_ranked_line with a happy path examples");
- char *value;
- int rank;
- int ret;
-
- ret = parse_ranked_line(stderr, "0:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == 0);
- free(value);
-
- ret = parse_ranked_line(stderr, "10:another command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "another command") == 0);
- assert(rank == 10);
- free(value);
-
- ret = parse_ranked_line(stderr, "123:123", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "123") == 0);
- assert(rank == 123);
- free(value);
-
- ret = parse_ranked_line(stderr, "-123:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == -123);
- free(value);
-
- ret = parse_ranked_line(stderr, "0:0", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "0") == 0);
- assert(rank == 0);
- free(value);
-
- ret = parse_ranked_line(stderr, "0:command with : in the middle", &value,
- &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command with : in the middle") == 0);
- assert(rank == 0);
- free(value);
-
- ret = parse_ranked_line(
- stderr, "0:::command:with:multiple:::in:the:middle:", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "::command:with:multiple:::in:the:middle:") == 0);
- assert(rank == 0);
- free(value);
-
- test_ok();
- }
- {
- testing("parse_ranked_line with an empty command");
- char *value;
- int rank;
-
- int ret = parse_ranked_line(stderr, "0:", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "") == 0);
- assert(rank == 0);
- free(value);
-
- test_ok();
- }
- {
- testing("parse_ranked_line with a bad rank numbers");
- char *value;
- int rank;
- int ret;
-
- ret = parse_ranked_line(stderr, ":command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == 0);
- free(value);
-
- ret = parse_ranked_line(stderr, "1 2 3:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == 1);
- free(value);
-
- ret = parse_ranked_line(stderr, ".1:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == 0);
- free(value);
-
- ret = parse_ranked_line(stderr, "3.14:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == 3);
- free(value);
-
- ret = parse_ranked_line(stderr, ":5:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "5:command") == 0);
- assert(rank == 0);
- free(value);
-
- ret = parse_ranked_line(stderr, "command:command", &value, &rank);
- if (ret) {
- exit(EXIT_FAILURE);
- }
- assert(ret == 0);
- assert(strcmp(value, "command") == 0);
- assert(rank == 0);
- free(value);
-
- test_ok();
- }
-}
+ return EXIT_SUCCESS;
#endif
-struct GetlineParams {
- char *line;
- size_t len;
- ssize_t read;
- FILE *stream;
-};
-
-int get_stdin(struct GetlineParams *s_params, struct GetlineParams *p_params,
- struct Rankings *p_rankings) {
- s_params->read = getline(&s_params->line, &s_params->len, s_params->stream);
- if (s_params->read == -1) {
- while ((p_params->read = getline(&p_params->line, &p_params->len,
- p_params->stream)) != -1) {
- char *value;
- int rank;
- int ret;
- if ((ret = parse_ranked_line(stderr, p_params->line, &value, &rank)) ==
- -1) {
- return ret;
- }
- if ((ret = rankings_insert(p_rankings, value, rank)) == -1) {
- return ret;
- }
- }
- return 1;
- }
- return 0;
-}
-
-int get_profile(struct GetlineParams *s_params, struct GetlineParams *p_params,
- struct Rankings *s_rankings, struct Rankings *p_rankings) {
- p_params->read = getline(&p_params->line, &p_params->len, p_params->stream);
- if (p_params->read == -1) {
- while ((s_params->read = getline(&s_params->line, &s_params->len,
- s_params->stream)) != -1) {
- char *s_value_copy = strdup(s_params->line);
- if (!s_value_copy) {
- return -1;
- }
- char *p_value_copy = strdup(s_params->line);
- if (!p_value_copy) {
- free(s_value_copy);
- return -1;
- }
-
- int ret;
- if ((ret = rankings_insert(s_rankings, s_value_copy, 0)) == -1) {
- free(s_value_copy);
- free(p_value_copy);
- return -1;
- }
-
- // profile grows with stdin entries
- if ((ret = rankings_insert(p_rankings, p_value_copy, 0)) == -1) {
- free(s_value_copy);
- free(p_value_copy);
- return -1;
- }
+ for (int i = 0; i < argc; i++) {
+ if (strcmp("--", argv[i]) == 0) {
+ break;
+ } else if (strcmp("--help", argv[i]) == 0) {
+ if (usage(stdout)) return EXIT_ERROR;
+ if (help(stdout)) return EXIT_ERROR;
+ return EXIT_SUCCESS;
+ } else if (strcmp("--version", argv[i]) == 0) {
+ if (version(stdout)) return EXIT_ERROR;
+ return EXIT_SUCCESS;
}
- return 1;
}
- return 0;
-}
-
-int merge_stdin_with_profile(char *profile_name, struct Rankings *s_rankings,
- struct Rankings *p_rankings) {
- FILE *profile = fopen(profile_name, "r");
- struct GetlineParams s_params = {
- .line = NULL, .len = 0, .read = 0, .stream = stdin};
- struct GetlineParams p_params = {
- .line = NULL, .len = 0, .read = 0, .stream = profile};
-
- int stop = get_stdin(&s_params, &p_params, p_rankings) ||
- get_profile(&s_params, &p_params, s_rankings, p_rankings);
- while (!stop) {
- char *value;
- int rank;
- parse_ranked_line(stderr, p_params.line, &value, &rank);
- int cmp = strcmp(s_params.line, value);
- if (cmp == 0) {
- rankings_insert(s_rankings, value, rank);
- rankings_insert(p_rankings, value, rank); // double free
- stop = get_stdin(&s_params, &p_params, p_rankings) ||
- get_profile(&s_params, &p_params, s_rankings, p_rankings);
- continue;
- }
-
- if (cmp < 0) {
- char *value_copy = malloc(strlen(s_params.line) + 1);
- strcpy(value_copy, s_params.line);
- int *rank = malloc(sizeof(int));
- *rank = 0;
- rankings_insert(s_rankings, value_copy, rank);
- rankings_insert(p_rankings, value_copy, rank);
- stop = get_stdin(&s_params, &p_params, p_rankings);
- tuple_free(&t);
- continue;
- }
-
- if (cmp > 0) {
- rankings_insert(p_rankings, t.first, t.second);
- stop = get_profile(&s_params, &p_params, s_rankings, p_rankings);
- tuple_free(&t);
- continue;
+ int option;
+ const char *profile = NULL;
+ const char *command = NULL;
+ while ((option = getopt(argc, argv, "p:c:hV")) != -1) {
+ switch (option) {
+ case 'p':
+ profile = optarg;
+ break;
+ case 'c':
+ command = optarg;
+ break;
+ case 'h':
+ if (usage(stdout)) return EXIT_ERROR;
+ if (help(stdout)) return EXIT_ERROR;
+ return EXIT_SUCCESS;
+ case 'V':
+ if (version(stdout)) return EXIT_ERROR;
+ return EXIT_SUCCESS;
+ default:
+ if (usage(stderr)) return EXIT_ERROR;
+ return EXIT_USAGE;
}
}
- free(s_params.line);
- free(p_params.line);
- fclose(profile);
-
- if (stop == -1) {
- return stop;
+ if (!profile) {
+ if (missing(stderr, "-p PROFILE")) return EXIT_ERROR;
+ if (usage(stderr)) return EXIT_ERROR;
+ return EXIT_USAGE;
}
- return 0;
-}
-#ifdef TEST
-static void unit_tests() {
- print_usage_test();
- get_options_test();
- mkdir_p_test();
- expand_profile_name_test();
- rankings_test();
- parse_ranked_line_test();
-}
-#endif
-
-int main(int argc, char *argv[]) {
-#ifdef TEST
- unit_tests();
- return EXIT_SUCCESS;
-#endif
-
- int ret;
-
- char *command, *profile;
- ret = get_options(stdout, stderr, argc, argv, &command, &profile);
- if (ret == -1) {
- return EXIT_FAILURE;
- } else if (ret) {
- return EXIT_SUCCESS;
+ if (!command) {
+ if (missing(stderr, "-c COMMAND")) return EXIT_ERROR;
+ if (usage(stderr)) return EXIT_ERROR;
+ return EXIT_USAGE;
}
-}
-*/
-int main() {
return 0;
}