[augeas-devel] augeas: master - Make fa_example work for strings with embedded NUL's

David Lutterkort lutter at fedoraproject.org
Thu Sep 3 18:17:48 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=7a880ff6e588206b64b72d6e46d9a62a3776313e
Commit:        7a880ff6e588206b64b72d6e46d9a62a3776313e
Parent:        a7c918ad3e923ec3b549dd5cc5bd69073f218063
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Wed Sep 2 15:14:35 2009 -0700
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Sep 2 15:14:35 2009 -0700

Make fa_example work for strings with embedded NUL's

---
 src/fa.c       |  111 +++++++++++++++++++++++++++++++++++++-------------------
 tests/fatest.c |    2 +
 2 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/src/fa.c b/src/fa.c
index 062c4b3..e5442c0 100644
--- a/src/fa.c
+++ b/src/fa.c
@@ -327,6 +327,43 @@ static void print_re(struct re *re) {
 }
 
 /*
+ * struct re_str
+ */
+static void release_re_str(struct re_str *str) {
+    if (str == NULL)
+        return;
+    FREE(str->rx);
+    str->len = 0;
+}
+
+static void free_re_str(struct re_str *str) {
+    if (str == NULL)
+        return;
+    release_re_str(str);
+    FREE(str);
+}
+
+static struct re_str *make_re_str(const char *s) {
+    struct re_str *str;
+
+    if (ALLOC(str) < 0)
+        return NULL;
+    if (s != NULL) {
+        str->rx = strdup(s);
+        str->len = strlen(s);
+        if (str->rx == NULL) {
+            FREE(str);
+            return NULL;
+        }
+    }
+    return str;
+}
+
+static int re_str_alloc(struct re_str *str) {
+    return ALLOC_N(str->rx, str->len + 1);
+}
+
+/*
  * Memory management
  */
 
@@ -2169,15 +2206,17 @@ static unsigned int chr_score(char c) {
         return 3;
     } else if (isprint(c)) {
         return 7;
+    } else if (c == '\0') {
+        return 10000;
     } else {
         return 100;
     }
 }
 
-static unsigned int str_score(const char *s) {
+static unsigned int str_score(const struct re_str *str) {
     unsigned int score = 0;
-    for ( ;*s; s++) {
-        score += chr_score(*s);
+    for (int i=0; i < str->len; i++) {
+        score += chr_score(str->rx[i]);
     }
     return score;
 }
@@ -2185,18 +2224,23 @@ static unsigned int str_score(const char *s) {
 /* See if we get a better string for DST by appending C to SRC. If DST is
  * NULL or empty, always use SRC + C
  */
-static char *string_extend(char *dst, const char *src, char c) {
+static struct re_str *string_extend(struct re_str *dst,
+                                    const struct re_str *src,
+                                    char c) {
     if (dst == NULL
-        || *dst == '\0'
+        || dst->len == 0
         || str_score(src) + chr_score(c) < str_score(dst)) {
-        int slen = strlen(src);
-        char *new_dst = realloc(dst, slen + 2);
-        if (new_dst) {
-            dst = new_dst;
-            strncpy(dst, src, slen);
-            dst[slen] = c;
-            dst[slen + 1] = '\0';
-        }
+        int slen = src->len;
+        if (dst == NULL)
+            dst = make_re_str(NULL);
+        if (dst == NULL)
+            return NULL;
+        if (REALLOC_N(dst->rx, slen+2) < 0)
+            return NULL;
+        memcpy(dst->rx, src->rx, slen);
+        dst->rx[slen] = c;
+        dst->rx[slen + 1] = '\0';
+        dst->len = slen + 1;
     }
     return dst;
 }
@@ -2223,7 +2267,8 @@ int fa_example(struct fa *fa, char **example, size_t *example_len) {
 
     /* Map from state to string */
     struct state_set *path = state_set_init(-1, S_DATA|S_SORTED);
-    state_set_push_data(path, fa->initial,(void*) strdup(""));
+    struct re_str *str = make_re_str("");
+    state_set_push_data(path, fa->initial, str);
 
     /* List of states still to visit */
     struct state_set *worklist = state_set_init(-1, S_NONE);
@@ -2231,39 +2276,40 @@ int fa_example(struct fa *fa, char **example, size_t *example_len) {
 
     while (worklist->used) {
         struct state *s = state_set_pop(worklist);
-        char *ps = state_set_find_data(path, s);
+        struct re_str *ps = state_set_find_data(path, s);
         for_each_trans(t, s) {
             char c = pick_char(t);
             int toind = state_set_index(path, t->to);
             if (toind == -1) {
-                char *w = string_extend(NULL, ps, c);
+                struct re_str *w = string_extend(NULL, ps, c);
                 state_set_push(worklist, t->to);
-                state_set_push_data(path, t->to, (void *) w);
+                state_set_push_data(path, t->to, w);
             } else {
                 path->data[toind] = string_extend(path->data[toind], ps, c);
             }
         }
     }
 
-    char *word = NULL;
+    struct re_str *word = NULL;
     for (int i=0; i < path->used; i++) {
         struct state *p = path->states[i];
-        char *ps = path->data[i];
+        struct re_str *ps = path->data[i];
         if (p->accept &&
-            (word == NULL || *word == '\0'
-             || (*ps != '\0' && str_score(word) > str_score(ps)))) {
-            free(word);
+            (word == NULL || word->len == 0
+             || (ps->len > 0 && str_score(word) > str_score(ps)))) {
+            free_re_str(word);
             word = ps;
         } else {
-            free(ps);
+            free_re_str(ps);
         }
     }
     state_set_free(path);
     state_set_free(worklist);
-    /* FIXME: handle embedded nul's */
-    if (word != NULL)
-        *example_len = strlen(word);
-    *example = word;
+    if (word != NULL) {
+        *example_len = word->len;
+        *example = word->rx;
+        free(word);
+    }
     return 0;
 }
 
@@ -2871,17 +2917,6 @@ static struct re *parse_regexp(struct re_parse *parse) {
  */
 static int re_as_string(const struct re *re, struct re_str *str);
 
-static void release_re_str(struct re_str *str) {
-    if (str == NULL)
-        return;
-    FREE(str->rx);
-    str->len = 0;
-}
-
-static int re_str_alloc(struct re_str *str) {
-    return ALLOC_N(str->rx, str->len + 1);
-}
-
 static int re_binop_count(enum re_type type, const struct re *re) {
     assert(type == CONCAT || type == UNION);
     if (re->type == type) {
diff --git a/tests/fatest.c b/tests/fatest.c
index 81b01be..fe2dfa7 100644
--- a/tests/fatest.c
+++ b/tests/fatest.c
@@ -338,6 +338,8 @@ static void testExample(CuTest *tc) {
     assertExample(tc, "\001((\002.)*\001)+\002", "\001\001\002");
     assertExample(tc, "\001((\001.)*\002)+\002", "\001\002\002");
 
+    assertExample(tc, "a[^\001-\004]+b", "aAb");
+
     struct fa *fa1 = mark(fa_make_basic(FA_EMPTY));
     size_t xmpl_len;
     char *xmpl;




More information about the augeas-devel mailing list