diff options
| -rw-r--r-- | bp.c | 2 | ||||
| -rw-r--r-- | grammar.c | 78 | ||||
| -rw-r--r-- | grammar.h | 1 | ||||
| -rw-r--r-- | types.h | 31 | ||||
| -rw-r--r-- | utils.c | 17 | ||||
| -rw-r--r-- | utils.h | 3 |
6 files changed, 80 insertions, 52 deletions
@@ -133,7 +133,7 @@ int main(int argc, char *argv[]) char path[PATH_MAX] = {0}; const char *rule = "find-all"; - grammar_t *g = new_grammar(); + grammar_t *g = new(grammar_t); // Load builtins: if (access("/etc/xdg/bp/builtins.bp", R_OK) != -1) @@ -10,24 +10,18 @@ #include "grammar.h" #include "utils.h" -grammar_t *new_grammar(void) -{ - grammar_t *g = new(grammar_t); - g->definitions = xcalloc(sizeof(def_t), (g->defcapacity = 128)); - return g; -} - +/* + * Add a definition to the grammar + */ void add_def(grammar_t *g, file_t *f, const char *src, const char *name, vm_op_t *op) { - if (g->defcount >= g->defcapacity) { - g->definitions = xrealloc(g->definitions, sizeof(&g->definitions[0])*(g->defcapacity += 32)); - } - int i = g->defcount; - g->definitions[i].file = f; - g->definitions[i].source = src; - g->definitions[i].name = name; - g->definitions[i].op = op; - ++g->defcount; + def_t *def = new(def_t); + def->next = g->firstdef; + def->file = f; + def->source = src; + def->name = name; + def->op = op; + g->firstdef = def; } /* @@ -65,39 +59,44 @@ vm_op_t *load_grammar(grammar_t *g, file_t *f) return ret; } +/* + * Look up a backreference or grammar definition by name + */ vm_op_t *lookup(grammar_t *g, const char *name) { - // Search backwards so newer backrefs/defs take precedence - for (int i = (int)g->backrefcount-1; i >= 0; i--) { - if (streq(g->backrefs[i].name, name)) { - return g->backrefs[i].op; - } + for (backref_t *b = g->firstbackref; b; b = b->next) { + if (streq(b->name, name)) + return b->op; } - for (int i = g->defcount-1; i >= 0; i--) { - if (streq(g->definitions[i].name, name)) { - return g->definitions[i].op; - } + for (def_t *d = g->firstdef; d; d = d->next) { + if (streq(d->name, name)) + return d->op; } return NULL; } +/* + * Push a backreference onto the backreference stack + */ void push_backref(grammar_t *g, const char *name, match_t *capture) { - if (g->backrefcount >= g->backrefcapacity) { - g->backrefs = xrealloc(g->backrefs, sizeof(g->backrefs[0])*(g->backrefcapacity += 32)); - } - size_t i = g->backrefcount++; - g->backrefs[i].name = name; - g->backrefs[i].capture = capture; + backref_t *backref = new(backref_t); + backref->name = name; + backref->capture = capture; vm_op_t *op = new(vm_op_t); op->op = VM_BACKREF; op->start = capture->start; op->end = capture->end; - op->len = -1; // TODO: maybe calculate this? + op->len = -1; // TODO: maybe calculate this? (nontrivial because of replacements) op->args.backref = capture; - g->backrefs[i].op = op; + backref->op = op; + backref->next = g->firstbackref; + g->firstbackref = backref; } +/* + * Push all the backreferences contained in a match onto the backreference stack + */ size_t push_backrefs(grammar_t *g, match_t *m) { if (m->op->op == VM_REF) return 0; @@ -111,14 +110,17 @@ size_t push_backrefs(grammar_t *g, match_t *m) return count; } +/* + * Pop a number of backreferences off the backreference stack + */ void pop_backrefs(grammar_t *g, size_t count) { - check(count <= g->backrefcount, "Attempt to pop %ld backrefs when there are only %ld", count, g->backrefcount); for ( ; count > 0; count--) { - //free(g->backrefs[i].op); // TODO: memory leak problem?? - int i = (int)g->backrefcount - 1; - memset(&g->backrefs[i], 0, sizeof(g->backrefs[i])); - --g->backrefcount; + backref_t *b = g->firstbackref; + g->firstbackref = b->next; + check(b, "Attempt to pop %ld more backrefs than there are", count); + xfree((void**)&b->op); + xfree((void**)&b); } } @@ -7,7 +7,6 @@ #include "file_loader.h" #include "types.h" -grammar_t *new_grammar(void); __attribute__((nonnull(1,3,4,5))) void add_def(grammar_t *g, file_t *f, const char *src, const char *name, vm_op_t *op); __attribute__((nonnull)) @@ -88,24 +88,33 @@ typedef struct match_s { vm_op_t *op; } match_t; - -typedef struct { +/* + * Pattern matching rule definition + */ +typedef struct def_s { const char *name; const char *source; file_t *file; vm_op_t *op; + struct def_s *next; } def_t; -typedef struct { - size_t defcount, defcapacity; - def_t *definitions; +/* + * Backreference (look up previous capture by name) + */ +typedef struct backref_s { + const char *name; + match_t *capture; + vm_op_t *op; + struct backref_s *next; +} backref_t; - size_t backrefcount, backrefcapacity; - struct { - const char *name; - match_t *capture; - vm_op_t *op; - } *backrefs; +/* + * Grammar (a collection of definitions) + */ +typedef struct { + def_t *firstdef; + backref_t *firstbackref; } grammar_t; #endif @@ -3,6 +3,7 @@ */ #include <ctype.h> +#include <stdlib.h> #include <unistd.h> #include "utils.h" @@ -186,6 +187,9 @@ size_t unescape_string(char *dest, const char *src, size_t bufsize) #undef PUT } +/* + * Fail and exit if a memory value is NULL + */ void *memcheck(void *p) { if (p == NULL) { @@ -195,7 +199,9 @@ void *memcheck(void *p) return p; } - +/* + * Case-insensitive memory comparison + */ int memicmp(const void *v1, const void *v2, size_t n) { int result = 0; @@ -205,4 +211,13 @@ int memicmp(const void *v1, const void *v2, size_t n) return result; } +/* + * Free memory, but also set the pointer to NULL for safety + */ +void xfree(void **p) +{ + free(*p); + p = NULL; +} + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1 @@ -31,7 +31,10 @@ int matchstr(const char **str, const char *target); __attribute__((nonnull)) size_t unescape_string(char *dest, const char *src, size_t bufsize); void *memcheck(void *p); +__attribute__((nonnull)) int memicmp(const void *s1, const void *s2, size_t n); +__attribute__((nonnull)) +void xfree(void **p); #endif // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1 |
