aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--definitions.c8
-rw-r--r--definitions.h8
-rw-r--r--match.c12
-rw-r--r--pattern.c42
-rw-r--r--types.h9
5 files changed, 37 insertions, 42 deletions
diff --git a/definitions.c b/definitions.c
index a19d3b8..0c99f9b 100644
--- a/definitions.c
+++ b/definitions.c
@@ -55,10 +55,10 @@ def_t *load_grammar(def_t *defs, file_t *f)
//
// Look up a backreference or grammar definition by name
//
-def_t *lookup(def_t *defs, const char *name)
+def_t *lookup(def_t *defs, size_t namelen, const char *name)
{
for ( ; defs; defs = defs->next) {
- if (strlen(name) == defs->namelen && strncmp(defs->name, name, defs->namelen) == 0)
+ if (namelen == defs->namelen && strncmp(defs->name, name, namelen) == 0)
return defs;
}
return NULL;
@@ -67,13 +67,13 @@ def_t *lookup(def_t *defs, const char *name)
//
// Push a backreference onto the backreference stack
//
-def_t *with_backref(def_t *defs, file_t *f, const char *name, match_t *m)
+def_t *with_backref(def_t *defs, file_t *f, size_t namelen, const char *name, match_t *m)
{
pat_t *backref = new_pat(f, m->start, BP_BACKREF);
backref->end = m->end;
backref->len = -1; // TODO: maybe calculate this? (nontrivial because of replacements)
backref->args.backref = m;
- return with_def(defs, strlen(name), name, backref);
+ return with_def(defs, namelen, name, backref);
}
//
diff --git a/definitions.h b/definitions.h
index 8c3ae87..6017b59 100644
--- a/definitions.h
+++ b/definitions.h
@@ -9,12 +9,12 @@
__attribute__((nonnull(3,4), returns_nonnull))
def_t *with_def(def_t *defs, size_t namelen, const char *name, pat_t *pat);
-__attribute__((nonnull(2,3,4), returns_nonnull))
-def_t *with_backref(def_t *defs, file_t *f, const char *name, match_t *m);
+__attribute__((nonnull(2,4,5), returns_nonnull))
+def_t *with_backref(def_t *defs, file_t *f, size_t namelen, const char *name, match_t *m);
__attribute__((nonnull(2)))
def_t *load_grammar(def_t *defs, file_t *f);
-__attribute__((pure, nonnull(2)))
-def_t *lookup(def_t *defs, const char *name);
+__attribute__((pure, nonnull(3)))
+def_t *lookup(def_t *defs, size_t namelen, const char *name);
__attribute__((nonnull(1)))
void free_defs(def_t **defs, def_t *stop);
diff --git a/match.c b/match.c
index 8e8f8e0..128e9da 100644
--- a/match.c
+++ b/match.c
@@ -171,8 +171,8 @@ match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, unsigned int
}
case BP_STRING: {
if (&str[pat->len] > f->end) return NULL;
- if (ignorecase ? memicmp(str, pat->args.s, (size_t)pat->len) != 0
- : memcmp(str, pat->args.s, (size_t)pat->len) != 0)
+ if (ignorecase ? memicmp(str, pat->args.string, (size_t)pat->len) != 0
+ : memcmp(str, pat->args.string, (size_t)pat->len) != 0)
return NULL;
match_t *m = new_match();
m->pat = pat;
@@ -347,7 +347,7 @@ match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, unsigned int
{ // Push backrefs and run matching, then cleanup
def_t *defs2 = defs;
if (m1->pat->type == BP_CAPTURE && m1->pat->args.capture.name)
- defs2 = with_backref(defs2, f, m1->pat->args.capture.name, m1);
+ defs2 = with_backref(defs2, f, m1->pat->args.capture.namelen, m1->pat->args.capture.name, m1);
// def_t *defs2 = with_backrefs(defs, f, m1);
m2 = match(defs2, f, m1->end, pat->args.multiple.second, ignorecase);
free_defs(&defs2, defs);
@@ -414,8 +414,8 @@ match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, unsigned int
return m;
}
case BP_REF: {
- def_t *def = lookup(defs, pat->args.s);
- check(def != NULL, "Unknown identifier: '%s'", pat->args.s);
+ def_t *def = lookup(defs, pat->args.name.len, pat->args.name.name);
+ check(def != NULL, "Unknown identifier: '%.*s'", (int)pat->args.name.len, pat->args.name.name);
pat_t *ref = def->pat;
pat_t rec_op = {
@@ -540,7 +540,7 @@ static match_t *get_capture_by_num(match_t *m, int *n)
static match_t *get_capture_by_name(match_t *m, const char *name)
{
if (m->pat->type == BP_CAPTURE && m->pat->args.capture.name
- && streq(m->pat->args.capture.name, name))
+ && strncmp(m->pat->args.capture.name, name, m->pat->args.capture.namelen) == 0)
return m;
for (match_t *c = m->child; c; c = c->nextsibling) {
match_t *cap = get_capture_by_name(c, name);
diff --git a/pattern.c b/pattern.c
index e600848..692deb5 100644
--- a/pattern.c
+++ b/pattern.c
@@ -246,7 +246,7 @@ static pat_t *_bp_simplepattern(file_t *f, const char *str)
pat = new_pat(f, opstart, BP_STRING);
char *s = xcalloc(sizeof(char), 2);
s[0] = c;
- pat->args.s = s;
+ pat->args.string = s;
}
pat->len = 1;
@@ -296,7 +296,7 @@ static pat_t *_bp_simplepattern(file_t *f, const char *str)
esc = new_pat(f, opstart, BP_STRING);
char *s = xcalloc(sizeof(char), 2);
s[0] = (char)e;
- esc->args.s = s;
+ esc->args.string = s;
}
esc->len = 1;
esc->end = str;
@@ -323,7 +323,7 @@ static pat_t *_bp_simplepattern(file_t *f, const char *str)
pat_t *pat = new_pat(f, start, BP_STRING);
pat->len = (ssize_t)len;
- pat->args.s = literal;
+ pat->args.string = literal;
if (!matchchar(&str, endquote))
file_err(f, start, str, "This string doesn't have a closing quote.");
@@ -448,7 +448,8 @@ static pat_t *_bp_simplepattern(file_t *f, const char *str)
pat_t *capture = new_pat(f, start, BP_CAPTURE);
const char *a = *str == '!' ? &str[1] : after_name(str);
if (a > str && after_spaces(a)[0] == '=' && after_spaces(a)[1] != '>') {
- capture->args.capture.name = strndup(str, (size_t)(a-str));
+ capture->args.capture.name = str;
+ capture->args.capture.namelen = (size_t)(a-str);
str = after_spaces(a) + 1;
}
pat_t *captured = bp_simplepattern(f, str);
@@ -461,17 +462,13 @@ static pat_t *_bp_simplepattern(file_t *f, const char *str)
}
// Special rules:
case '_': case '^': case '$': case '|': {
- const char *name = NULL;
- if (matchchar(&str, c)) { // double __, ^^, $$
- if (matchchar(&str, ':')) return NULL; // Don't match definitions
- char tmp[3] = {c, c, '\0'};
- name = strdup(tmp);
- } else {
- if (matchchar(&str, ':')) return NULL; // Don't match definitions
- name = strndup(&c, 1);
- }
+ size_t namelen = 1;
+ if (matchchar(&str, c)) // double __, ^^, $$
+ ++namelen;
+ if (matchchar(&str, ':')) return NULL; // Don't match definitions
pat_t *ref = new_pat(f, start, BP_REF);
- ref->args.s = name;
+ ref->args.name.name = start;
+ ref->args.name.len = namelen;
ref->end = str;
return ref;
}
@@ -484,7 +481,8 @@ static pat_t *_bp_simplepattern(file_t *f, const char *str)
if (matchchar(&str, ':')) // Don't match definitions
return NULL;
pat_t *ref = new_pat(f, start, BP_REF);
- ref->args.s = strndup(refname, (size_t)(str - refname));
+ ref->args.name.name = refname;
+ ref->args.name.len = (size_t)(str - refname);
ref->end = str;
return ref;
}
@@ -537,7 +535,7 @@ pat_t *bp_stringpattern(file_t *f, const char *str)
if (len > 0) {
pat_t *strop = new_pat(f, str, BP_STRING);
strop->len = (ssize_t)len;
- strop->args.s = literal;
+ strop->args.string = literal;
strop->end = str;
ret = chain_together(f, ret, strop);
}
@@ -608,16 +606,8 @@ def_t *bp_definition(def_t *defs, file_t *f, const char *str)
//
void destroy_pat(pat_t *pat)
{
- switch (pat->type) {
- case BP_STRING: case BP_REF:
- xfree(&pat->args.s);
- break;
- case BP_CAPTURE:
- if (pat->args.capture.name)
- xfree(&pat->args.capture.name);
- break;
- default: break;
- }
+ if (pat->type == BP_STRING)
+ xfree(&pat->args.string);
}
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
diff --git a/types.h b/types.h
index 58b65d2..e10c763 100644
--- a/types.h
+++ b/types.h
@@ -41,7 +41,11 @@ typedef struct pat_s {
// Length of the match, if constant, otherwise -1
ssize_t len;
union {
- const char *s;
+ const char *string;
+ struct {
+ const char *name;
+ size_t len;
+ } name;
struct {
unsigned char low, high;
} range;
@@ -60,7 +64,8 @@ typedef struct pat_s {
} replace;
struct {
struct pat_s *capture_pat;
- char *name;
+ const char *name;
+ size_t namelen;
} capture;
struct match_s *backref;
struct {