[augeas-devel] augeas: master - Better error mesages when re match fails during get/put
David Lutterkort
lutter at fedoraproject.org
Wed Feb 11 21:43:26 UTC 2009
Gitweb: http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=353c861bfc952cc6fcf1410b2cc9555d798b4d5b
Commit: 353c861bfc952cc6fcf1410b2cc9555d798b4d5b
Parent: e41c183e688015b423ee804b9c9c113f1b1767ff
Author: David Lutterkort <lutter at redhat.com>
AuthorDate: Wed Feb 11 13:37:13 2009 -0800
Committer: David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Feb 11 13:37:13 2009 -0800
Better error mesages when re match fails during get/put
---
src/get.c | 67 ++++++++++++++++++++++++++++++++++++---------------------
src/put.c | 60 ++++++++++++++++++++++++++++++++++-----------------
src/regexp.c | 20 +++++++++++++++++
src/syntax.h | 3 ++
4 files changed, 105 insertions(+), 45 deletions(-)
diff --git a/src/get.c b/src/get.c
index b87241b..e54bf38 100644
--- a/src/get.c
+++ b/src/get.c
@@ -222,6 +222,25 @@ static struct split *set_split(struct state *state, struct split *split) {
return split;
}
+static void regexp_match_error(struct state *state, struct lens *lens,
+ int count, struct split *split,
+ struct regexp *r) {
+ char *text = strndup(split->start, split->size);
+ char *pat = regexp_escape(r);
+
+ if (count == -1) {
+ get_error(state, lens, "Failed to match /%s/ with %s", pat, text);
+ } else if (count == -2) {
+ get_error(state, lens, "Internal error matching /%s/ with %s",
+ pat, text);
+ } else if (count == -3) {
+ /* Should have been caught by the typechecker */
+ get_error(state, lens, "Syntax error in regexp /%s/", pat);
+ }
+ free(pat);
+ free(text);
+}
+
/* Refine a tree split OUTER according to the L_CONCAT lens LENS */
static struct split *split_concat(struct state *state, struct lens *lens) {
assert(lens->tag == L_CONCAT);
@@ -235,14 +254,8 @@ static struct split *split_concat(struct state *state, struct lens *lens) {
if (ctype->re != NULL)
ctype->re->regs_allocated = REGS_UNALLOCATED;
count = regexp_match(ctype, outer->start, outer->size, 0, ®s);
- if (count == -2) {
- FIXME("Match failed - produce better error");
- abort();
- } else if (count == -1) {
- char *text = strndup(outer->start, outer->size);
- get_error(state, lens,
- "Failed to match /%s/ with %s", ctype->pattern->str, text);
- free(text);
+ if (count < 0) {
+ regexp_match_error(state, lens, count, outer, ctype);
return NULL;
}
@@ -267,10 +280,11 @@ static struct split *split_concat(struct state *state, struct lens *lens) {
goto done;
}
-static struct split *split_iter(struct lens *lens, struct split *outer) {
+static struct split *split_iter(struct state *state, struct lens *lens) {
assert(lens->tag == L_STAR);
int count = 0;
+ struct split *outer = state->split;
struct split *split = NULL;
struct regexp *ctype = lens->child->ctype;
@@ -278,11 +292,11 @@ static struct split *split_iter(struct lens *lens, struct split *outer) {
struct split *tail = NULL;
while (pos < outer->size) {
count = regexp_match(ctype, outer->start, outer->size, pos, NULL);
- if (count == -2) {
- FIXME("Match failed - produce better error");
- abort();
- } else if (count == -1) {
+ if (count == -1) {
break;
+ } else if (count < -1) {
+ regexp_match_error(state, lens, count, outer, ctype);
+ goto error;
}
tail = split_append(&split, tail, outer->start, pos, pos + count);
if (tail == NULL)
@@ -295,12 +309,15 @@ static struct split *split_iter(struct lens *lens, struct split *outer) {
return NULL;
}
-static int applies(struct lens *lens, struct split *split) {
+static int applies(struct state *state, struct lens *lens) {
+ struct split *split = state->split;
int count;
count = regexp_match(lens->ctype, split->start, split->size, 0, NULL);
- if (count == -2) {
- FIXME("Match failed - produce better error");
- abort();
+ if (count == -1)
+ return 0;
+ else if (count < -1) {
+ regexp_match_error(state, lens, count, split, lens->ctype);
+ return 0;
}
return (count == split->size);
}
@@ -425,7 +442,7 @@ static struct tree *get_union(struct lens *lens, struct state *state) {
for (int i=0; i < lens->nchildren; i++) {
struct lens *l = lens->children[i];
- if (applies(l, state->split)) {
+ if (applies(state, l)) {
tree = get_lens(l, state);
applied = 1;
break;
@@ -444,7 +461,7 @@ static struct skel *parse_union(struct lens *lens, struct state *state,
for (int i=0; i < lens->nchildren; i++) {
struct lens *l = lens->children[i];
- if (applies(l, state->split)) {
+ if (applies(state, l)) {
skel = parse_lens(l, state, dict);
applied = 1;
break;
@@ -517,7 +534,7 @@ static struct tree *get_quant_star(struct lens *lens, struct state *state) {
assert(lens->tag == L_STAR);
struct tree *tree = NULL, *tail = NULL;
struct split *oldsplit = state->split;
- struct split *split = split_iter(lens, state->split);
+ struct split *split = split_iter(state, lens);
set_split(state, split);
while (state->split != NULL) {
@@ -538,7 +555,7 @@ static struct skel *parse_quant_star(struct lens *lens, struct state *state,
struct dict **dict) {
assert(lens->tag == L_STAR);
struct split *oldsplit = state->split;
- struct split *split = split_iter(lens, state->split);
+ struct split *split = split_iter(state, lens);
struct skel *skel = make_skel(lens), *tail = NULL;
*dict = NULL;
@@ -563,7 +580,7 @@ static struct tree *get_quant_maybe(struct lens *lens, struct state *state) {
assert(lens->tag == L_MAYBE);
struct tree *tree = NULL;
- if (applies(lens->child, state->split)) {
+ if (applies(state, lens->child)) {
tree = get_lens(lens->child, state);
}
return tree;
@@ -574,7 +591,7 @@ static struct skel *parse_quant_maybe(struct lens *lens, struct state *state,
assert(lens->tag == L_MAYBE);
struct skel *skel = NULL;
- if (applies(lens->child, state->split)) {
+ if (applies(state, lens->child)) {
skel = parse_lens(lens->child, state, dict);
}
if (skel == NULL)
@@ -681,7 +698,7 @@ struct tree *lns_get(struct info *info, struct lens *lens, const char *text,
* try to process, hoping we'll get a more specific error, and if that
* fails, we throw our arms in the air and say 'something went wrong'
*/
- partial = !applies(lens, &split);
+ partial = !applies(&state, lens);
tree = get_lens(lens, &state);
@@ -773,7 +790,7 @@ struct skel *lns_parse(struct lens *lens, const char *text, struct dict **dict,
state.text = text;
state.pos = text;
- if (applies(lens, &split)) {
+ if (applies(&state, lens)) {
*dict = NULL;
skel = parse_lens(lens, &state, dict);
diff --git a/src/put.c b/src/put.c
index 615e5c9..aff370b 100644
--- a/src/put.c
+++ b/src/put.c
@@ -106,6 +106,26 @@ static void put_error(struct state *state, struct lens *lens,
state->error->message = NULL;
}
+static void regexp_match_error(struct state *state, struct lens *lens,
+ int count, struct split *split,
+ struct regexp *r) {
+ char *text = strndup(split->labels + split->start,
+ split->end - split->start);
+ char *pat = regexp_escape(r);
+
+ if (count == -1) {
+ put_error(state, lens, "Failed to match /%s/ with %s", pat, text);
+ } else if (count == -2) {
+ put_error(state, lens, "Internal error matching /%s/ with %s",
+ pat, text);
+ } else if (count == -3) {
+ /* Should have been caught by the typechecker */
+ put_error(state, lens, "Syntax error in regexp /%s/", pat);
+ }
+ free(pat);
+ free(text);
+}
+
static struct split *make_split(struct tree *tree) {
struct split *split;
CALLOC(split, 1);
@@ -191,16 +211,10 @@ static struct split *split_concat(struct state *state, struct lens *lens) {
atype->re->regs_allocated = REGS_UNALLOCATED;
count = regexp_match(atype, outer->labels, outer->end,
outer->start, ®s);
- if (count == -2) {
- FIXME("Match failed - produce better error");
- abort();
- } else if (count == -1 || count != outer->end - outer->start) {
- char *labels = strndup(outer->labels + outer->start,
- outer->end - outer->start);
- put_error(state, lens,
- "Failed to match /%s/ with %s",
- atype->pattern->str, labels);
- free(labels);
+ if (count >= 0 && count != outer->end - outer->start)
+ count = -1;
+ if (count < 0) {
+ regexp_match_error(state, lens, count, outer, atype);
return NULL;
}
@@ -225,10 +239,11 @@ static struct split *split_concat(struct state *state, struct lens *lens) {
return split;
}
-static struct split *split_iter(struct lens *lens, struct split *outer) {
+static struct split *split_iter(struct state *state, struct lens *lens) {
assert(lens->tag == L_STAR);
int count = 0;
+ struct split *outer = state->split;
struct split *split = NULL;
struct regexp *atype = lens->child->atype;
@@ -237,12 +252,13 @@ static struct split *split_iter(struct lens *lens, struct split *outer) {
struct split *tail = NULL;
while (pos < outer->end) {
count = regexp_match(atype, outer->labels, outer->end, pos, NULL);
- if (count == -2) {
- FIXME("Match failed - produce better error");
- abort();
- } else if (count == -1) {
+ if (count == -1) {
break;
+ } else if (count < -1) {
+ regexp_match_error(state, lens, count, outer, atype);
+ goto error;
}
+
struct tree *follow = cur;
for (int j = pos; j < pos + count; j++) {
if (outer->labels[j] == '/')
@@ -254,6 +270,9 @@ static struct split *split_iter(struct lens *lens, struct split *outer) {
pos += count;
}
return split;
+ error:
+ free_split(split);
+ return NULL;
}
/* Check if LENS applies to the current split in STATE */
@@ -263,10 +282,11 @@ static int applies(struct lens *lens, struct state *state) {
count = regexp_match(lens->atype, split->labels, split->end,
split->start, NULL);
- if (count == -2) {
- FIXME("Match failed - produce better error");
- abort();
+ if (count < -1) {
+ regexp_match_error(state, lens, count, split, lens->atype);
+ return 0;
}
+
if (count != split->end - split->start)
return 0;
if (count == 0 && lens->value)
@@ -475,7 +495,7 @@ static void put_quant_star(struct lens *lens, struct state *state) {
struct split *oldsplit = state->split;
struct skel *oldskel = state->skel;
- struct split *split = split_iter(lens, state->split);
+ struct split *split = split_iter(state, lens);
state->skel = state->skel->skels;
set_split(state, split);
@@ -614,7 +634,7 @@ static void create_quant_star(struct lens *lens, struct state *state) {
assert(lens->tag == L_STAR);
struct split *oldsplit = state->split;
- struct split *split = split_iter(lens, state->split);
+ struct split *split = split_iter(state, lens);
set_split(state, split);
while (state->split != NULL) {
diff --git a/src/regexp.c b/src/regexp.c
index 9a96b55..797d0e6 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -31,6 +31,26 @@ static const struct string empty_pattern_string = {
static const struct string *const empty_pattern = &empty_pattern_string;
+char *regexp_escape(struct regexp *r) {
+ char *pat = escape(r->pattern->str, -1);
+
+ if (pat == NULL)
+ return NULL;
+
+ /* Remove unneeded '()' from pat */
+ for (int changed = 1; changed;) {
+ changed = 0;
+ for (char *p = pat; *p != '\0'; p++) {
+ if (*p == '(' && p[1] == ')') {
+ memmove(p, p+2, strlen(p+2)+1);
+ changed = 1;
+ }
+ }
+ }
+
+ return pat;
+}
+
void print_regexp(FILE *out, struct regexp *r) {
if (r == NULL) {
fprintf(out, "<NULL>");
diff --git a/src/syntax.h b/src/syntax.h
index d7a53fc..208c4db 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -210,6 +210,9 @@ struct regexp *regexp_make_empty(struct info *);
regular expressions */
void regexp_release(struct regexp *regexp);
+/* Produce a printable representation of R */
+char *regexp_escape(struct regexp *r);
+
struct native {
unsigned int argc;
struct type *type;
More information about the augeas-devel
mailing list