Hi,

Attached is a first draft of a patch for getting the node position, namely indexes of label and value of a node in the input file. The idea is to be able to highlight those in a UI.

A struct for indexes would be better, but I'm questioning where it should be allocated and freed. I think that allocating it in the get_subtree and free it in the tree destruction should be ok, but I'm not sure if this is the "right" way to do it.

Cheer,

Francis
>From 94249e056b22d81e1d52c126d6a0a340a0f5ddec Mon Sep 17 00:00:00 2001
From: Francis Giraldeau <[email protected]>
Date: Mon, 4 Oct 2010 08:22:42 -0400
Subject: [PATCH] Add basic support for node position

---
 src/augeas.c           |   27 +++++++++++++++++++++++++++
 src/augeas.h           |    3 +++
 src/augeas_sym.version |    5 +++++
 src/augtool.c          |   26 ++++++++++++++++++++++++++
 src/get.c              |   34 ++++++++++++++++++++++++++++++++--
 src/internal.h         |    4 ++++
 tests/test-load.c      |   19 +++++++++++++++++++
 7 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 25ca016..a4d96a7 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -943,6 +943,33 @@ int aug_rm(struct augeas *aug, const char *path) {
     return -1;
 }
 
+int aug_nodepos(struct augeas *aug, const char *path,
+        uint *key_start, uint *key_end, uint *value_start, uint *value_end) {
+    struct pathx *p = NULL;
+    int result;
+    struct tree *tree = NULL;
+
+    api_entry(aug);
+    p = pathx_aug_parse(aug, aug->origin, path, true);
+    tree = pathx_first(p);
+    if (tree == NULL){
+        result = -1;
+        goto error;
+    }
+    *key_start = tree->label_start;
+    *key_end = tree->label_end;
+    *value_start = tree->value_start;
+    *value_end = tree->value_end;
+    result = 0;
+    ERR_BAIL(aug);
+    api_exit(aug);
+    return result;
+
+ error:
+    api_exit(aug);
+    return result;
+}
+
 int tree_replace(struct augeas *aug, const char *path, struct tree *sub) {
     struct tree *parent;
     struct pathx *p = NULL;
diff --git a/src/augeas.h b/src/augeas.h
index b4848cb..9026494 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -149,6 +149,9 @@ int aug_set(augeas *aug, const char *path, const char *value);
  */
 int aug_setm(augeas *aug, const char *base, const char *sub, const char *value);
 
+int aug_nodepos(augeas *aug, const char *path,
+        uint *label_start, uint *label_end, uint *value_start, uint *value_end);
+
 /* Function: aug_insert
  *
  * Create a new sibling LABEL for PATH by inserting into the tree just
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index 542f5fa..a821626 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -34,3 +34,8 @@ AUGEAS_0.11.0 {
     global:
       aug_setm;
 } AUGEAS_0.10.0;
+
+AUGEAS_0.12.0 {
+    global:
+      aug_nodepos;
+} AUGEAS_0.11.0;
diff --git a/src/augtool.c b/src/augtool.c
index 6c8416a..7f8bb79 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -624,6 +624,31 @@ static const struct command_def cmd_setm_def = {
     "BASE will be modified."
 };
 
+static void cmd_nodepos(struct command *cmd) {
+    const char *path = arg_value(cmd, "path");
+    int r;
+    uint key_start, key_end, value_start, value_end;
+    r = aug_nodepos(aug, path, &key_start, &key_end, &value_start, &value_end);
+    err_check(cmd);
+    if (r == -1)
+        printf ("Failed\n");
+    printf("%i,%i,%i,%i\n", key_start, key_end, value_start, value_end);
+}
+
+static const struct command_opt_def cmd_nodepos_opts[] = {
+    { .type = CMD_PATH, .name = "path", .optional = false,
+      .help = "node path" },
+    CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_nodepos_def = {
+    .name = "nodepos",
+    .opts = cmd_nodepos_opts,
+    .handler = cmd_nodepos,
+    .synopsis = "get the key and value position in the text of this node",
+    .help = "get the key and value position in the text of this node"
+};
+
 static void cmd_defvar(struct command *cmd) {
     const char *name = arg_value(cmd, "name");
     const char *path = arg_value(cmd, "expr");
@@ -932,6 +957,7 @@ static const struct command_def const *commands[] = {
     &cmd_save_def,
     &cmd_set_def,
     &cmd_setm_def,
+    &cmd_nodepos_def,
     &cmd_help_def,
     &cmd_def_last
 };
diff --git a/src/get.c b/src/get.c
index 11ea5de..f5b683b 100644
--- a/src/get.c
+++ b/src/get.c
@@ -65,6 +65,11 @@ struct state {
      */
     struct re_registers *regs;
     uint                 nreg;
+    /* Position in the text of this node */
+    uint                 key_start;
+    uint                 key_end;
+    uint                 value_start;
+    uint                 value_end;
 };
 
 /* Used by recursive lenses to stack intermediate results */
@@ -408,8 +413,12 @@ static struct tree *get_store(struct lens *lens, struct state *state) {
         get_error(state, lens, "More than one store in a subtree");
     else if (! REG_MATCHED(state))
         no_match_error(state, lens);
-    else
+    else {
         state->value = token(state);
+        state->value_start = REG_START(state);
+        state->value_end = REG_END(state);
+        //printf("value=%s,value_start=%i,value_end=%i\n", state->value, state->value_start, state->value_end);
+    }
     return tree;
 }
 
@@ -435,8 +444,12 @@ static struct tree *get_key(struct lens *lens, struct state *state) {
     ensure0(lens->tag == L_KEY, state->info);
     if (! REG_MATCHED(state))
         no_match_error(state, lens);
-    else
+    else {
         state->key = token(state);
+        state->key_start = REG_START(state);
+        state->key_end = REG_END(state);
+        //printf("key=%s,key_start=%i,key_end=%i\n", state->key, state->key_start, state->key_end);
+    }
     return NULL;
 }
 
@@ -657,15 +670,32 @@ static struct tree *get_subtree(struct lens *lens, struct state *state) {
     char *key = state->key;
     char *value = state->value;
     struct tree *tree = NULL, *children;
+    uint label_start = state->key_start;
+    uint label_end = state->key_end;
+    uint value_start = state->value_start;
+    uint value_end = state->value_end;
 
     state->key = NULL;
     state->value = NULL;
+    state->key_start = 0;
+    state->key_end = 0;
+    state->value_start = 0;
+    state->value_end = 0;
+
     children = get_lens(lens->child, state);
 
     tree = make_tree(state->key, state->value, NULL, children);
+    tree->label_start = state->key_start;
+    tree->label_end = state->key_end;
+    tree->value_start = state->value_start;
+    tree->value_end = state->value_end;
 
     state->key = key;
     state->value = value;
+    state->key_start = label_start;
+    state->key_end = label_end;
+    state->value_start = value_start;
+    state->value_end = value_end;
     return tree;
 }
 
diff --git a/src/internal.h b/src/internal.h
index 71c5d42..3003922 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -344,6 +344,10 @@ struct tree {
     struct tree *children;   /* List of children through NEXT */
     char        *value;
     int          dirty;
+    uint         label_start;
+    uint         label_end;
+    uint         value_start;
+    uint         value_end;
 };
 
 /* The opaque structure used to represent path expressions. API's
diff --git a/tests/test-load.c b/tests/test-load.c
index 6110ebc..d6ee531 100644
--- a/tests/test-load.c
+++ b/tests/test-load.c
@@ -484,6 +484,24 @@ static void testParseErrorReported(CuTest *tc) {
     aug_close(aug);
 }
 
+static void testNodePos(CuTest *tc) {
+    int r;
+    struct augeas *aug;
+    static const char *const expr = "/files/etc/hosts/1/ipaddr";
+    uint label_start, label_end, value_start, value_end;
+    aug = setup_writable_hosts(tc);
+
+    r = aug_load(aug);
+    CuAssertRetSuccess(tc, r);
+
+    r = aug_nodepos(aug, expr, &label_start, &label_end, &value_start, &value_end);
+    CuAssertRetSuccess(tc, r);
+    CuAssertIntEquals(tc, 0, label_start);
+    CuAssertIntEquals(tc, 0, label_end);
+    CuAssertIntEquals(tc, 104, value_start);
+    CuAssertIntEquals(tc, 113, value_end);
+}
+
 int main(void) {
     char *output = NULL;
     CuSuite* suite = CuSuiteNew();
@@ -502,6 +520,7 @@ int main(void) {
     SUITE_ADD_TEST(suite, testReloadDeletedMeta);
     SUITE_ADD_TEST(suite, testReloadExternalMod);
     SUITE_ADD_TEST(suite, testParseErrorReported);
+    SUITE_ADD_TEST(suite, testNodePos);
 
     abs_top_srcdir = getenv("abs_top_srcdir");
     if (abs_top_srcdir == NULL)
-- 
1.7.0.4

_______________________________________________
augeas-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/augeas-devel

Reply via email to