From c70796b9fbe0f397d68fd70d8db27735fbc9d1ea Mon Sep 17 00:00:00 2001 From: Curt Brune Date: Tue, 26 Apr 2022 14:48:12 -0700 Subject: [PATCH] add a capnp annotation for creating name spaces This patch adds an annotation for creating name spaces within capnproto files with the C-language code generator. Use the annotation like this: using C = import "/c.capnp"; $C.namespace("sample_namespace_"); The string passed into the namespace annotation is prepended to the name of all the struct's in the schema file. Signed-off-by: Curt Brune --- compiler/c.capnp | 3 +++ compiler/capnpc-c.c | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/compiler/c.capnp b/compiler/c.capnp index 92c955a..dfcf026 100644 --- a/compiler/c.capnp +++ b/compiler/c.capnp @@ -46,3 +46,6 @@ annotation donotinclude @0x8c99797357b357e9 (file): UInt64; annotation typedefto @0xcefaf27713042144 (struct, enum): Text; # generate a typedef for the annotated struct or enum declaration + +annotation namespace @0xf2c035025fec7c2b (file): Text; +# prefix structs with a name space string diff --git a/compiler/capnpc-c.c b/compiler/capnpc-c.c index 641fe56..fed4853 100644 --- a/compiler/capnpc-c.c +++ b/compiler/capnpc-c.c @@ -147,8 +147,9 @@ static void free_id_bst(struct id_bst * bst) * set node->name. * It also builds up the list of nodes within a file (file_nodes and * next_file_node). */ -static void resolve_names(struct str *b, struct node *n, capn_text name, struct node *file) { +static void resolve_names(struct str *b, struct node *n, capn_text name, struct node *file, const char *namespace) { int i, sz = b->len; + str_add(b, namespace, -1); str_add(b, name.str, name.len); str_add(&n->name, b->str, b->len); str_add(b, "_", 1); @@ -158,14 +159,14 @@ static void resolve_names(struct str *b, struct node *n, capn_text name, struct get_Node_NestedNode(&nest, n->n.nestedNodes, i); struct node *nn = find_node(nest.id); if (nn != NULL) { - resolve_names(b, nn, nest.name, file); + resolve_names(b, nn, nest.name, file, namespace); } } if (n->n.which == Node__struct) { for (i = capn_len(n->n._struct.fields)-1; i >= 0; i--) { if (n->fields[i].group) { - resolve_names(b, n->fields[i].group, n->fields[i].f.name, file); + resolve_names(b, n->fields[i].group, n->fields[i].f.name, file, namespace); } } } @@ -1299,6 +1300,8 @@ static void declare(struct node *file_node, const char *format, int num) { } } +#define ANNOTATION_NAMESPACE 0xf2c035025fec7c2bUL + int main() { struct capn capn; CodeGeneratorRequest_ptr root; @@ -1348,13 +1351,39 @@ int main() { for (n = all_files; n != NULL; n = n->next) { struct str b = STR_INIT; + const char *namespace = NULL; + + /* apply name space if present */ + for (j = capn_len(n->n.annotations)-1; j >= 0; j--) { + struct Annotation a; + struct Value v; + get_Annotation(&a, n->n.annotations, j); + read_Value(&v, a.value); + + if (a.id == ANNOTATION_NAMESPACE) { + if (v.which != Value_text) { + fprintf(stderr, "%s: schema breakage on $C::namespace annotation\n", + n->n.displayName.str); + exit(2); + } + if (namespace) { + fprintf(stderr, "%s: $C::namespace annotation appears more than once.\n", + n->n.displayName.str); + exit(2); + } + namespace = v.text.str ? v.text.str : ""; + } + } + + if (!namespace) + namespace = ""; for (i = capn_len(n->n.nestedNodes)-1; i >= 0; i--) { struct Node_NestedNode nest; get_Node_NestedNode(&nest, n->n.nestedNodes, i); struct node *nn = find_node_mayfail(nest.id); if (nn) { - resolve_names(&b, nn, nest.name, n); + resolve_names(&b, nn, nest.name, n, namespace); } }