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