[augeas-devel] [PATCH] Fix a major bug in the get implementation of lenses

David Lutterkort dlutter at redhat.com
Fri May 23 01:58:23 UTC 2008


7 files changed, 232 insertions(+), 193 deletions(-)
lenses/tests/test_hosts.aug         |    6 
src/augparse.c                      |   25 --
src/builtin.c                       |    2 
src/get.c                           |  372 ++++++++++++++++++++---------------
src/lens.h                          |   10 
src/transform.c                     |    2 
tests/modules/pass_prefix_union.aug |    8 


# HG changeset patch
# User David Lutterkort <dlutter at redhat.com>
# Date 1211507846 25200
# Node ID bbaa761fac76c9a9548b710cee1bdadbdb72b596
# Parent  38c46290bfc585f8ff5628d8f299d788031d83fb
Fix a major bug in the get implementation of lenses

We used to process the input from left to right, matching the regular
expressions of lenses with the input successively. That is very wrong, in
particular, it leads to lens union choosing the wrong branch: in the union
l1|l2, union would always choose l1 if l1 matched a prefix of l2.

We now process the input in a top-down fashion, splitting the string into
parts as we descend in the tree of lenses. As evidenced by the test
pass_prefix_union, that fixes the bad behavior.

Incidentally, it also uncovered another bug in the test_hosts.aug, where a
test passed, even though the string we were using did not end with the
newline that is mandatory for Hosts.record.

This change also does away with pasing flags and a FILE* for logging
details about hte parse process; they don't really make sense anymore, nor
is that behavior very useful in a library.

diff -r 38c46290bfc5 -r bbaa761fac76 lenses/tests/test_hosts.aug
--- a/lenses/tests/test_hosts.aug	Thu May 22 13:18:50 2008 -0700
+++ b/lenses/tests/test_hosts.aug	Thu May 22 18:57:26 2008 -0700
@@ -7,7 +7,7 @@ 192.168.0.1 pigiron.example.com pigiron 
 192.168.0.1 pigiron.example.com pigiron pigiron.example
 "
 
-  test Hosts.record get "127.0.0.1 foo" =
+  test Hosts.record get "127.0.0.1 foo\n" =
     { "1" { "ipaddr" = "127.0.0.1" }
           { "canonical" = "foo" } }
 
@@ -22,9 +22,9 @@ 192.168.0.1 pigiron.example.com pigiron 
           { "alias" = "pigiron" }
           { "alias" = "pigiron.example" }  }
 
-  test Hosts.record put "127.0.0.1 foo" after
+  test Hosts.record put "127.0.0.1 foo\n" after
       set "1/canonical" "bar"
-  = "127.0.0.1 bar"
+  = "127.0.0.1 bar\n"
 
   test Hosts.lns put two_entries after
     set "2/alias[10]" "piggy" ;
diff -r 38c46290bfc5 -r bbaa761fac76 src/augparse.c
--- a/src/augparse.c	Thu May 22 13:18:50 2008 -0700
+++ b/src/augparse.c	Thu May 22 18:57:26 2008 -0700
@@ -31,42 +31,23 @@ const char *progname;
 
 __attribute__((noreturn))
 static void usage(void) {
-    fprintf(stderr, "Usage: %s [OPTIONS] GRAMMAR [FILE]\n", progname);
-    fprintf(stderr, "Load GRAMMAR and parse FILE according to it.\n");
-    fprintf(stderr, "If FILE is omitted, the GRAMMAR is read and printed\n");
+    fprintf(stderr, "Usage: %s [OPTIONS] MODULE\n", progname);
+    fprintf(stderr, "Evaluate MODULE. Generally, MODULE should contain unit tests.\n");
     fprintf(stderr, "\nOptions:\n\n");
-    fprintf(stderr, "  -P WHAT       Show details of how FILE is parsed. Possible values for WHAT\n"
-                    "                are 'advance', 'match', 'tokens', and 'skel'\n");
     fprintf(stderr, "  -I DIR        Add DIR to the module loadpath. Can be given multiple times.\n");
     exit(EXIT_FAILURE);
 }
 
 int main(int argc, char **argv) {
     int opt;
-    int print_skels = 0;
-    int parse_flags = PF_NONE;
     struct augeas *aug;
     char *loadpath = NULL;
     size_t loadpathlen = 0;
 
     progname = argv[0];
 
-    while ((opt = getopt(argc, argv, "hP:I:")) != -1) {
+    while ((opt = getopt(argc, argv, "hI:")) != -1) {
         switch(opt) {
-        case 'P':
-            if (STREQ(optarg, "advance"))
-                parse_flags |= PF_ADVANCE;
-            else if (STREQ(optarg, "match"))
-                parse_flags |= PF_MATCH;
-            else if (STREQ(optarg, "tokens"))
-                parse_flags |= PF_TOKEN;
-            else if (STREQ(optarg, "skel"))
-                print_skels = 1;
-            else {
-                fprintf(stderr, "Illegal argument '%s' for -%c\n", optarg, opt);
-                usage();
-            }
-            break;
         case 'I':
             argz_add(&loadpath, &loadpathlen, optarg);
             break;
diff -r 38c46290bfc5 -r bbaa761fac76 src/builtin.c
--- a/src/builtin.c	Thu May 22 13:18:50 2008 -0700
+++ b/src/builtin.c	Thu May 22 18:57:26 2008 -0700
@@ -112,7 +112,7 @@ static struct value *lens_get(struct inf
     struct value *v;
     const char *text = str->string->str;
 
-    struct tree *tree = lns_get(info, l->lens, text, NULL, 0, &err);
+    struct tree *tree = lns_get(info, l->lens, text, &err);
     if (err == NULL) {
         v = make_value(V_TREE, ref(info));
         v->tree = tree;
diff -r 38c46290bfc5 -r bbaa761fac76 src/get.c
--- a/src/get.c	Thu May 22 13:18:50 2008 -0700
+++ b/src/get.c	Thu May 22 18:57:26 2008 -0700
@@ -26,9 +26,19 @@
 #include "syntax.h"
 #include "list.h"
 #include "internal.h"
+#include "memory.h"
 
 #define assert_error(state, format, args ...) \
     assert_error_at(__FILE__, __LINE__, &(state->info), format, ## args)
+
+/* A substring in the overall string we are matching. A lens is supposed
+   to process the whole string from start[0] ... start[size]
+*/
+struct split {
+    struct split *next;
+    const char   *start;    /* The start of the text to process */
+    int           size;
+};
 
 struct seq {
     struct seq *next;
@@ -38,11 +48,8 @@ struct seq {
 
 struct state {
     struct info       info;
+    struct split     *split;
     const char       *text;
-    const char       *pos;
-    int               applied;
-    int               flags;     /* set of parse_flags */
-    FILE             *log;
     struct seq       *seqs;
     const char       *key;
     const char       *value;     /* GET_STORE leaves a value here */
@@ -72,7 +79,7 @@ static void get_error(struct state *stat
         return;
     CALLOC(state->error, 1);
     state->error->lens = ref(lens);
-    state->error->pos  = state->pos - state->text;
+    state->error->pos  = state->split->start - state->text;
     va_start(ap, format);
     r = vasprintf(&state->error->message, format, ap);
     va_end(ap);
@@ -239,7 +246,7 @@ static void get_expected_error(struct st
     char *word, *p, *pat;
 
     word = alloca(11);
-    strncpy(word, state->pos, 10);
+    strncpy(word, state->split->start, 10);
     word[10] = '\0';
     for (p = word; *p != '\0' && *p != '\n'; p++);
     *p = '\0';
@@ -250,67 +257,104 @@ static void get_expected_error(struct st
 }
 
 /*
- * Parsing/construction of the AST
+ * Splitting of the input text
  */
-static void advance(struct state *state, int cnt) {
-    if (cnt == 0)
-        return;
 
-    for (int i=0; i<cnt; i++) {
-        assert(state->pos[i] != '\0');
-        if (state->pos[i] == '\n')
-            state->info.first_line++;
-        state->info.last_line = state->info.first_line;
-    }
-    state->pos += cnt;
-    if (state->flags & PF_ADVANCE) {
-        fprintf(state->log, "A %3d ", cnt);
-        print_pos(state->log, state->text, state->pos - state->text);
+static char *token_from_split(struct split *split) {
+    return strndup(split->start, split->size);
+}
+
+static void split_append(struct split **split,
+                         const char *text, int start, int end) {
+    struct split *sp;
+    if (ALLOC(sp) >= 0) {
+        sp->start = text + start;
+        sp->size = end - start;
+        list_append(*split, sp);
     }
 }
 
-static int lex(struct lens *lens, struct regexp *regexp, struct state *state) {
-    int count;
-    int offset = state->pos - state->text;
-    count = regexp_match(regexp, state->text, strlen(state->text),
-                         offset, NULL);
-    if (state->flags & PF_MATCH) {
-        fprintf(state->log, "M %d ", offset);
-        print_regexp(state->log, regexp);
-        fprintf(state->log, " %d..%d\n", offset, offset+count);
+/* 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);
+
+    int count = 0;
+    struct split *outer = state->split;
+    struct re_registers regs;
+    struct split *split = NULL;
+    struct regexp *ctype = lens->ctype;
+
+    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);
+        return NULL;
     }
 
-    if (count == -2) {
-        get_error(state, lens, "Match failed for /%s/ at %d",
-                  regexp->pattern->str, offset);
-        return -1;
-    } else if (count == -1) {
-        return 0;
-    } else {
-        return count;
+    int reg = 1;
+    for (int i=0; i < lens->nchildren; i++) {
+        assert(reg < regs.num_regs);
+        assert(regs.start[reg] != -1);
+        split_append(&split, outer->start, regs.start[reg], regs.end[reg]);
+        reg += 1 + regexp_nsub(lens->children[i]->ctype);
     }
+    assert(reg < regs.num_regs);
+    free(regs.start);
+    free(regs.end);
+    return split;
 }
 
-static int match(struct lens *lens, struct state *state,
-                 const char **token) {
-    assert(lens->tag == L_DEL || lens->tag == L_STORE || lens->tag == L_KEY);
+static struct split *split_iter(struct lens *lens, struct split *outer) {
+    assert(lens->tag == L_STAR);
 
-    int len = lex(lens, lens->regexp, state);
-    if (len < 0)
-        return -1;
-    if (token != NULL)
-        *token = strndup(state->pos, len);
+    int count = 0;
+    struct re_registers regs;
+    struct split *split = NULL;
+    struct regexp *ctype = lens->child->ctype;
 
-    if ((state->log != NULL) && (state->flags & PF_TOKEN)) {
-        fprintf(state->log, "T ");
-        print_regexp(state->log, lens->regexp);
-        fprintf(state->log, " = <");
-        print_chars(state->log, state->pos, len);
-        fprintf(state->log, ">\n");
+    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) {
+        return NULL;
     }
 
-    advance(state, len);
-    return len;
+    const int reg = 0;
+    int pos = 0;
+    while (pos < outer->size) {
+        count = regexp_match(ctype, outer->start, outer->size, pos, &regs);
+        if (count == -2) {
+            FIXME("Match failed - produce better error");
+            abort();
+        } else if (count == -1) {
+            break;
+        }
+        split_append(&split, outer->start, regs.start[reg], regs.end[reg]);
+        pos = regs.end[reg];
+    }
+    free(regs.start);
+    free(regs.end);
+    return split;
+}
+
+static int applies(struct lens *lens, struct split *split) {
+    int count;
+    count = regexp_match(lens->ctype, split->start, split->size, 0, NULL);
+    if (count == -2) {
+        FIXME("Match failed - produce better error");
+        abort();
+    }
+    return (count == split->size);
 }
 
 static struct tree *get_lens(struct lens *lens, struct state *state);
@@ -369,58 +413,44 @@ static struct skel *parse_counter(struct
     return make_skel(lens);
 }
 
-static struct tree *get_del(struct lens *lens, struct state *state) {
+static struct tree *get_del(struct lens *lens,
+                            ATTRIBUTE_UNUSED struct state *state) {
     assert(lens->tag == L_DEL);
 
-    state->applied = match(lens, state, NULL) >= 0;
     return NULL;
 }
 
 static struct skel *parse_del(struct lens *lens, struct state *state) {
     assert(lens->tag == L_DEL);
-    const char *token = NULL;
     struct skel *skel = NULL;
 
-    state->applied = match(lens, state, &token) >= 0;
-    if (state->applied) {
-        skel = make_skel(lens);
-        skel->text = token;
-    }
+    skel = make_skel(lens);
+    skel->text = token_from_split(state->split);
     return skel;
 }
 
 static struct tree *get_store(struct lens *lens, struct state *state) {
     assert(lens->tag == L_STORE);
-    const char *token = NULL;
     struct tree *tree = NULL;
 
-    if (match(lens, state, &token) < 0)
-        get_expected_error(state, lens);
-    else {
-        assert(state->value == NULL);
-        if (state->value != NULL) {
-            get_error(state, lens, "More than one store in a subtree");
-        } else {
-            state->value = token;
-        }
+    assert(state->value == NULL);
+    if (state->value != NULL) {
+        get_error(state, lens, "More than one store in a subtree");
+    } else {
+        state->value = token_from_split(state->split);
     }
     return tree;
 }
 
-static struct skel *parse_store(struct lens *lens, struct state *state) {
+static struct skel *parse_store(struct lens *lens,
+                                ATTRIBUTE_UNUSED struct state *state) {
     assert(lens->tag == L_STORE);
-    if (match(lens, state, NULL) < 0)
-        get_expected_error(state, lens);
     return make_skel(lens);
 }
 
 static struct tree *get_key(struct lens *lens, struct state *state) {
     assert(lens->tag == L_KEY);
-    const char *token = NULL;
-    if (match(lens, state, &token) < 0)
-        get_expected_error(state, lens);
-    else
-        state->key = token;
+    state->key = token_from_split(state->split);
     return NULL;
 }
 
@@ -440,24 +470,20 @@ static struct skel *parse_label(struct l
     return make_skel(lens);
 }
 
-static int applies(struct lens *lens, struct state *state) {
-    return lex(lens, lens->ctype, state) > 0;
-}
-
 static struct tree *get_union(struct lens *lens, struct state *state) {
     assert(lens->tag == L_UNION);
     struct tree *tree = NULL;
+    int applied = 0;
 
-    state->applied = 0;
     for (int i=0; i < lens->nchildren; i++) {
         struct lens *l = lens->children[i];
-        if (applies(l, state)) {
+        if (applies(l, state->split)) {
             tree = get_lens(l, state);
-            state->applied = 1;
+            applied = 1;
             break;
         }
     }
-    if (! state->applied)
+    if (!applied)
         get_expected_error(state, lens);
     return tree;
 }
@@ -466,17 +492,17 @@ static struct skel *parse_union(struct l
                                 struct dict **dict) {
     assert(lens->tag == L_UNION);
     struct skel *skel = NULL;
+    int applied = 0;
 
-    state->applied = 0;
     for (int i=0; i < lens->nchildren; i++) {
         struct lens *l = lens->children[i];
-        if (applies(l, state)) {
+        if (applies(l, state->split)) {
             skel = parse_lens(l, state, dict);
-            state->applied = 1;
+            applied = 1;
             break;
         }
     }
-    if (! state->applied)
+    if (! applied)
         get_expected_error(state, lens);
 
     return skel;
@@ -484,20 +510,28 @@ static struct skel *parse_union(struct l
 
 static struct tree *get_concat(struct lens *lens, struct state *state) {
     assert(lens->tag == L_CONCAT);
+    struct tree *tree = NULL;
+    struct split *oldsplit = state->split;
+    struct split *split = split_concat(state, lens);
 
-    struct tree *tree = NULL;
-
-    state->applied = 1;
+    state->split = split;
     for (int i=0; i < lens->nchildren; i++) {
         struct tree *t = NULL;
+        if (state->split == NULL) {
+            get_error(state, lens->children[i],
+                      "Not enough components in concat");
+            list_free(split);
+            free_tree(tree);
+            return NULL;
+        }
+
         t = get_lens(lens->children[i], state);
-        if (! state->applied) {
-            get_expected_error(state, lens->children[i]);
-            break;
-        }
         list_append(tree, t);
+        state->split = state->split->next;
     }
 
+    state->split = oldsplit;
+    list_free(split);
     return tree;
 }
 
@@ -505,51 +539,69 @@ static struct skel *parse_concat(struct 
                                  struct dict **dict) {
     assert(lens->tag == L_CONCAT);
     struct skel *skel = make_skel(lens);
+    struct split *oldsplit = state->split;
+    struct split *split = split_concat(state, lens);
 
-    state->applied = 1;
+    state->split = split;
     for (int i=0; i < lens->nchildren; i++) {
         struct skel *sk = NULL;
         struct dict *di = NULL;
+        if (state->split == NULL) {
+            get_error(state, lens->children[i],
+                      "Not enough components in concat");
+            list_free(split);
+            free_skel(skel);
+            return NULL;
+        }
 
         sk = parse_lens(lens->children[i], state, &di);
-        if (! state->applied) {
-            get_expected_error(state, lens->children[i]);
-            break;
-        }
         list_append(skel->skels, sk);
         dict_append(dict, di);
+        state->split = state->split->next;
     }
+
+    state->split = oldsplit;
+    list_free(split);
     return skel;
 }
 
 static struct tree *get_quant_star(struct lens *lens, struct state *state) {
     assert(lens->tag == L_STAR);
+    struct tree *tree = NULL;
+    struct split *oldsplit = state->split;
+    struct split *split = split_iter(lens, state->split);
 
-    struct tree *tree = NULL;
-    while (applies(lens->child, state)) {
+    state->split = split;
+    while (state->split != NULL) {
         struct tree *t = NULL;
         t = get_lens(lens->child, state);
         list_append(tree, t);
+        state->split = state->split->next;
     }
-    state->applied = 1;
+    state->split = oldsplit;
+    list_free(split);
     return tree;
 }
 
 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 skel *skel = make_skel(lens);
 
-    struct skel *skel = make_skel(lens);
     *dict = NULL;
-    while (applies(lens->child, state)) {
+    state->split = split;
+    while (state->split != NULL) {
         struct skel *sk;
         struct dict *di = NULL;
         sk = parse_lens(lens->child, state, &di);
         list_append(skel->skels, sk);
         dict_append(dict, di);
+        state->split = state->split->next;
     }
-    state->applied = 1;
-
+    state->split = oldsplit;
+    list_free(split);
     return skel;
 }
 
@@ -557,10 +609,9 @@ static struct tree *get_quant_maybe(stru
     assert(lens->tag == L_MAYBE);
     struct tree *tree = NULL;
 
-    if (applies(lens->child, state)) {
+    if (applies(lens->child, state->split)) {
         tree = get_lens(lens->child, state);
     }
-    state->applied = 1;
     return tree;
 }
 
@@ -569,12 +620,11 @@ static struct skel *parse_quant_maybe(st
     assert(lens->tag == L_MAYBE);
 
     struct skel *skel = make_skel(lens);
-    if (applies(lens->child, state)) {
+    if (applies(lens->child, state->split)) {
         struct skel *sk;
         sk = parse_lens(lens->child, state, dict);
         list_append(skel->skels, sk);
     }
-    state->applied = 1;
     return skel;
 }
 
@@ -652,38 +702,38 @@ static struct tree *get_lens(struct lens
 }
 
 struct tree *lns_get(struct info *info, struct lens *lens, const char *text,
-                     FILE *log, int flags, struct lns_error **err) {
+                     struct lns_error **err) {
     struct state state;
-    struct tree *tree;
+    struct split split;
+    struct tree *tree = NULL;
 
     MEMZERO(&state, 1);
+    MEMZERO(&split, 1);
     state.info = *info;
     state.info.ref = UINT_MAX;
 
+    split.start = text;
+    split.size = strlen(text);
+
+    state.split = &split;
     state.text = text;
-    state.pos = text;
-    if (flags != PF_NONE && log != NULL) {
-        state.flags = flags;
-        state.log = log;
+
+    if (applies(lens, &split)) {
+        tree = get_lens(lens, &state);
+
+        free_seqs(state.seqs);
+        if (state.key != NULL) {
+            get_error(&state, lens, "get left unused key %s", state.key);
+            free((char *) state.key);
+        }
+        if (state.value != NULL) {
+            get_error(&state, lens, "get left unused value %s", state.value);
+            free((char *) state.value);
+        }
     } else {
-        state.flags = PF_NONE;
-        state.log = stdout;
+        get_error(&state, lens, "get can not process entire input");
     }
 
-    tree = get_lens(lens, &state);
-
-    free_seqs(state.seqs);
-    if (! state.applied || *state.pos != '\0') {
-        get_error(&state, lens, "get did not process entire input");
-    }
-    if (state.key != NULL) {
-        get_error(&state, lens, "get left unused key %s", state.key);
-        free((char *) state.key);
-    }
-    if (state.value != NULL) {
-        get_error(&state, lens, "get left unused value %s", state.value);
-        free((char *) state.value);
-    }
     if (err != NULL) {
         *err = state.error;
     } else {
@@ -744,36 +794,44 @@ struct skel *lns_parse(struct lens *lens
 struct skel *lns_parse(struct lens *lens, const char *text, struct dict **dict,
                        struct lns_error **err) {
     struct state state;
+    struct split split;
     struct skel *skel;
 
     MEMZERO(&state, 1);
+    MEMZERO(&split, 1);
     state.info.ref = UINT_MAX;
     state.text = text;
-    state.pos = text;
-    state.flags = PF_NONE;
 
-    *dict = NULL;
-    skel = parse_lens(lens, &state, dict);
+    split.start = text;
+    split.size = strlen(text);
 
-    free_seqs(state.seqs);
-    if (! state.applied || *state.pos != '\0') {
+    state.split = &split;
+    state.text = text;
+
+    if (applies(lens, &split)) {
+        *dict = NULL;
+        skel = parse_lens(lens, &state, dict);
+
+        free_seqs(state.seqs);
+        if (state.error != NULL) {
+            free_skel(skel);
+            skel = NULL;
+            free_dict(*dict);
+            *dict = NULL;
+        }
+        if (state.key != NULL) {
+            get_error(&state, lens, "parse left unused key %s", state.key);
+            free((char *) state.key);
+        }
+        if (state.value != NULL) {
+            get_error(&state, lens, "parse left unused value %s", state.value);
+            free((char *) state.value);
+        }
+    } else {
         // This should never happen during lns_parse
-        get_error(&state, lens, "parse did not process entire input");
+        get_error(&state, lens, "parse can not process entire input");
     }
-    if (state.error != NULL) {
-        free_skel(skel);
-        skel = NULL;
-        free_dict(*dict);
-        *dict = NULL;
-    }
-    if (state.key != NULL) {
-        get_error(&state, lens, "parse left unused key %s", state.key);
-        free((char *) state.key);
-    }
-    if (state.value != NULL) {
-        get_error(&state, lens, "parse left unused value %s", state.value);
-        free((char *) state.value);
-    }
+
     if (err != NULL) {
         *err = state.error;
     } else {
diff -r 38c46290bfc5 -r bbaa761fac76 src/lens.h
--- a/src/lens.h	Thu May 22 13:18:50 2008 -0700
+++ b/src/lens.h	Thu May 22 18:57:26 2008 -0700
@@ -83,14 +83,6 @@ struct value *lns_make_maybe(struct info
 struct value *lns_make_maybe(struct info *, struct lens *,
                              int check);
 
-/* Flags to control debug printing during parsing */
-enum parse_debug_flags {
-    PF_NONE    = 0,
-    PF_ADVANCE = (1 << 0),  /* Show how the lexer advances through the input */
-    PF_MATCH   = (1 << 1),  /* Show regex matches */
-    PF_TOKEN   = (1 << 2)   /* Show tokenization */
-};
-
 /* Auxiliary data structures used during get/put/create */
 struct skel {
     struct skel *next;
@@ -138,7 +130,7 @@ void free_lns_error(struct lns_error *er
  * parse_flags
  */
 struct tree *lns_get(struct info *info, struct lens *lens, const char *text,
-                     FILE *log, int flags, struct lns_error **err);
+                     struct lns_error **err);
 struct skel *lns_parse(struct lens *lens, const char *text,
                        struct dict **dict, struct lns_error **err);
 void lns_put(FILE *out, struct lens *lens, struct tree *tree,
diff -r 38c46290bfc5 -r bbaa761fac76 src/transform.c
--- a/src/transform.c	Thu May 22 13:18:50 2008 -0700
+++ b/src/transform.c	Thu May 22 18:57:26 2008 -0700
@@ -329,7 +329,7 @@ static int load_file(struct augeas *aug,
     info->filename->str = filename;
     info->first_line = 1;
 
-    tree = lns_get(info, lens, text, stdout, PF_NONE, &err);
+    tree = lns_get(info, lens, text, &err);
 
     info->filename->str = NULL;
     unref(info, info);
diff -r 38c46290bfc5 -r bbaa761fac76 tests/modules/pass_prefix_union.aug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/modules/pass_prefix_union.aug	Thu May 22 18:57:26 2008 -0700
@@ -0,0 +1,8 @@
+module Pass_prefix_union =
+
+let eol = del "\n" "\n"
+let pair (k:regexp) (v:regexp) = [ key k . del "=" "=" . store v . eol ]
+
+let lns = pair "a" "a" | pair "a" "a" . pair "b" "b"
+
+test lns get "a=a\nb=b\n" = ?




More information about the augeas-devel mailing list