aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bp.c2
-rw-r--r--grammar.c78
-rw-r--r--grammar.h1
-rw-r--r--types.h31
-rw-r--r--utils.c17
-rw-r--r--utils.h3
6 files changed, 80 insertions, 52 deletions
diff --git a/bp.c b/bp.c
index cefb5aa..bcc8b98 100644
--- a/bp.c
+++ b/bp.c
@@ -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)
diff --git a/grammar.c b/grammar.c
index 5284225..f287f46 100644
--- a/grammar.c
+++ b/grammar.c
@@ -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);
}
}
diff --git a/grammar.h b/grammar.h
index 0e77cad..7aa92fc 100644
--- a/grammar.h
+++ b/grammar.h
@@ -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))
diff --git a/types.h b/types.h
index e497c44..67d5e33 100644
--- a/types.h
+++ b/types.h
@@ -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
diff --git a/utils.c b/utils.c
index cac2c7d..c18ef9e 100644
--- a/utils.c
+++ b/utils.c
@@ -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
diff --git a/utils.h b/utils.h
index 75026c6..7fde16f 100644
--- a/utils.h
+++ b/utils.h
@@ -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