[augeas-devel] [PATCH 1/7] Add an explicit parent pointer to the tree

David Lutterkort lutter at redhat.com
Mon Dec 22 19:46:27 UTC 2008


---
 src/augeas.c   |   68 ++++++++++++++++++++++++++++++-------------------------
 src/builtin.c  |    2 +-
 src/get.c      |    2 +-
 src/internal.h |    4 ++-
 src/parser.y   |    4 +-
 5 files changed, 44 insertions(+), 36 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 7613753..02e0355 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -105,13 +105,10 @@ static void free_path(struct path *path) {
 }
 
 /* Return the start of the list of siblings of SEG->TREE */
-static struct tree *seg_siblings(struct path *path, struct segment *seg) {
-    return (seg == path->segments) ? path->root : (seg-1)->tree->children;
-}
-
-/* Return the parent of SEG->TREE or NULL if SEG->TREE is on the toplevel */
-static struct tree *seg_parent(struct path *path, struct segment *seg) {
-    return (seg == path->segments) ? NULL : (seg-1)->tree;
+static struct tree *seg_siblings(struct segment *seg) {
+    if (seg->tree == NULL || seg->tree->parent == NULL)
+        return NULL;
+    return seg->tree->parent->children;
 }
 
 /* Take a path expression PATH and turn it into a path structure usable for
@@ -203,7 +200,7 @@ static int complete_path(struct path *path, int segnr, struct tree *tree) {
     while (1) {
         struct segment *seg = path->segments + cur;
         int found = 0;
-        struct tree *siblings = seg_siblings(path, seg);
+        struct tree *siblings = seg_siblings(seg);
         list_for_each(t, seg->tree) {
             if (seg->any || streqv(t->label, seg->label)) {
                 int indx = sibling_index(siblings, t);
@@ -234,7 +231,7 @@ static int complete_path(struct path *path, int segnr, struct tree *tree) {
 static struct tree *path_next(struct path *path) {
     for (int i = path->nsegments-1; i >= 0; i--) {
         struct segment *seg = path->segments + i;
-        struct tree *siblings = seg_siblings(path, seg);
+        struct tree *siblings = seg_siblings(seg);
         if (! seg->fixed) {
             list_for_each(t, seg->tree->next) {
                 if (seg->any || streqv(t->label, seg->label)) {
@@ -410,23 +407,28 @@ static char *path_expand(struct tree *tree, struct tree *start,
  */
 static struct segment *tree_create(struct tree *root, struct path *path) {
     struct segment *s, *seg;
+    struct tree *parent = NULL;
 
     for (seg = path->segments;
          seg->tree != NULL && seg <= last_segment(path);
-         seg++);
+         seg++)
+        parent = seg->tree;
+
     if (seg->tree != NULL)
         return NULL;
 
     for (s = seg ; s <= last_segment(path); s++) {
-        s->tree = make_tree(strdup(s->label), NULL, NULL);
+        s->tree = make_tree(strdup(s->label), NULL, parent, NULL);
         if (s->tree == NULL || s->tree->label == NULL)
             goto error;
+        parent = s->tree;
     }
+
     for (s = seg ; s < last_segment(path); s++) {
         s->tree->children = (s+1)->tree;
     }
 
-    struct tree *tree = seg_parent(path, seg);
+    struct tree *tree = seg->tree->parent;
     if (tree == NULL)
         list_append(root, seg->tree);
     else
@@ -481,7 +483,7 @@ struct augeas *aug_init(const char *root, const char *loadpath,
     struct augeas *result;
 
     CALLOC(result, 1);
-    result->tree = make_tree(NULL, NULL, NULL);
+    result->tree = make_tree(NULL, NULL, NULL, NULL);
 
     result->flags = flags;
 
@@ -630,17 +632,17 @@ int tree_insert(struct tree **tree, const char *path, const char *label,
     if (path_find_one(p) != 1)
         goto error;
 
-    new = make_tree(strdup(label), NULL, NULL);
+    struct segment *seg = last_segment(p);
+
+    new = make_tree(strdup(label), NULL, seg->tree->parent, NULL);
     if (new == NULL || new->label == NULL)
         goto error;
 
-    struct segment *seg = last_segment(p);
     if (before) {
-        if (seg == p->segments) {
+        if (new->parent == NULL) {
             list_insert_before(new, seg->tree, *tree);
         } else {
-            struct tree *parent = seg_parent(p, seg);
-            list_insert_before(new, seg->tree, parent->children);
+            list_insert_before(new, seg->tree, new->parent->children);
         }
     } else {
         new->next = seg->tree->next;
@@ -659,7 +661,8 @@ int aug_insert(struct augeas *aug, const char *path, const char *label,
     return tree_insert(&(aug->tree), path, label, before);
 }
 
-struct tree *make_tree(char *label, char *value, struct tree *children) {
+struct tree *make_tree(char *label, char *value, struct tree *parent,
+                       struct tree *children) {
     struct tree *tree;
     CALLOC(tree, 1);
     if (tree == NULL)
@@ -667,7 +670,10 @@ struct tree *make_tree(char *label, char *value, struct tree *children) {
 
     tree->label = label;
     tree->value = value;
+    tree->parent = parent;
     tree->children = children;
+    list_for_each(c, tree->children)
+        c->parent = tree;
     tree->dirty = 1;
     return tree;
 }
@@ -699,7 +705,7 @@ int free_tree(struct tree *tree) {
 
 int tree_rm(struct tree **htree, const char *path) {
     struct path *p = NULL;
-    struct tree *tree, **del, **parents;
+    struct tree *tree, **del;
     int cnt = 0, ndel = 0, i;
 
     p = make_path(*htree, path);
@@ -718,37 +724,32 @@ int tree_rm(struct tree **htree, const char *path) {
         return 0;
     }
 
-    CALLOC(del, ndel);
-    CALLOC(parents, ndel);
-    if (del == NULL || parents == NULL) {
+    if (ALLOC_N(del, ndel) < 0) {
         free(del);
-        free(parents);
         return -1;
     }
 
     for (i = 0, tree = path_first(p); tree != NULL; tree = path_next(p)) {
         if (TREE_HIDDEN(tree))
             continue;
-        parents[i] = seg_parent(p, seg);
         del[i] = seg->tree;
         i += 1;
     }
     free_path(p);
 
     for (i = 0; i < ndel; i++) {
-        if (parents[i] == NULL) {
+        if (del[i]->parent == NULL) {
             list_remove(del[i], *htree);
             if (*htree)
                 (*htree)->dirty = 1;
         } else {
-            list_remove(del[i], parents[i]->children);
-            parents[i]->dirty = 1;
+            list_remove(del[i], del[i]->parent->children);
+            del[i]->parent->dirty = 1;
         }
         cnt += free_tree(del[i]->children) + 1;
         free_tree_node(del[i]);
     }
     free(del);
-    free(parents);
 
     return cnt;
 }
@@ -770,6 +771,9 @@ int aug_tree_replace(struct augeas *aug, const char *path, struct tree *sub) {
         goto error;
 
     list_append(parent->children, sub);
+    list_for_each(s, sub) {
+        s->parent = parent;
+    }
     return 0;
  error:
     return -1;
@@ -809,7 +813,9 @@ int aug_mv(struct augeas *aug, const char *src, const char *dst) {
     free_tree(td->children);
 
     td->children = ts->children;
-
+    list_for_each(c, td->children) {
+        c->parent = td;
+    }
     free(td->value);
     td->value = ts->value;
 
@@ -817,7 +823,7 @@ int aug_mv(struct augeas *aug, const char *src, const char *dst) {
     ts->children = NULL;
 
 
-    t = seg_parent(s, last_segment(s));
+    t = last_segment(s)->tree->parent;
     if (t == NULL) {
         list_remove(ts, aug->tree);
         t = aug->tree;
diff --git a/src/builtin.c b/src/builtin.c
index 549b020..fb48d45 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -177,7 +177,7 @@ static struct value *tree_set_glue(struct info *info, struct value *path,
     struct tree *fake = NULL;
 
     if (tree->tree == NULL) {
-        fake = make_tree(NULL, NULL, NULL);
+        fake = make_tree(NULL, NULL, NULL, NULL);
         tree->tree = fake;
     }
 
diff --git a/src/get.c b/src/get.c
index 38709c9..f0f2f92 100644
--- a/src/get.c
+++ b/src/get.c
@@ -589,7 +589,7 @@ static struct tree *get_subtree(struct lens *lens, struct state *state) {
     state->value = NULL;
     children = get_lens(lens->child, state);
 
-    tree = make_tree(state->key, state->value, children);
+    tree = make_tree(state->key, state->value, NULL, children);
 
     state->key = key;
     state->value = value;
diff --git a/src/internal.h b/src/internal.h
index 0334d8a..9bfea75 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -261,6 +261,7 @@ struct augeas {
  */
 struct tree {
     struct tree *next;
+    struct tree *parent;     /* NULL for root */
     char        *label;      /* Last component of PATH */
     struct tree *children;   /* List of children through NEXT */
     char        *value;
@@ -271,7 +272,8 @@ struct tree {
  * Allocate a new tree node with the given LABEL, VALUE, and CHILDREN,
  * which are not copied. The new tree is marked as dirty
  */
-struct tree *make_tree(char *label, char *value, struct tree *children);
+struct tree *make_tree(char *label, char *value,
+                       struct tree *parent, struct tree *children);
 
 int aug_tree_replace(struct augeas *aug, const char *path, struct tree *sub);
 
diff --git a/src/parser.y b/src/parser.y
index 3ba0c5f..42dac53 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -291,11 +291,11 @@ tree_const: '{' tree_branch '}' tree_const
 
 tree_branch: tree_label tree_const
              {
-               $$ = make_tree($1, NULL, $2);
+               $$ = make_tree($1, NULL, NULL, $2);
              }
            | tree_label '=' DQUOTED tree_const
              {
-               $$ = make_tree($1, $3, $4);
+               $$ = make_tree($1, $3, NULL, $4);
              }
 tree_label: DQUOTED
           | /* empty */
-- 
1.6.0.4




More information about the augeas-devel mailing list