[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, &regs);
-    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, &regs);
-    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