aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-07 13:14:12 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-05-07 13:14:12 +0300
commitd0371e1111cb083b3916a6ced2ed515a69ca71cc (patch)
tree31cabf0e3dd328c0bb8b2acabc4fc0ee8c844461 /src
parent366e821d28a007a0ca49b9deb97c6c9cea97f2b9 (diff)
downloadgrecs-d0371e1111cb083b3916a6ced2ed515a69ca71cc.tar.gz
grecs-d0371e1111cb083b3916a6ced2ed515a69ca71cc.tar.bz2
Implement table-driven statement aggregation.
* src/grecs.h (grecs_tree_reduce): Change signature. (nodeproc_closure)<flags>: New member. (value_to_list): Bugfixes. (value_to_array,array_add): New functions. (node_aggregate_stmt): Rewrite. (node_merge_stmt): Take additional argument. (grecs_tree_reduce): Take additional argument. All uses changed. * src/tree.c (grecs_tree_free): Don't coredump on NULL arg. * src/format.c (grecs_format_simple_statement): Bugfix. * tests/reduce03.at: New testcase. * tests/Makefile.am: Add reduce03.at * tests/testsuite.at: Add reduce03.at * tests/gcffmt.c: Single grecs_format_node call is enough to print the entire tree. * tests/gcfset.c (logging_kwtab): Mark "facility" as GRECS_AGGR to disable aggregation. (usage): Update. (main): New options: -print, -locus, -sort, -noset. Pass GRECS_AGGR to grecs_tree_reduce.
Diffstat (limited to 'src')
-rw-r--r--src/format.c5
-rw-r--r--src/grecs.h3
-rw-r--r--src/tree.c80
3 files changed, 71 insertions, 17 deletions
diff --git a/src/format.c b/src/format.c
index f12b465..9b6b6af 100644
--- a/src/format.c
+++ b/src/format.c
@@ -145,6 +145,7 @@ grecs_format_simple_statement(struct grecs_keyword *kwp, unsigned level,
gettext(grecs_data_type_string(
- GRECS_TYPE (kwp->type))));
+ GRECS_TYPE(kwp->type))));
else
fprintf(stream, "%s",
- gettext(grecs_data_type_string(kwp->type)));
+ gettext(grecs_data_type_string(
+ GRECS_TYPE(kwp->type))));
fprintf(stream, ">;\n");
diff --git a/src/grecs.h b/src/grecs.h
index f32fc1f..628f9f2 100644
--- a/src/grecs.h
+++ b/src/grecs.h
@@ -340,3 +340,4 @@ struct grecs_node *grecs_find_node(struct grecs_node *node, const char *path);
struct grecs_node *grecs_node_from_path(const char *path, const char *value);
-int grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd);
+int grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd,
+ int flags);
diff --git a/src/tree.c b/src/tree.c
index 955fc52..06f15f0 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -218,3 +218,5 @@ grecs_tree_free(struct grecs_node *node)
{
- /* FIXME: Check if that's a node_type_root */
+ if (!node)
+ return 0;
+ /* FIXME: Check if that's a node_type_root */
if (node->type != grecs_node_root) {
@@ -762,2 +764,3 @@ struct nodeproc_closure {
struct grecs_list *sections;
+ int flags;
};
@@ -902,3 +905,3 @@ value_to_list(struct grecs_value *val)
- if (val->type != GRECS_TYPE_LIST)
+ if (val->type == GRECS_TYPE_LIST)
return;
@@ -907,3 +910,3 @@ value_to_list(struct grecs_value *val)
case GRECS_TYPE_STRING:
- grecs_list_append(list, val);
+ grecs_list_append(list, grecs_value_ptr_from_static(val));
break;
@@ -919,7 +922,50 @@ value_to_list(struct grecs_value *val)
static void
+value_to_array(struct grecs_value *val)
+{
+ if (val->type == GRECS_TYPE_ARRAY)
+ return;
+ else {
+ struct grecs_value **vp;
+ vp = grecs_calloc(1, sizeof(*vp));
+ vp[0] = grecs_value_ptr_from_static(val);
+ val->type = GRECS_TYPE_ARRAY;
+ val->v.arg.c = 1;
+ val->v.arg.v = vp;
+ }
+}
+
+static void
+array_add(struct grecs_value *vx, struct grecs_value *vy)
+{
+ size_t i;
+
+ vx->v.arg.v = grecs_realloc(vx->v.arg.v,
+ (vx->v.arg.c + vy->v.arg.c) *
+ sizeof(vx->v.arg.v[0]));
+ for (i = 0; i < vy->v.arg.c; i++)
+ vx->v.arg.v[i + vy->v.arg.c] = vy->v.arg.v[i];
+ grecs_free(vy->v.arg.v);
+ vy->v.arg.v = NULL;
+ vy->v.arg.c = 0;
+}
+
+static void
node_aggregate_stmt(struct grecs_node *dst, struct grecs_node *src, int type)
{
- value_to_list(dst->v.value);
- value_to_list(src->v.value);
- grecs_list_add(dst->v.value->v.list, src->v.value->v.list);
+ if (GRECS_IS_LIST(type)) {
+ struct grecs_list *t;
+ /* Coerce both arguments to lists */
+ value_to_list(dst->v.value);
+ value_to_list(src->v.value);
+ /* Aggregate two lists in order */
+ grecs_list_add(src->v.value->v.list, dst->v.value->v.list);
+ /* Swap them */
+ t = dst->v.value->v.list;
+ dst->v.value->v.list = src->v.value->v.list;
+ src->v.value->v.list = t;
+ } else {
+ value_to_array(dst->v.value);
+ value_to_array(src->v.value);
+ array_add(dst->v.value, src->v.value);
+ }
}
@@ -928,5 +974,7 @@ static void
node_merge_stmt(struct grecs_node *to_node, struct grecs_node *from_node,
- struct grecs_keyword *kwp)
+ struct grecs_keyword *kwp, int flags)
{
- if (kwp && GRECS_IS_LIST(kwp->type) && (kwp->type & GRECS_AGGR))
+ if (kwp &&
+ (flags & GRECS_AGGR) ^ (kwp->type & GRECS_AGGR) &&
+ (GRECS_IS_LIST(kwp->type) || kwp->callback))
node_aggregate_stmt(to_node, from_node, kwp->type);
@@ -957,3 +1005,3 @@ node_merge_block(struct grecs_node *to_node, struct grecs_node *from_node,
static void
-node_reduce(struct grecs_node *node, struct grecs_keyword *kwp)
+node_reduce(struct grecs_node *node, struct grecs_keyword *kwp, int flags)
{
@@ -969,3 +1017,3 @@ node_reduce(struct grecs_node *node, struct grecs_keyword *kwp)
case grecs_node_stmt:
- node_merge_stmt(p, node, kwp);
+ node_merge_stmt(p, node, kwp, flags);
break;
@@ -987,3 +1035,4 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
if (clos->sections)
- grecs_list_pop(clos->sections);
+ clos->cursect = (struct grecs_keyword *)
+ grecs_list_pop(clos->sections);
} else {
@@ -994,3 +1043,4 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
grecs_error(&node->locus, 0,
- _("Unknown keyword"));
+ _("%s: unknown keyword"),
+ node->ident);
return grecs_tree_recurse_skip;
@@ -1002,3 +1052,3 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
}
- node_reduce(node, kwp);
+ node_reduce(node, kwp, clos->flags);
}
@@ -1008,3 +1058,4 @@ reduceproc(enum grecs_tree_recurse_op op, struct grecs_node *node, void *data)
int
-grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd)
+grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd,
+ int flags)
{
@@ -1022,2 +1073,3 @@ grecs_tree_reduce(struct grecs_node *node, struct grecs_keyword *kwd)
}
+ clos.flags = flags;
rc = grecs_tree_recurse(node->down, reduceproc, &clos);

Return to:

Send suggestions and report system problems to the System administrator.