diff --git a/src/config.c b/src/config.c index e5a5afe..95548be 100644 --- a/src/config.c +++ b/src/config.c @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -6,9 +8,9 @@ #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"); \ +#define BUF_STORE(name, len) { \ + if (i >= len) { \ + PMSG("error", name " is too long"); \ err = 1; \ } else { \ ibuf[i] = ch; \ @@ -16,6 +18,8 @@ } \ } +static int parse_conf_opts(struct conf_opts_t *, char *); + config_t * parse_config(char *path) { @@ -29,7 +33,7 @@ parse_config(char *path) #define ST_SKIP_B 5 #define ST_OPTS 6 char ch; - char ibuf[11]; + char ibuf[32]; config_t *conf, *cur; fd = fopen(path, "r"); @@ -56,27 +60,33 @@ parse_config(char *path) if (comment) continue; + /* only run on the first whitespace */ if (!ws) { i = 0; ws = 1; state++; - /* convert offsets to uint32_t (or close enough) */ switch (state) { + /* convert offsets to uint32_t (or close enough) */ case ST_START: - cur->start = strtoul(ibuf, ibuf+strlen(ibuf), 10); + cur->start = strtoul(ibuf, NULL, 10); break; case ST_END: - cur->end = strtoul(ibuf, ibuf+strlen(ibuf), 10); + cur->end = strtoul(ibuf, NULL, 10); break; case ST_SKIP_A: - cur->skip_a = strtoul(ibuf, ibuf+strlen(ibuf), 10); + cur->skip_a = strtoul(ibuf, NULL, 10); break; case ST_SKIP_B: - cur->skip_b = strtoul(ibuf, ibuf+strlen(ibuf), 10); + cur->skip_b = strtoul(ibuf, NULL, 10); break; - /* TODO: probably handle ST_OPTS here? */ + /* parse options */ + case ST_OPTS: + if (parse_conf_opts(&cur->opts, ibuf) != 0) { + PMSG("error", "unable to parse opts (see above)"); + err = 1; + } } - memset(ibuf, 0, 11); + memset(ibuf, 0, 32); } break; case '\r': /* dos line end */ @@ -91,7 +101,7 @@ parse_config(char *path) } if (state != ST_OPTS) { - PMSG("warn", "line ends early") + PMSG("warn", "line ends early"); } /* reset state for next line */ @@ -117,7 +127,7 @@ parse_config(char *path) PMSG("error", "filename must be less than eight characters"); err = 1; } else { - cur->filename[i] = ch; + cur->filename[i] = toupper(ch); i++; } break; @@ -126,20 +136,20 @@ parse_config(char *path) PMSG("error", "ext must be less than three characters"); err = 1; } else { - cur->ext[i] = ch; + cur->ext[i] = toupper(ch); i++; } break; case ST_START: - BUF_STORE("start byte") + BUF_STORE("start byte", 10); case ST_END: - BUF_STORE("end byte") + BUF_STORE("end byte", 10); case ST_SKIP_A: - BUF_STORE("first byte skip") + BUF_STORE("first byte skip", 10); case ST_SKIP_B: - BUF_STORE("second byte skip") + BUF_STORE("second byte skip", 10); case ST_OPTS: - /* TODO */ + BUF_STORE("option string", 31); default: PMSG("error", "too many columns"); err = 1; @@ -160,6 +170,42 @@ parse_config(char *path) return conf; } +#define STORE_VAL(name, var, lim) { \ + val = strtoul(cur+4, NULL, 10); \ + if (val > lim) { \ + fprintf(stderr, "err: " name " value out of bounds\n"); \ + return 1; \ + } else { \ + var = val; \ + } \ +} + +/* + * Parses the options column of the config, ex. + * "xor=10,add=5,shl=2" + */ +static int +parse_conf_opts(struct conf_opts_t *opts, char *parse) +{ + char *cur, *last; + unsigned int val; + + for ((cur = strtok_r(parse, ",", &last)); cur; + (cur = strtok_r(NULL, ",", &last))) { + if (!strncmp(cur, "xor=", 4)) { + STORE_VAL("xor", opts->bit_xor, 0xff); + } else if (!strncmp(cur, "add=", 4)) { + STORE_VAL("add", opts->add, 0xff); + } else if (!strncmp(cur, "shr=", 4)) { + STORE_VAL("shr", opts->shr, 8); + } else if (!strncmp(cur, "shl=", 4)) { + STORE_VAL("shl", opts->shl, 8); + } + } + + return 0; +} + void free_config(config_t *conf) {