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:
parent
546ed596d4
commit
dccbb40798
175
src/config.c
175
src/config.c
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ struct conf_opts_t {
|
||||||
typedef struct config_t {
|
typedef struct config_t {
|
||||||
char filename[9];
|
char filename[9];
|
||||||
char ext[4];
|
char ext[4];
|
||||||
uint16_t start;
|
uint32_t start;
|
||||||
uint16_t end;
|
uint32_t end;
|
||||||
uint16_t skip_a;
|
uint16_t skip_a;
|
||||||
uint16_t skip_b;
|
uint16_t skip_b;
|
||||||
struct conf_opts_t opts;
|
struct conf_opts_t opts;
|
||||||
|
|
Loading…
Reference in a new issue