[augeas-devel] [PATCH 2/3] Use precise ctype of a square lens if it is indeed regular

lutter at redhat.com lutter at redhat.com
Tue Oct 23 23:25:28 UTC 2012


From: David Lutterkort <lutter at redhat.com>

---
 src/get.c  |   48 +++++++++++++++++++++++++++++----------------
 src/lens.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 17 deletions(-)

diff --git a/src/get.c b/src/get.c
index 535c6fe..a7ee565 100644
--- a/src/get.c
+++ b/src/get.c
@@ -862,31 +862,31 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
 
     struct lens *concat = lens->child;
     struct tree *tree = NULL;
-    struct lens *curr;
+    struct re_registers *old_regs = state->regs;
     uint old_nreg = state->nreg;
-    uint nreg = state->nreg;
-    uint nsub, i;
+    uint end = REG_END(state);
+    uint start = REG_START(state);
     char *rsqr = NULL, *lsqr = NULL;
-    uint start, end;
+    int r;
+
+    r = match(state, lens->child, lens->child->ctype, end, start);
+    ERR_NOMEM(r < 0, state->info);
 
     tree = get_lens(lens->child, state);
 
     /* retrieve left component */
-    nreg = old_nreg + 1;
-    start = state->regs->start[nreg];
-    end = state->regs->end[nreg];
+    state->nreg = 1;
+    start = REG_START(state);
+    end = REG_END(state);
     lsqr = token_range(state->text, start, end);
 
     /* retrieve right component */
     /* compute nreg for the last children */
-    nreg = old_nreg + 1;
-    for (i = 0; i < concat->nchildren - 1; i++) {
-        curr = concat->children[i];
-        nsub = regexp_nsub(curr->ctype);
-        nreg += 1 + nsub;
-    }
-    start = state->regs->start[nreg];
-    end = state->regs->end[nreg];
+    for (int i = 0; i < concat->nchildren - 1; i++)
+        state->nreg += 1 + regexp_nsub(concat->children[i]->ctype);
+
+    start = REG_START(state);
+    end = REG_END(state);
     rsqr = token_range(state->text, start, end);
 
     if (!square_match(lens, lsqr, rsqr)) {
@@ -897,7 +897,9 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
     }
 
  done:
+    free_regs(state);
     state->nreg = old_nreg;
+    state->regs = old_regs;
     FREE(lsqr);
     FREE(rsqr);
     return tree;
@@ -911,14 +913,26 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
 static struct skel *parse_square(struct lens *lens, struct state *state,
                                  struct dict **dict) {
     ensure0(lens->tag == L_SQUARE, state->info);
-    struct skel *skel, *sk;
+    struct re_registers *old_regs = state->regs;
+    uint old_nreg = state->nreg;
+    uint end = REG_END(state);
+    uint start = REG_START(state);
+    struct skel *skel = NULL, *sk = NULL;
+    int r;
+
+    r = match(state, lens->child, lens->child->ctype, end, start);
+    ERR_NOMEM(r < 0, state->info);
 
-    skel = parse_concat(lens->child, state, dict);
+    skel = parse_lens(lens->child, state, dict);
     if (skel == NULL)
         return NULL;
     sk = make_skel(lens);
     sk->skels = skel;
 
+ error:
+    free_regs(state);
+    state->regs = old_regs;
+    state->nreg = old_nreg;
     return sk;
 }
 
diff --git a/src/lens.c b/src/lens.c
index 3e99159..58256ed 100644
--- a/src/lens.c
+++ b/src/lens.c
@@ -400,6 +400,66 @@ struct value *lns_make_maybe(struct info *info, struct lens *l, int check) {
     return make_lens_value(lens);
 }
 
+/* The ctype of SQR is a regular approximation of the true ctype of SQR
+ * at this point. In some situations, for example in processing quoted
+ * strings this leads to false typecheck errors; to lower the chances
+ * of these, we try to construct the precise ctype of SQR if the
+ * language of L1 is finite (and has a small number of words)
+ */
+static void square_precise_type(struct info *info,
+                                struct regexp **sqr,
+                                struct regexp *left,
+                                struct regexp *body) {
+
+    char **words = NULL;
+    int nwords = 0, r;
+    struct fa *fa = NULL;
+    struct value *exn = NULL;
+    struct regexp **u = NULL, *c[3], *w = NULL;
+
+    exn = str_to_fa(info, left->pattern->str, &fa, left->nocase);
+    if (exn != NULL)
+        goto error;
+
+    nwords = fa_enumerate(fa, 10, &words); /* The limit of 10 is arbitrary */
+    if (nwords < 0)
+        goto error;
+
+    r = ALLOC_N(u, nwords);
+    ERR_NOMEM(r < 0, info);
+
+    c[1] = body;
+    for (int i=0; i < nwords; i++) {
+        w = make_regexp_literal(left->info, words[i]);
+        ERR_NOMEM(w == NULL, info);
+        w->nocase = left->nocase;
+
+        c[0] = c[2] = w;
+        u[i] = regexp_concat_n(info, 3, c);
+
+        unref(w, regexp);
+        ERR_NOMEM(u[i] == NULL, info);
+    }
+    w = regexp_union_n(info, nwords, u);
+    if (w != NULL) {
+        unref(*sqr, regexp);
+        *sqr = w;
+        w = NULL;
+    }
+
+ error:
+    unref(w, regexp);
+    for (int i=0; i < nwords; i++) {
+        free(words[i]);
+        if (u != NULL)
+            unref(u[i], regexp);
+    }
+    free(words);
+    free(u);
+    fa_free(fa);
+    unref(exn, value);
+}
+
 /* Build a square lens as
  *    left . body . right
  * where left and right accepts the same language and
@@ -433,6 +493,9 @@ struct value * lns_make_square(struct info *info, struct lens *l1,
 
     for (int t=0; t < ntypes; t++)
         ltype(sqr, t) = ref(ltype(cnt2->lens, t));
+
+    square_precise_type(info, &(sqr->ctype), l1->ctype, l2->ctype);
+
     sqr->recursive = cnt2->lens->recursive;
     sqr->rec_internal = cnt2->lens->rec_internal;
     sqr->consumes_value = cnt2->lens->consumes_value;
-- 
1.7.7.6




More information about the augeas-devel mailing list