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...
This commit is contained in:
snow flurry 2020-11-16 17:32:03 -08:00
parent 546ed596d4
commit dccbb40798
2 changed files with 176 additions and 3 deletions

View file

@ -1 +1,174 @@
/* TODO */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}
}

View file

@ -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;