diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-07 13:14:12 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-07 13:14:12 +0300 |
commit | d0371e1111cb083b3916a6ced2ed515a69ca71cc (patch) | |
tree | 31cabf0e3dd328c0bb8b2acabc4fc0ee8c844461 /src | |
parent | 366e821d28a007a0ca49b9deb97c6c9cea97f2b9 (diff) | |
download | grecs-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.c | 5 | ||||
-rw-r--r-- | src/grecs.h | 3 | ||||
-rw-r--r-- | src/tree.c | 80 |
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); @@ -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); |