From dccbb407985bbe7c01a89165812940fade8e3233 Mon Sep 17 00:00:00 2001 From: snow flurry Date: Mon, 16 Nov 2020 17:32:03 -0800 Subject: [PATCH] config: add (non-working) implementation I believe there's a lot that's missing here, and honestly I don't like how messy it feels. I can already see a couple edge cases where things might break or work weirdly, but for now we can probably gloss over them... --- src/config.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/config.h | 4 +- 2 files changed, 176 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index 8f414f5..e5a5afe 100644 --- a/src/config.c +++ b/src/config.c @@ -1 +1,174 @@ -/* TODO */ +#include +#include +#include + +#include "config.h" + +#define PMSG(t, x) fprintf(stderr, t ":%s:%d: " x "\n", path, line) + +#define BUF_STORE(name) { \ + if (i >= 10) { \ + PMSG("error", name " is too big"); \ + err = 1; \ + } else { \ + ibuf[i] = ch; \ + i++; \ + } \ +} + +config_t * +parse_config(char *path) +{ + FILE *fd; + int res, state, line, ws, comment, err, i; +#define ST_FILENAME 0 +#define ST_EXT 1 +#define ST_START 2 +#define ST_END 3 +#define ST_SKIP_A 4 +#define ST_SKIP_B 5 +#define ST_OPTS 6 + char ch; + char ibuf[11]; + config_t *conf, *cur; + + fd = fopen(path, "r"); + if (fd == NULL) { + perror("couldn't open config"); + return NULL; + } + + conf = malloc(sizeof(config_t)); + if (conf == NULL) { + perror("couldn't allocate config"); + return NULL; + } + memset(conf, 0, sizeof(config_t)); + + state = ST_FILENAME; + line = 1; + ws = comment = err = 0; + i = 0; + while ((ch = getc(fd)) != EOF) { + switch (ch) { + case '\t': + case ' ': + if (comment) + continue; + + if (!ws) { + i = 0; + ws = 1; + state++; + /* convert offsets to uint32_t (or close enough) */ + switch (state) { + case ST_START: + cur->start = strtoul(ibuf, ibuf+strlen(ibuf), 10); + break; + case ST_END: + cur->end = strtoul(ibuf, ibuf+strlen(ibuf), 10); + break; + case ST_SKIP_A: + cur->skip_a = strtoul(ibuf, ibuf+strlen(ibuf), 10); + break; + case ST_SKIP_B: + cur->skip_b = strtoul(ibuf, ibuf+strlen(ibuf), 10); + break; + /* TODO: probably handle ST_OPTS here? */ + } + memset(ibuf, 0, 11); + } + break; + case '\r': /* dos line end */ + (void)getc(fd); + /* FALLTHROUGH */ + case '\n': + cur->next = malloc(sizeof(config_t)); + if (cur == NULL) { + perror("couldn't allocate config"); + err = 1; + break; + } + + if (state != ST_OPTS) { + PMSG("warn", "line ends early") + } + + /* reset state for next line */ + state = ST_FILENAME; + cur = cur->next; + memset(cur, 0, sizeof(config_t)); + ws = i = comment = 0; + line++; + break; + case '#': + comment = 1; + break; + default: + if (comment) + continue; + + ws = 0; + + /* not a special character, store into buffer */ + switch (state) { + case ST_FILENAME: + if (i >= 8) { + PMSG("error", "filename must be less than eight characters"); + err = 1; + } else { + cur->filename[i] = ch; + i++; + } + break; + case ST_EXT: + if (i >= 3) { + PMSG("error", "ext must be less than three characters"); + err = 1; + } else { + cur->ext[i] = ch; + i++; + } + break; + case ST_START: + BUF_STORE("start byte") + case ST_END: + BUF_STORE("end byte") + case ST_SKIP_A: + BUF_STORE("first byte skip") + case ST_SKIP_B: + BUF_STORE("second byte skip") + case ST_OPTS: + /* TODO */ + default: + PMSG("error", "too many columns"); + err = 1; + } + } + + if (err) + break; + } + + + if (err) { + free_config(conf); + conf = NULL; + } + + fclose(fd); + return conf; +} + +void +free_config(config_t *conf) +{ + config_t *cur, *prev; + + cur = conf; + while (cur != NULL) { + prev = cur; + cur = cur->next; + free(prev); + } +} diff --git a/src/config.h b/src/config.h index 74f3201..067d0b8 100644 --- a/src/config.h +++ b/src/config.h @@ -11,8 +11,8 @@ struct conf_opts_t { typedef struct config_t { char filename[9]; char ext[4]; - uint16_t start; - uint16_t end; + uint32_t start; + uint32_t end; uint16_t skip_a; uint16_t skip_b; struct conf_opts_t opts;