[augeas-devel] [PATCH] Basic support for case insensitive square lens

Francis Giraldeau francis.giraldeau at gmail.com
Wed Feb 9 04:15:08 UTC 2011


Square lens must match open and close tag. In some situations, for instance
httpd, open and close tags case is allowed to be different. If the square
regexp is case insensitive, we allow case mismatch between open and close tag.
The default case for the close tag is the one from the key in the create
function, and in the put function, the original case is preserved.

As test case shows, some serious errors occurs when the lens regexp is set to
nocase. Here is the error message while running pass_square.aug:

lt-augparse: put.c:236: split_concat: Assertion `regs.start[reg] != -1' failed.
---
 src/get.c                     |   55 +++++++++++++++++++++++++++++++++++++---
 src/put.c                     |    7 +----
 src/regexp.c                  |    3 +-
 tests/modules/pass_square.aug |   36 ++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/src/get.c b/src/get.c
index dbab6fa..49f7b78 100644
--- a/src/get.c
+++ b/src/get.c
@@ -313,6 +313,37 @@ static int match(struct state *state, struct lens *lens,
     return count;
 }
 
+/* compare two strings in a case insensitive manner
+ * returns 0 if string matches, -1 otherwise
+ */
+static int strcmp_nocase(char *s1, char *s2) {
+    char *s1_re;
+    int count, s2_len;
+    int result = -1;
+
+    s2_len = strlen(s2);
+    s1_re = strdup(s1);
+    if (s1_re == NULL)
+        goto error_dup;
+
+    struct regexp *re = make_regexp(NULL, s1_re, true);
+    if (re == NULL)
+        goto error_re;
+
+    count = regexp_match(re, s2, s2_len, 0, NULL);
+
+    if (count == s2_len)
+        result = 0;
+
+    unref(re, regexp);
+    return result;
+
+ error_re:
+   FREE(s1_re);
+ error_dup:
+    return result;
+}
+
 static void free_regs(struct state *state) {
     if (state->regs != NULL) {
         free(state->regs->start);
@@ -692,6 +723,7 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
 
     struct tree *tree = NULL;
     char *key = NULL, *square = NULL;
+    int res;
 
     // get the child lens
     tree = get_concat(lens->child, state);
@@ -701,7 +733,13 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
     ensure0(key != NULL, state->info);
     ensure0(square != NULL, state->info);
 
-    if (strcmp(key, square) != 0) {
+    if (lens->ktype->nocase) {
+        res = strcmp_nocase(key, square);
+    } else {
+        res = strcmp(key, square);
+    }
+
+    if (res != 0) {
         get_error(state, lens, "%s \"%s\" %s \"%s\"",
                 "Parse error: mismatched key in square lens, expecting", key,
                 "but got", square);
@@ -1008,6 +1046,7 @@ static void visit_exit(struct lens *lens,
     } else if (lens->tag == L_SQUARE) {
         if (rec_state->mode == M_GET) {
             char *key, *square;
+            int res;
 
             key = top_frame(rec_state)->key;
             square = top_frame(rec_state)->square;
@@ -1015,15 +1054,21 @@ static void visit_exit(struct lens *lens,
             ensure(key != NULL, state->info);
             ensure(square != NULL, state->info);
 
-            // raise syntax error if they are not equals
-            if (strcmp(key, square) != 0){
+            if (lens->ktype->nocase) {
+                res = strcmp_nocase(key, square);
+            } else {
+                res = strcmp(key, square);
+            }
+
+            if (res != 0) {
                 get_error(state, lens, "%s \"%s\" %s \"%s\"",
-                                "Parse error: mismatched key in square lens, expecting", key,
-                                "but got", square);
+                        "Parse error: mismatched key in square lens, expecting", key,
+                        "but got", square);
                 state->error->pos = end - strlen(square);
                 goto error;
             }
 
+            FREE(square);
             get_combine(rec_state, lens, 1);
         } else {
             parse_combine(rec_state, lens, 1);
diff --git a/src/put.c b/src/put.c
index 32618c4..66030bb 100644
--- a/src/put.c
+++ b/src/put.c
@@ -468,12 +468,7 @@ static void put_del(ATTRIBUTE_UNUSED struct lens *lens, struct state *state) {
     assert(lens->tag == L_DEL);
     assert(state->skel != NULL);
     assert(state->skel->tag == L_DEL);
-    if (lens->string != NULL) {
     fprintf(state->out, "%s", state->skel->text);
-    } else {
-    /* L_DEL with NULL string: replicate the current key */
-        fprintf(state->out, "%s", state->key);
-    }
 }
 
 static void put_union(struct lens *lens, struct state *state) {
@@ -662,7 +657,7 @@ static void create_subtree(struct lens *lens, struct state *state) {
 static void create_del(struct lens *lens, struct state *state) {
     assert(lens->tag == L_DEL);
     if (lens->string != NULL) {
-    print_escaped_chars(state->out, lens->string->str);
+        print_escaped_chars(state->out, lens->string->str);
     } else {
         /* L_DEL with NULL string: replicate the current key */
         print_escaped_chars(state->out, state->key);
diff --git a/src/regexp.c b/src/regexp.c
index 14020af..ca9f7a5 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -117,7 +117,8 @@ struct regexp *make_regexp(struct info *info, char *pat, int nocase) {
     struct regexp *regexp;
 
     make_ref(regexp);
-    regexp->info = ref(info);
+    if (info != NULL)
+        regexp->info = ref(info);
 
     make_ref(regexp->pattern);
     regexp->pattern->str = pat;
diff --git a/tests/modules/pass_square.aug b/tests/modules/pass_square.aug
index 0185031..ace80ac 100644
--- a/tests/modules/pass_square.aug
+++ b/tests/modules/pass_square.aug
@@ -112,3 +112,39 @@ test sqr3 put input3 after clear "/x[1]" = input3
 let b4 = del "x" "x"
 let rec sqr4 = [ del /[a]+/ "a" . square /[b]|[c]/ (b4|sqr4) ]
 test sqr4 put "aabaaacxcb" after rm "x" = "aabaaacxcb"
+
+(* test case insensitive match *)
+let b5 = del "x" "x"
+let sqr5 = [ square /[a]+/i b5 . b5 ]*
+test sqr5 put "axaxAxAxaxAxAxax" after rm "/x" = "axaxAxAxaxAxAxax"
+test sqr5 put "" after clear "/A" = "AxAx"
+test sqr5 put "" after clear "/a" = "axax"
+
+(* Basic element *)
+let xml_element_i (body:lens) =
+    let g = del ">" ">" . body . del "</" "</" in
+        [ del "<" "<" . square /[a-z]+/i g . del ">" ">" ] *
+
+let rec xml_rec_i = xml_element_i xml_rec_i
+let doc_i = "<a><B><c><D><e></E></d></c></b></A>"
+test xml_rec_i get doc_i =
+  { "a"
+    { "B"
+      { "c"
+        { "D"
+          { "e" }
+        }
+      }
+    }
+  }
+
+test xml_rec_i put doc_i after rm "x" = ?
+
+let rec rec_i = [ key /[a]/i . rec_i ]?
+test rec_i get "aA" = ?
+
+(* test case sensitive: error raised *)
+let b7 = del "x" "x"
+let sqr7 = [ square /[a]+/ b5 . b5 ]*
+test sqr7 get "axA" = *
+
-- 
1.7.1




More information about the augeas-devel mailing list