diff --git a/Makefile b/Makefile index 7aa2571..a329c49 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ SRC = $(wildcard src/*.c) OBJ = $(subst .c,.o,$(subst src,work,$(SRC))) LDFLAGS = CFLAGS := -O2 -pipe -Wall -Wpedantic -Wshadow -ansi -CFLAGS += -Isrc/include/ -D_POSIX_C_SOURCE=2 +CFLAGS += -Isrc/include/ INSTALLDIR := /usr/bin/ OUT = ncdg diff --git a/src/include/config.h b/src/include/config.h index 1714176..09a7768 100644 --- a/src/include/config.h +++ b/src/include/config.h @@ -1,5 +1,6 @@ #define ESCAPE_CHAR '%' #define INCLUDE_CHAR '@' -#define VAR_CHAR '=' +#define VAR_CHAR '>' +#define SET_CHAR '=' #define MAX_INCLUDE_DEPTH 10 diff --git a/src/include/string.h b/src/include/strings.h similarity index 100% rename from src/include/string.h rename to src/include/strings.h diff --git a/src/include/vector.h b/src/include/vector.h new file mode 100644 index 0000000..5e24183 --- /dev/null +++ b/src/include/vector.h @@ -0,0 +1,19 @@ +#ifndef HAVE_VECTOR +#define HAVE_VECTOR + +#include + +struct vector { + void *data; + size_t len; + size_t alloc; + size_t membersize; +}; + +struct vector *newvectorsize(size_t membersize); +#define newvector(type) newvectorsize(sizeof(type)) +#define getvector(vector, type, ind) (((type *) (vector)->data)[ind]) +int addvector(struct vector *vector, void *item); +void freevector(struct vector *vector); + +#endif diff --git a/src/parse.c b/src/parse.c index 49587ee..893f74f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1,23 +1,56 @@ +#include + #include -#include +#include +#include #include -static int expandfile(struct string *expanded, char *filename, int level); +struct var { + struct string *var; + struct string *value; +}; + +struct expandfile { + struct string *data; + struct vector *vars; + /* This is a vector of struct var */ +}; + +static int expandfile(struct expandfile *ret, char *filename, int level); static struct string *getstring(FILE *file, char end); int parsefile(char *template, FILE *out) { - struct string *expanded; - expanded = newstring(); + int i; + struct expandfile *expanded; + expanded = malloc(sizeof *expanded); if (expanded == NULL) - return 1; + goto error1; + expanded->data = newstring(); + if (expanded->data == NULL) + goto error2; + expanded->vars = newvector(struct var); + if (expanded->vars == NULL) + goto error3; if (expandfile(expanded, template, 0)) - return 1; - fwrite(expanded->data, 1, expanded->len, stdout); + goto error4; + fwrite(expanded->data->data, 1, expanded->data->len, out); return 0; +error4: + for (i = 0; i < expanded->vars->len; ++i) { + freestring(getvector(expanded->vars, struct var, i).var); + freestring(getvector(expanded->vars, struct var, i).value); + } + freevector(expanded->vars); +error3: + freestring(expanded->data); +error2: + free(expanded); +error1: + return 1; } -static int expandfile(struct string *expanded, char *filename, int level) { +static int expandfile(struct expandfile *ret, char *filename, int level) { FILE *file; int c, linenum; file = fopen(filename, "r"); @@ -39,28 +72,37 @@ static int expandfile(struct string *expanded, char *filename, int level) { c = fgetc(file); switch (c) { case ESCAPE_CHAR: - if (appendchar(expanded, ESCAPE_CHAR)) + if (appendchar(ret->data, ESCAPE_CHAR)) + goto error; + if (appendchar(ret->data, ESCAPE_CHAR)) goto error; break; case VAR_CHAR: - if (appendchar(expanded, ESCAPE_CHAR)) + if (appendchar(ret->data, ESCAPE_CHAR)) goto error; for (;;) { if (c == EOF) goto error; - if (appendchar(expanded, c)) + if (appendchar(ret->data, c)) goto error; if (c == ESCAPE_CHAR) break; c = fgetc(file); } break; + case SET_CHAR: { + struct var var; + var.var = getstring(file, ' '); + var.value = getstring(file, ESCAPE_CHAR); + addvector(ret->vars, &var); + break; + } case INCLUDE_CHAR: { struct string *inclname; inclname = getstring(file, ESCAPE_CHAR); if (inclname == NULL) goto error; - if (expandfile(expanded, inclname->data, + if (expandfile(ret, inclname->data, level + 1)) return 1; freestring(inclname); @@ -78,7 +120,7 @@ static int expandfile(struct string *expanded, char *filename, int level) { case EOF: goto end; default: casedefault: - if (appendchar(expanded, c)) + if (appendchar(ret->data, c)) goto error; break; } diff --git a/src/string.c b/src/strings.c similarity index 89% rename from src/string.c rename to src/strings.c index 8ee7f00..e18a520 100644 --- a/src/string.c +++ b/src/strings.c @@ -1,7 +1,7 @@ #include #include -#include +#include struct string *newstring() { struct string *ret; @@ -25,9 +25,7 @@ int appendchar(struct string *string, char c) { if (string->len >= string->alloc) { char *newdata; size_t newalloc; - newalloc = string->alloc; - while (string->len >= newalloc) - newalloc *= 2; + newalloc = string->alloc * 2; newdata = realloc(string->data, newalloc); if (newdata == NULL) return 1; diff --git a/src/vector.c b/src/vector.c new file mode 100644 index 0000000..a89e629 --- /dev/null +++ b/src/vector.c @@ -0,0 +1,42 @@ +#include +#include + +#include + +struct vector *newvectorsize(size_t membersize) { + struct vector *ret; + ret = malloc(sizeof *ret); + if (ret == NULL) + return NULL; + ret->alloc = 20; + ret->membersize = membersize; + ret->data = malloc(ret->alloc * ret->membersize); + if (ret->data == NULL) { + free(ret); + return NULL; + } + ret->len = 0; + return ret; +} + +int addvector(struct vector *vector, void *item) { + if (vector->len >= vector->alloc) { + void *newdata; + size_t newalloc; + newalloc = vector->alloc * 2; + newdata = realloc(vector->data, newalloc * vector->alloc); + if (newdata == NULL) + return 1; + vector->data = newdata; + vector->alloc = newalloc; + } + memcpy((char *) vector->data + vector->len * vector->membersize, item, + vector->membersize); + ++vector->len; + return 0; +} + +void freevector(struct vector *vector) { + free(vector->data); + free(vector); +}