1273 lines
35 KiB
C
1273 lines
35 KiB
C
#include "schema.capnp.h"
|
|
#include "str.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
struct value {
|
|
struct Type t;
|
|
const char *tname;
|
|
struct str tname_buf;
|
|
struct Value v;
|
|
capn_ptr ptrval;
|
|
int64_t intval;
|
|
};
|
|
|
|
struct field {
|
|
struct Field f;
|
|
struct value v;
|
|
struct node *group;
|
|
};
|
|
|
|
struct node {
|
|
struct capn_tree hdr;
|
|
struct Node n;
|
|
struct node *next;
|
|
struct node *file_nodes, *next_file_node;
|
|
struct str name;
|
|
struct field *fields;
|
|
};
|
|
|
|
// annotation ids introduced via c++.capnp, see comments in find_node()
|
|
static const uint64_t NAMESPACE_ANNOTATION_ID = 0xb9c6f99ebf805f2cull;
|
|
static const uint64_t NAME_ANNOTATION_ID = 0xf264a779fef191ceull;
|
|
|
|
static struct str SRC = STR_INIT, HDR = STR_INIT;
|
|
static struct capn g_valcapn;
|
|
static struct capn_segment g_valseg;
|
|
static int g_valc;
|
|
static int g_val0used, g_nullused;
|
|
|
|
static struct capn_tree *g_node_tree;
|
|
|
|
struct node *find_node(uint64_t id) {
|
|
|
|
/*
|
|
* TODO: an Annotation is technically a node (since it can show up in
|
|
* a Node's NestedNode list), but a `struct node` is currently configured
|
|
* to represent only Nodes. So when processing all nested nodes,
|
|
* we need a way to handle entities (like Annotation) which can't be
|
|
* represented by a `struct node`.
|
|
*
|
|
* Current workaround is a hard coded test for the annotations
|
|
* introduced via c++.capnp (NAME_ANNOTATION_ID and NAMESPACE_ANNOTATION_ID),
|
|
* and to report that we don't have a node associated with them
|
|
* (but at least don't fail and stop further processing).
|
|
*/
|
|
|
|
if (id == NAME_ANNOTATION_ID || id == NAMESPACE_ANNOTATION_ID) {
|
|
return NULL;
|
|
}
|
|
|
|
struct node *s = (struct node*) g_node_tree;
|
|
while (s && s->n.id != id) {
|
|
s = (struct node*) s->hdr.link[s->n.id < id];
|
|
}
|
|
if (s == NULL) {
|
|
fprintf(stderr, "cant find node with id 0x%x%x\n", (uint32_t) (id >> 32), (uint32_t) id);
|
|
exit(2);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
static void insert_node(struct node *s) {
|
|
struct capn_tree **x = &g_node_tree;
|
|
while (*x) {
|
|
s->hdr.parent = *x;
|
|
x = &(*x)->link[((struct node*)*x)->n.id < s->n.id];
|
|
}
|
|
*x = &s->hdr;
|
|
g_node_tree = capn_tree_insert(g_node_tree, &s->hdr);
|
|
}
|
|
|
|
/* resolve_names recursively follows the nestedNodes tree in order to
|
|
* 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) {
|
|
int i, sz = b->len;
|
|
str_add(b, name.str, name.len);
|
|
str_add(&n->name, b->str, b->len);
|
|
str_add(b, "_", 1);
|
|
|
|
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(nest.id);
|
|
if (nn != NULL) {
|
|
resolve_names(b, nn, nest.name, file);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (n->n.which != Node__struct || !n->n._struct.isGroup) {
|
|
n->next_file_node = file->file_nodes;
|
|
file->file_nodes = n;
|
|
}
|
|
|
|
str_setlen(b, sz);
|
|
}
|
|
|
|
static void define_enum(struct node *n) {
|
|
int i;
|
|
|
|
str_addf(&HDR, "\nenum %s {", n->name.str);
|
|
for (i = 0; i < capn_len(n->n._enum.enumerants); i++) {
|
|
struct Enumerant e;
|
|
get_Enumerant(&e, n->n._enum.enumerants, i);
|
|
if (i) {
|
|
str_addf(&HDR, ",");
|
|
}
|
|
str_addf(&HDR, "\n\t%s_%s = %d", n->name.str, e.name.str, i);
|
|
}
|
|
str_addf(&HDR, "\n};\n");
|
|
}
|
|
|
|
static void decode_value(struct value* v, Type_ptr type, Value_ptr value, const char *symbol) {
|
|
struct Type list_type;
|
|
memset(v, 0, sizeof(*v));
|
|
read_Type(&v->t, type);
|
|
read_Value(&v->v, value);
|
|
|
|
switch (v->t.which) {
|
|
case Type__void:
|
|
v->tname = "void";
|
|
break;
|
|
case Type__bool:
|
|
v->tname = "unsigned";
|
|
break;
|
|
case Type_int8:
|
|
v->tname = "int8_t";
|
|
break;
|
|
case Type_int16:
|
|
v->tname = "int16_t";
|
|
break;
|
|
case Type_int32:
|
|
v->tname = "int32_t";
|
|
break;
|
|
case Type_int64:
|
|
v->tname = "int64_t";
|
|
break;
|
|
case Type_uint8:
|
|
v->tname = "uint8_t";
|
|
break;
|
|
case Type_uint16:
|
|
v->tname = "uint16_t";
|
|
break;
|
|
case Type_uint32:
|
|
v->tname = "uint32_t";
|
|
break;
|
|
case Type_uint64:
|
|
v->tname = "uint64_t";
|
|
break;
|
|
case Type_float32:
|
|
v->tname = "float";
|
|
break;
|
|
case Type_float64:
|
|
v->tname = "double";
|
|
break;
|
|
case Type_text:
|
|
v->tname = "capn_text";
|
|
break;
|
|
case Type_data:
|
|
v->tname = "capn_data";
|
|
break;
|
|
case Type__enum:
|
|
v->tname = strf(&v->tname_buf, "enum %s", find_node(v->t._enum.typeId)->name.str);
|
|
break;
|
|
case Type__struct:
|
|
case Type__interface:
|
|
v->tname = strf(&v->tname_buf, "%s_ptr", find_node(v->t._struct.typeId)->name.str);
|
|
break;
|
|
case Type_anyPointer:
|
|
v->tname = "capn_ptr";
|
|
break;
|
|
case Type__list:
|
|
read_Type(&list_type, v->t._list.elementType);
|
|
|
|
switch (list_type.which) {
|
|
case Type__void:
|
|
v->tname = "capn_ptr";
|
|
break;
|
|
case Type__bool:
|
|
v->tname = "capn_list1";
|
|
break;
|
|
case Type_int8:
|
|
case Type_uint8:
|
|
v->tname = "capn_list8";
|
|
break;
|
|
case Type_int16:
|
|
case Type_uint16:
|
|
case Type__enum:
|
|
v->tname = "capn_list16";
|
|
break;
|
|
case Type_int32:
|
|
case Type_uint32:
|
|
case Type_float32:
|
|
v->tname = "capn_list32";
|
|
break;
|
|
case Type_int64:
|
|
case Type_uint64:
|
|
case Type_float64:
|
|
v->tname = "capn_list64";
|
|
break;
|
|
case Type_text:
|
|
case Type_data:
|
|
case Type_anyPointer:
|
|
case Type__list:
|
|
v->tname = "capn_ptr";
|
|
break;
|
|
case Type__struct:
|
|
case Type__interface:
|
|
v->tname = strf(&v->tname_buf, "%s_list", find_node(list_type._struct.typeId)->name.str);
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (v->v.which) {
|
|
case Value__bool:
|
|
v->intval = v->v._bool;
|
|
break;
|
|
case Value_int8:
|
|
case Value_uint8:
|
|
v->intval = v->v.int8;
|
|
break;
|
|
case Value_int16:
|
|
case Value_uint16:
|
|
case Value__enum:
|
|
v->intval = v->v.int16;
|
|
break;
|
|
case Value_int32:
|
|
case Value_uint32:
|
|
case Value_float32:
|
|
v->intval = v->v.int32;
|
|
break;
|
|
case Value_int64:
|
|
case Value_float64:
|
|
case Value_uint64:
|
|
v->intval = v->v.int64;
|
|
break;
|
|
case Value_text:
|
|
if (v->v.text.len) {
|
|
capn_ptr p = capn_root(&g_valcapn);
|
|
if (capn_set_text(p, 0, v->v.text)) {
|
|
fprintf(stderr, "failed to copy text\n");
|
|
exit(2);
|
|
}
|
|
p = capn_getp(p, 0, 1);
|
|
if (!p.type)
|
|
break;
|
|
|
|
v->ptrval = p;
|
|
|
|
if (!symbol) {
|
|
static struct str buf = STR_INIT;
|
|
v->intval = ++g_valc;
|
|
symbol = strf(&buf, "capn_val%d", (int) v->intval);
|
|
}
|
|
|
|
str_addf(&SRC, "%scapn_text %s = {%d,(char*)&capn_buf[%d],(struct capn_segment*)&capn_seg};\n",
|
|
symbol ? "" : "static ",
|
|
symbol,
|
|
p.len-1,
|
|
(int) (p.data-p.seg->data-8));
|
|
}
|
|
break;
|
|
|
|
case Value_data:
|
|
case Value__struct:
|
|
case Value_anyPointer:
|
|
case Value__list:
|
|
if (v->v.anyPointer.type) {
|
|
capn_ptr p = capn_root(&g_valcapn);
|
|
if (capn_setp(p, 0, v->v.anyPointer)) {
|
|
fprintf(stderr, "failed to copy object\n");
|
|
exit(2);
|
|
}
|
|
p = capn_getp(p, 0, 1);
|
|
if (!p.type)
|
|
break;
|
|
|
|
v->ptrval = p;
|
|
|
|
if (!symbol) {
|
|
static struct str buf = STR_INIT;
|
|
v->intval = ++g_valc;
|
|
symbol = strf(&buf, "capn_val%d", (int) v->intval);
|
|
}
|
|
|
|
str_addf(&SRC, "%s%s %s = {", symbol ? "" : "static ", v->tname, symbol);
|
|
if (strcmp(v->tname, "capn_ptr"))
|
|
str_addf(&SRC, "{");
|
|
|
|
str_addf(&SRC, "%d,%d,%d,%d,%d,%d,%d,(char*)&capn_buf[%d],(struct capn_segment*)&capn_seg",
|
|
p.type,
|
|
p.has_ptr_tag,
|
|
p.is_list_member,
|
|
p.is_composite_list,
|
|
p.datasz,
|
|
p.ptrs,
|
|
p.len,
|
|
(int) (p.data-p.seg->data-8));
|
|
|
|
if (strcmp(v->tname, "capn_ptr"))
|
|
str_addf(&SRC, "}");
|
|
|
|
str_addf(&SRC, "};\n");
|
|
}
|
|
break;
|
|
|
|
case Value__interface:
|
|
case Value__void:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void define_const(struct node *n) {
|
|
struct value v;
|
|
decode_value(&v, n->n._const.type, n->n._const.value, n->name.str);
|
|
|
|
switch (v.v.which) {
|
|
case Value__bool:
|
|
case Value_int8:
|
|
case Value_int16:
|
|
case Value_int32:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
str_addf(&SRC, "%s %s = %d;\n", v.tname, n->name.str, (int) v.intval);
|
|
break;
|
|
|
|
case Value_uint8:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
str_addf(&SRC, "%s %s = %u;\n", v.tname, n->name.str, (uint8_t) v.intval);
|
|
break;
|
|
|
|
case Value_uint16:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
str_addf(&SRC, "%s %s = %u;\n", v.tname, n->name.str, (uint16_t) v.intval);
|
|
break;
|
|
|
|
case Value_uint32:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
str_addf(&SRC, "%s %s = %uu;\n", v.tname, n->name.str, (uint32_t) v.intval);
|
|
break;
|
|
|
|
case Value__enum:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
str_addf(&SRC, "%s %s = (%s) %uu;\n", v.tname, n->name.str, v.tname, (uint32_t) v.intval);
|
|
break;
|
|
|
|
case Value_int64:
|
|
case Value_uint64:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
str_addf(&SRC, "%s %s = ((uint64_t) %#xu << 32) | %#xu;\n", v.tname, n->name.str,
|
|
(uint32_t) (v.intval >> 32), (uint32_t) v.intval);
|
|
break;
|
|
|
|
case Value_float32:
|
|
str_addf(&HDR, "extern union capn_conv_f32 %s;\n", n->name.str);
|
|
str_addf(&SRC, "union capn_conv_f32 %s = {%#xu};\n", n->name.str, (uint32_t) v.intval);
|
|
break;
|
|
|
|
case Value_float64:
|
|
str_addf(&HDR, "extern union capn_conv_f64 %s;\n", n->name.str);
|
|
str_addf(&SRC, "union capn_conv_f64 %s = {((uint64_t) %#xu << 32) | %#xu};\n",
|
|
n->name.str, (uint32_t) (v.intval >> 32), (uint32_t) v.intval);
|
|
break;
|
|
|
|
case Value_text:
|
|
case Value_data:
|
|
case Value__struct:
|
|
case Value_anyPointer:
|
|
case Value__list:
|
|
str_addf(&HDR, "extern %s %s;\n", v.tname, n->name.str);
|
|
if (!v.ptrval.type) {
|
|
str_addf(&SRC, "%s %s;\n", v.tname, n->name.str);
|
|
}
|
|
break;
|
|
|
|
case Value__interface:
|
|
case Value__void:
|
|
break;
|
|
}
|
|
|
|
str_release(&v.tname_buf);
|
|
}
|
|
|
|
static void decode_field(struct field *fields, Field_list l, int i) {
|
|
struct field f;
|
|
memset(&f, 0, sizeof(f));
|
|
get_Field(&f.f, l, i);
|
|
|
|
if (f.f.codeOrder >= capn_len(l)) {
|
|
fprintf(stderr, "unexpectedly large code order %d >= %d\n", f.f.codeOrder, capn_len(l));
|
|
exit(3);
|
|
}
|
|
|
|
if (f.f.which == Field_group) {
|
|
f.group = find_node(f.f.group.typeId);
|
|
}
|
|
|
|
memcpy(&fields[f.f.codeOrder], &f, sizeof(f));
|
|
}
|
|
|
|
static const char *xor_member(struct field *f) {
|
|
static struct str buf = STR_INIT;
|
|
|
|
if (f->v.intval) {
|
|
switch (f->v.v.which) {
|
|
case Value_int8:
|
|
case Value_int16:
|
|
case Value_int32:
|
|
return strf(&buf, " ^ %d", (int32_t) f->v.intval);
|
|
|
|
case Value_uint8:
|
|
return strf(&buf, " ^ %uu", (uint8_t) f->v.intval);
|
|
|
|
case Value_uint16:
|
|
case Value__enum:
|
|
return strf(&buf, " ^ %uu", (uint16_t) f->v.intval);
|
|
|
|
case Value_uint32:
|
|
return strf(&buf, " ^ %uu", (uint32_t) f->v.intval);
|
|
|
|
case Value_float32:
|
|
return strf(&buf, " ^ %#xu", (uint32_t) f->v.intval);
|
|
|
|
case Value_int64:
|
|
case Value_uint64:
|
|
case Value_float64:
|
|
return strf(&buf, " ^ ((uint64_t) %#xu << 32) ^ %#xu",
|
|
(uint32_t) (f->v.intval >> 32), (uint32_t) f->v.intval);
|
|
|
|
default:
|
|
return "";
|
|
}
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
static const char *ptr_member(struct field *f, const char *var) {
|
|
static struct str buf = STR_INIT;
|
|
if (!strcmp(f->v.tname, "capn_ptr")) {
|
|
return var;
|
|
} else if (var[0] == '*') {
|
|
return strf(&buf, "%s->p", var+1);
|
|
} else {
|
|
return strf(&buf, "%s.p", var);
|
|
}
|
|
}
|
|
|
|
static void set_member(struct str *func, struct field *f, const char *ptr, const char *tab, const char *var) {
|
|
const char *xor = xor_member(f);
|
|
const char *pvar = ptr_member(f, var);
|
|
|
|
if (f->v.t.which == Type__void)
|
|
return;
|
|
|
|
str_add(func, tab, -1);
|
|
|
|
switch (f->v.t.which) {
|
|
case Type__bool:
|
|
str_addf(func, "capn_write1(%s, %d, %s != %d);\n", ptr, f->f.slot.offset, var, (int) f->v.intval);
|
|
break;
|
|
case Type_int8:
|
|
str_addf(func, "capn_write8(%s, %d, (uint8_t) %s%s);\n", ptr, f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_int16:
|
|
case Type__enum:
|
|
str_addf(func, "capn_write16(%s, %d, (uint16_t) %s%s);\n", ptr, 2*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_int32:
|
|
str_addf(func, "capn_write32(%s, %d, (uint32_t) %s%s);\n", ptr, 4*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_int64:
|
|
str_addf(func, "capn_write64(%s, %d, (uint64_t) %s%s);\n", ptr, 8*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_uint8:
|
|
str_addf(func, "capn_write8(%s, %d, %s%s);\n", ptr, f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_uint16:
|
|
str_addf(func, "capn_write16(%s, %d, %s%s);\n", ptr, 2*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_uint32:
|
|
str_addf(func, "capn_write32(%s, %d, %s%s);\n", ptr, 4*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_float32:
|
|
str_addf(func, "capn_write32(%s, %d, capn_from_f32(%s)%s);\n", ptr, 4*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_uint64:
|
|
str_addf(func, "capn_write64(%s, %d, %s%s);\n", ptr, 8*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_float64:
|
|
str_addf(func, "capn_write64(%s, %d, capn_from_f64(%s)%s);\n", ptr, 8*f->f.slot.offset, var, xor);
|
|
break;
|
|
case Type_text:
|
|
if (f->v.ptrval.type) {
|
|
g_val0used = 1;
|
|
str_addf(func, "capn_set_text(%s, %d, (%s.str != capn_val%d.str) ? %s : capn_val0);\n",
|
|
ptr, f->f.slot.offset, var, (int)f->v.intval, var);
|
|
} else {
|
|
str_addf(func, "capn_set_text(%s, %d, %s);\n",
|
|
ptr, f->f.slot.offset, var);
|
|
}
|
|
break;
|
|
case Type_data:
|
|
case Type__struct:
|
|
case Type__interface:
|
|
case Type__list:
|
|
case Type_anyPointer:
|
|
if (!f->v.intval) {
|
|
str_addf(func, "capn_setp(%s, %d, %s);\n",
|
|
ptr, f->f.slot.offset, pvar);
|
|
} else if (!strcmp(f->v.tname, "capn_ptr")) {
|
|
g_nullused = 1;
|
|
str_addf(func, "capn_setp(%s, %d, (%s.data != capn_val%d.data) ? %s : capn_null);\n",
|
|
ptr, f->f.slot.offset, pvar, (int)f->v.intval, pvar);
|
|
} else {
|
|
g_nullused = 1;
|
|
str_addf(func, "capn_setp(%s, %d, (%s.data != capn_val%d.p.data) ? %s : capn_null);\n",
|
|
ptr, f->f.slot.offset, pvar, (int)f->v.intval, pvar);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void get_member(struct str *func, struct field *f, const char *ptr, const char *tab, const char *var) {
|
|
const char *xor = xor_member(f);
|
|
const char *pvar = ptr_member(f, var);
|
|
|
|
if (f->v.t.which == Type__void)
|
|
return;
|
|
|
|
str_add(func, tab, -1);
|
|
|
|
switch (f->v.t.which) {
|
|
case Type__bool:
|
|
str_addf(func, "%s = (capn_read8(%s, %d) & %d) != %d;\n",
|
|
var, ptr, f->f.slot.offset/8, 1 << (f->f.slot.offset%8), (int)f->v.intval);
|
|
return;
|
|
case Type_int8:
|
|
str_addf(func, "%s = (int8_t) capn_read8(%s, %d)%s;\n", var, ptr, f->f.slot.offset, xor);
|
|
return;
|
|
case Type_int16:
|
|
str_addf(func, "%s = (int16_t) capn_read16(%s, %d)%s;\n", var, ptr, 2*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_int32:
|
|
str_addf(func, "%s = (int32_t) capn_read32(%s, %d)%s;\n", var, ptr, 4*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_int64:
|
|
str_addf(func, "%s = (int64_t) capn_read64(%s, %d)%s;\n", var, ptr, 8*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_uint8:
|
|
str_addf(func, "%s = capn_read8(%s, %d)%s;\n", var, ptr, f->f.slot.offset, xor);
|
|
return;
|
|
case Type_uint16:
|
|
str_addf(func, "%s = capn_read16(%s, %d)%s;\n", var, ptr, 2*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_uint32:
|
|
str_addf(func, "%s = capn_read32(%s, %d)%s;\n", var, ptr, 4*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_uint64:
|
|
str_addf(func, "%s = capn_read64(%s, %d)%s;\n", var, ptr, 8*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_float32:
|
|
str_addf(func, "%s = capn_to_f32(capn_read32(%s, %d)%s);\n", var, ptr, 4*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_float64:
|
|
str_addf(func, "%s = capn_to_f64(capn_read64(%s, %d)%s);\n", var, ptr, 8*f->f.slot.offset, xor);
|
|
return;
|
|
case Type__enum:
|
|
str_addf(func, "%s = (%s) capn_read16(%s, %d)%s;\n", var, f->v.tname, ptr, 2*f->f.slot.offset, xor);
|
|
return;
|
|
case Type_text:
|
|
if (!f->v.intval)
|
|
g_val0used = 1;
|
|
str_addf(func, "%s = capn_get_text(%s, %d, capn_val%d);\n", var, ptr, f->f.slot.offset, (int)f->v.intval);
|
|
return;
|
|
|
|
case Type_data:
|
|
str_addf(func, "%s = capn_get_data(%s, %d);\n", var, ptr, f->f.slot.offset);
|
|
break;
|
|
case Type__struct:
|
|
case Type__interface:
|
|
case Type_anyPointer:
|
|
case Type__list:
|
|
str_addf(func, "%s = capn_getp(%s, %d, 0);\n", pvar, ptr, f->f.slot.offset);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if (f->v.intval) {
|
|
str_addf(func, "%sif (!%s.type) {\n", tab, pvar);
|
|
str_addf(func, "%s\t%s = capn_val%d;\n", tab, var, (int)f->v.intval);
|
|
str_addf(func, "%s}\n", tab);
|
|
}
|
|
}
|
|
|
|
struct strings {
|
|
struct str ftab;
|
|
struct str dtab;
|
|
struct str get;
|
|
struct str set;
|
|
struct str enums;
|
|
struct str decl;
|
|
struct str var;
|
|
};
|
|
|
|
static const char *field_name(struct field *f) {
|
|
static struct str buf = STR_INIT;
|
|
static const char *reserved[] = {
|
|
/* C++11 reserved words */
|
|
"alignas", "alignof", "and", "and_eq", "asm",
|
|
"auto", "bitand", "bitor", "bool", "break",
|
|
"case", "catch", "char", "char16_t", "char32_t",
|
|
"class", "compl", "const", "constexpr", "const_cast",
|
|
"continue", "decltype", "default", "delete", "do",
|
|
"double", "dynamic_cast", "else", "enum", "explicit",
|
|
"export", "extern", "false", "float", "for",
|
|
"friend", "goto", "if", "inline", "int",
|
|
"long", "mutable", "namespace", "new", "noexcept",
|
|
"not", "not_eq", "nullptr", "operator", "or",
|
|
"or_eq", "private", "protected", "public", "register",
|
|
"reinterpret_cast", "return", "short", "signed", "sizeof",
|
|
"static", "static_assert", "static_cast", "struct", "switch",
|
|
"template", "this", "thread_local", "throw", "true",
|
|
"try", "typedef", "typeid", "typename", "union",
|
|
"unsigned", "using", "virtual", "void", "volatile",
|
|
"wchar_t", "while", "xor", "xor_eq",
|
|
/* COM reserved words */
|
|
"interface", "module", "import",
|
|
/* capn reserved otherwise Value_ptr enum and type collide */
|
|
"ptr", "list",
|
|
/* C11 keywords not reserved in C++ */
|
|
"restrict", "_Alignas", "_Alignof", "_Atomic", "_Bool",
|
|
"_Complex", "_Generic", "_Imaginary", "_Noreturn", "_Static_assert",
|
|
"_Thread_local",
|
|
};
|
|
|
|
size_t i;
|
|
const char *s = f->f.name.str;
|
|
for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); i++) {
|
|
if (!strcmp(s, reserved[i])) {
|
|
return strf(&buf, "_%s", s);
|
|
}
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
static void union_block(struct strings *s, struct field *f) {
|
|
static struct str buf = STR_INIT;
|
|
str_add(&s->ftab, "\t", -1);
|
|
set_member(&s->set, f, "p.p", s->ftab.str, strf(&buf, "%s%s", s->var.str, field_name(f)));
|
|
get_member(&s->get, f, "p.p", s->ftab.str, strf(&buf, "%s%s", s->var.str, field_name(f)));
|
|
str_addf(&s->set, "%sbreak;\n", s->ftab.str);
|
|
str_addf(&s->get, "%sbreak;\n", s->ftab.str);
|
|
str_setlen(&s->ftab, s->ftab.len-1);
|
|
}
|
|
|
|
static int in_union(struct field *f) {
|
|
return f->f.discriminantValue != 0xFFFF;
|
|
}
|
|
|
|
static void union_cases(struct strings *s, struct node *n, struct field *first_field, int mask) {
|
|
struct field *f, *u = NULL;
|
|
|
|
for (f = first_field; f < n->fields + capn_len(n->n._struct.fields) && in_union(f); f++) {
|
|
|
|
if (f->f.which != Field_slot)
|
|
continue;
|
|
if (f->v.ptrval.type || f->v.intval)
|
|
continue;
|
|
if ((mask & (1 << f->v.t.which)) == 0)
|
|
continue;
|
|
|
|
u = f;
|
|
str_addf(&s->set, "%scase %s_%s:\n", s->ftab.str, n->name.str, field_name(f));
|
|
str_addf(&s->get, "%scase %s_%s:\n", s->ftab.str, n->name.str, field_name(f));
|
|
}
|
|
|
|
if (u)
|
|
union_block(s, u);
|
|
}
|
|
|
|
static void declare_slot(struct strings *s, struct field *f) {
|
|
switch (f->v.t.which) {
|
|
case Type__void:
|
|
break;
|
|
case Type__bool:
|
|
str_addf(&s->decl, "%s%s %s : 1;\n", s->dtab.str, f->v.tname, field_name(f));
|
|
break;
|
|
default:
|
|
str_addf(&s->decl, "%s%s %s;\n", s->dtab.str, f->v.tname, field_name(f));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void define_group(struct strings *s, struct node *n, const char *group_name);
|
|
|
|
static void do_union(struct strings *s, struct node *n, struct field *first_field, const char *union_name) {
|
|
int tagoff = 2 * n->n._struct.discriminantOffset;
|
|
struct field *f;
|
|
static struct str tag = STR_INIT;
|
|
struct str enums = STR_INIT;
|
|
|
|
str_reset(&tag);
|
|
|
|
if (union_name) {
|
|
str_addf(&tag, "%.*s_which", s->var.len - 1, s->var.str);
|
|
str_addf(&enums, "enum %s_which {", n->name.str);
|
|
str_addf(&s->decl, "%senum %s_which %s_which;\n", s->dtab.str, n->name.str, union_name);
|
|
str_addf(&s->get, "%s%s = (enum %s_which) capn_read16(p.p, %d);\n",
|
|
s->ftab.str, tag.str, n->name.str, tagoff);
|
|
} else {
|
|
str_addf(&tag, "%swhich", s->var.str);
|
|
str_addf(&enums, "enum %s_which {", n->name.str);
|
|
str_addf(&s->decl, "%senum %s_which which;\n", s->dtab.str, n->name.str);
|
|
str_addf(&s->get, "%s%s = (enum %s_which) capn_read16(p.p, %d);\n",
|
|
s->ftab.str, tag.str, n->name.str, tagoff);
|
|
}
|
|
|
|
str_addf(&s->set, "%scapn_write16(p.p, %d, %s);\n", s->ftab.str, tagoff, tag.str);
|
|
str_addf(&s->set, "%sswitch (%s) {\n", s->ftab.str, tag.str);
|
|
str_addf(&s->get, "%sswitch (%s) {\n", s->ftab.str, tag.str);
|
|
|
|
/* if we have a bunch of the same C type with zero defaults, we
|
|
* only need to emit one switch block as the layout will line up
|
|
* in the C union */
|
|
union_cases(s, n, first_field, (1 << Type__bool));
|
|
union_cases(s, n, first_field, (1 << Type_int8) | (1 << Type_uint8));
|
|
union_cases(s, n, first_field, (1 << Type_int16) | (1 << Type_uint16) | (1 << Type__enum));
|
|
union_cases(s, n, first_field, (1 << Type_int32) | (1 << Type_uint32) | (1 << Type_float32));
|
|
union_cases(s, n, first_field, (1 << Type_int64) | (1 << Type_uint64) | (1 << Type_float64));
|
|
union_cases(s, n, first_field, (1 << Type_text));
|
|
union_cases(s, n, first_field, (1 << Type_data));
|
|
union_cases(s, n, first_field, (1 << Type__struct) | (1 << Type__interface) | (1 << Type_anyPointer) | (1 << Type__list));
|
|
|
|
str_addf(&s->decl, "%sunion {\n", s->dtab.str);
|
|
str_add(&s->dtab, "\t", -1);
|
|
|
|
/* when we have defaults or groups we have to emit each case seperately */
|
|
for (f = first_field; f < n->fields + capn_len(n->n._struct.fields) && in_union(f); f++) {
|
|
if (f > first_field) {
|
|
str_addf(&enums, ",");
|
|
}
|
|
|
|
str_addf(&enums, "\n\t%s_%s = %d", n->name.str, field_name(f), f->f.discriminantValue);
|
|
|
|
switch (f->f.which) {
|
|
case Field_group:
|
|
str_addf(&s->get, "%scase %s_%s:\n", s->ftab.str, n->name.str, field_name(f));
|
|
str_addf(&s->set, "%scase %s_%s:\n", s->ftab.str, n->name.str, field_name(f));
|
|
str_add(&s->ftab, "\t", -1);
|
|
define_group(s, f->group, field_name(f));
|
|
str_addf(&s->get, "%sbreak;\n", s->ftab.str);
|
|
str_addf(&s->set, "%sbreak;\n", s->ftab.str);
|
|
str_setlen(&s->ftab, s->ftab.len-1);
|
|
break;
|
|
|
|
case Field_slot:
|
|
declare_slot(s, f);
|
|
if (f->v.ptrval.type || f->v.intval) {
|
|
str_addf(&s->get, "%scase %s_%s:\n", s->ftab.str, n->name.str, field_name(f));
|
|
str_addf(&s->set, "%scase %s_%s:\n", s->ftab.str, n->name.str, field_name(f));
|
|
union_block(s, f);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
str_setlen(&s->dtab, s->dtab.len - 1);
|
|
|
|
if (union_name) {
|
|
str_addf(&s->decl, "%s} %s;\n", s->dtab.str, union_name);
|
|
} else {
|
|
str_addf(&s->decl, "%s};\n", s->dtab.str);
|
|
}
|
|
|
|
str_addf(&s->get, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, s->ftab.str, s->ftab.str);
|
|
str_addf(&s->set, "%sdefault:\n%s\tbreak;\n%s}\n", s->ftab.str, s->ftab.str, s->ftab.str);
|
|
|
|
str_addf(&enums, "\n};\n");
|
|
str_add(&s->enums, enums.str, enums.len);
|
|
str_release(&enums);
|
|
}
|
|
|
|
static void define_field(struct strings *s, struct field *f) {
|
|
static struct str buf = STR_INIT;
|
|
|
|
switch (f->f.which) {
|
|
case Field_slot:
|
|
declare_slot(s, f);
|
|
set_member(&s->set, f, "p.p", s->ftab.str, strf(&buf, "%s%s", s->var.str, field_name(f)));
|
|
get_member(&s->get, f, "p.p", s->ftab.str, strf(&buf, "%s%s", s->var.str, field_name(f)));
|
|
break;
|
|
|
|
case Field_group:
|
|
define_group(s, f->group, field_name(f));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void define_group(struct strings *s, struct node *n, const char *group_name) {
|
|
struct field *f;
|
|
int flen = capn_len(n->n._struct.fields);
|
|
int ulen = n->n._struct.discriminantCount;
|
|
/* named union is where all group members are in the union */
|
|
int named_union = (group_name && ulen == flen && ulen > 0);
|
|
int named_struct = (group_name && !named_union);
|
|
|
|
if (named_struct) {
|
|
str_addf(&s->decl, "%sstruct {\n", s->dtab.str);
|
|
str_add(&s->dtab, "\t", 1);
|
|
}
|
|
|
|
if (group_name) {
|
|
str_addf(&s->var, "%s.", group_name);
|
|
}
|
|
|
|
for (f = n->fields; f < n->fields + flen; f++) {
|
|
decode_value(&f->v, f->f.slot.type, f->f.slot.defaultValue, NULL);
|
|
}
|
|
|
|
/* fields before the union members */
|
|
for (f = n->fields; f < n->fields + flen && !in_union(f); f++) {
|
|
define_field(s, f);
|
|
}
|
|
|
|
if (ulen > 0) {
|
|
do_union(s, n, f, named_union ? group_name : NULL);
|
|
|
|
while (f < n->fields + flen && in_union(f))
|
|
f++;
|
|
|
|
/* fields after the unnamed union */
|
|
for (;f < n->fields + flen; f++) {
|
|
define_field(s, f);
|
|
}
|
|
}
|
|
|
|
if (named_struct) {
|
|
str_setlen(&s->dtab, s->dtab.len-1);
|
|
str_addf(&s->decl, "%s} %s;\n", s->dtab.str, group_name);
|
|
}
|
|
|
|
if (group_name) {
|
|
str_setlen(&s->var, s->var.len - strlen(group_name) - 1);
|
|
}
|
|
}
|
|
|
|
static void define_struct(struct node *n) {
|
|
static struct strings s;
|
|
|
|
str_reset(&s.dtab);
|
|
str_reset(&s.ftab);
|
|
str_reset(&s.get);
|
|
str_reset(&s.set);
|
|
str_reset(&s.enums);
|
|
str_reset(&s.decl);
|
|
str_reset(&s.var);
|
|
|
|
str_add(&s.dtab, "\t", -1);
|
|
str_add(&s.ftab, "\t", -1);
|
|
str_add(&s.var, "s->", -1);
|
|
|
|
define_group(&s, n, NULL);
|
|
|
|
str_add(&HDR, s.enums.str, s.enums.len);
|
|
|
|
str_addf(&HDR, "\nstruct %s {\n", n->name.str);
|
|
str_add(&HDR, s.decl.str, s.decl.len);
|
|
str_addf(&HDR, "};\n");
|
|
|
|
str_addf(&SRC, "\n%s_ptr new_%s(struct capn_segment *s) {\n", n->name.str, n->name.str);
|
|
str_addf(&SRC, "\t%s_ptr p;\n", n->name.str);
|
|
str_addf(&SRC, "\tp.p = capn_new_struct(s, %d, %d);\n", 8*n->n._struct.dataWordCount, n->n._struct.pointerCount);
|
|
str_addf(&SRC, "\treturn p;\n");
|
|
str_addf(&SRC, "}\n");
|
|
|
|
str_addf(&SRC, "%s_list new_%s_list(struct capn_segment *s, int len) {\n", n->name.str, n->name.str);
|
|
str_addf(&SRC, "\t%s_list p;\n", n->name.str);
|
|
str_addf(&SRC, "\tp.p = capn_new_list(s, len, %d, %d);\n", 8*n->n._struct.dataWordCount, n->n._struct.pointerCount);
|
|
str_addf(&SRC, "\treturn p;\n");
|
|
str_addf(&SRC, "}\n");
|
|
|
|
str_addf(&SRC, "void read_%s(struct %s *s, %s_ptr p) {\n", n->name.str, n->name.str, n->name.str);
|
|
str_addf(&SRC, "\tcapn_resolve(&p.p);\n");
|
|
str_add(&SRC, s.get.str, s.get.len);
|
|
str_addf(&SRC, "}\n");
|
|
|
|
str_addf(&SRC, "void write_%s(const struct %s *s, %s_ptr p) {\n", n->name.str, n->name.str, n->name.str);
|
|
str_addf(&SRC, "\tcapn_resolve(&p.p);\n");
|
|
str_add(&SRC, s.set.str, s.set.len);
|
|
str_addf(&SRC, "}\n");
|
|
|
|
str_addf(&SRC, "void get_%s(struct %s *s, %s_list l, int i) {\n", n->name.str, n->name.str, n->name.str);
|
|
str_addf(&SRC, "\t%s_ptr p;\n", n->name.str);
|
|
str_addf(&SRC, "\tp.p = capn_getp(l.p, i, 0);\n");
|
|
str_addf(&SRC, "\tread_%s(s, p);\n", n->name.str);
|
|
str_addf(&SRC, "}\n");
|
|
|
|
str_addf(&SRC, "void set_%s(const struct %s *s, %s_list l, int i) {\n", n->name.str, n->name.str, n->name.str);
|
|
str_addf(&SRC, "\t%s_ptr p;\n", n->name.str);
|
|
str_addf(&SRC, "\tp.p = capn_getp(l.p, i, 0);\n");
|
|
str_addf(&SRC, "\twrite_%s(s, p);\n", n->name.str);
|
|
str_addf(&SRC, "}\n");
|
|
}
|
|
|
|
#if 0
|
|
/* Commenting out interfaces until the RPC protocol has been spec'd */
|
|
static int find_offset(struct str *v, int inc, uint64_t mask) {
|
|
int i, j;
|
|
union {uint64_t u; char c[8];} umask;
|
|
umask.u = capn_flip64(mask);
|
|
for (i = 0; i < v->len*8; i += inc) {
|
|
for (j = i; j < i+inc; j++) {
|
|
if (((uint8_t*)v->str)[j/8] & (1 << (j%8))) {
|
|
goto loop;
|
|
}
|
|
}
|
|
|
|
for (j = i; j < i+inc; j++) {
|
|
((uint8_t*)v->str)[j/8] |= 1 << (j%8);
|
|
}
|
|
|
|
return j/inc;
|
|
loop:
|
|
continue;
|
|
}
|
|
str_add(v, umask.c, 8);
|
|
return (v->len-8)/inc;
|
|
}
|
|
|
|
static void define_method(struct node *iface, int ord) {
|
|
static struct str buf = STR_INIT;
|
|
struct member *mbrs;
|
|
struct InterfaceNode_Method method;
|
|
int i, ptrs = 0, datasz;
|
|
|
|
get_InterfaceNode_Method(&method, iface->i.methods, ord);
|
|
mbrs = calloc(method.params.p.len, sizeof(*mbrs));
|
|
|
|
str_reset(&buf);
|
|
|
|
for (i = 0; i < method.params.p.len; i++) {
|
|
struct InterfaceNode_Method_Param param;
|
|
struct member *m = &mbrs[i];
|
|
|
|
get_InterfaceNode_Method_Param(¶m, method.params, i);
|
|
decode_value(&m->v, param.type, param.defaultValue, NULL);
|
|
m->m.name = param.name;
|
|
m->m.annotations = param.annotations;
|
|
m->m.ordinal = i;
|
|
|
|
switch (m->v.t.body_tag) {
|
|
case Type__void:
|
|
break;
|
|
case Type__bool:
|
|
m->f.offset = find_offset(&buf, 1, 1);
|
|
break;
|
|
case Type_int8:
|
|
case Type_uint8:
|
|
m->f.offset = find_offset(&buf, 8, 0xFF);
|
|
break;
|
|
case Type_int16:
|
|
case Type_uint16:
|
|
case Type__enum:
|
|
m->f.offset = find_offset(&buf, 16, 0xFFFF);
|
|
break;
|
|
case Type_int32:
|
|
case Type_uint32:
|
|
case Type_float32:
|
|
m->f.offset = find_offset(&buf, 32, 0xFFFFFFFFu);
|
|
break;
|
|
case Type_int64:
|
|
case Type_uint64:
|
|
case Type_float64:
|
|
m->f.offset = find_offset(&buf, 64, ~((uint64_t) 0));
|
|
break;
|
|
case Type_text:
|
|
case Type_data:
|
|
case Type__list:
|
|
case Type__struct:
|
|
case Type__interface:
|
|
case Type_anyPointer:
|
|
m->f.offset = ptrs++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
datasz = buf.len;
|
|
|
|
|
|
/* write function to initiate a call */
|
|
|
|
str_addf(&HDR, "\nint write_%s_%s(struct capn_msg*", iface->name.str, method.name.str);
|
|
str_addf(&SRC, "\nint write_%s_%s(struct capn_msg *m", iface->name.str, method.name.str);
|
|
for (i = 0; i < method.params.p.len; i++) {
|
|
struct member *m = &mbrs[i];
|
|
str_addf(&HDR, ", %s %s", m->v.tname, m->m.name.str);
|
|
str_addf(&SRC, ", %s a%d", m->v.tname, i);
|
|
}
|
|
str_addf(&HDR, ");\n");
|
|
str_addf(&SRC, ") {\n");
|
|
|
|
str_addf(&SRC, "\tint err = 0;\n");
|
|
str_addf(&SRC, "\tm->method = %d;\n", ord);
|
|
str_addf(&SRC, "\tm->iface = ((uint64_t) %#xu << 32) | %#xu;\n", (uint32_t) (iface->n.id >> 32), (uint32_t) iface->n.id);
|
|
|
|
if (datasz || ptrs) {
|
|
str_addf(&SRC, "\tm->args = capn_new_struct(m->seg, %d, %d);\n", datasz, ptrs);
|
|
} else {
|
|
g_nullused = 1;
|
|
str_addf(&SRC, "\tm->args = capn_null;\n");
|
|
}
|
|
|
|
for (i = 0; i < method.params.p.len; i++) {
|
|
set_member(&mbrs[i], "m->args", "\t", strf(&buf, "a%d", i));
|
|
}
|
|
|
|
str_addf(&SRC, "\treturn err;\n");
|
|
str_addf(&SRC, "}\n");
|
|
|
|
|
|
/* read function to handle a call */
|
|
|
|
if (datasz || ptrs) {
|
|
str_addf(&HDR, "void read_%s_%s(struct capn_msg*", iface->name.str, method.name.str);
|
|
str_addf(&SRC, "void read_%s_%s(struct capn_msg *m", iface->name.str, method.name.str);
|
|
for (i = 0; i < method.params.p.len; i++) {
|
|
struct member *m = &mbrs[i];
|
|
str_addf(&HDR, ", %s *%s", m->v.tname, m->m.name.str);
|
|
str_addf(&SRC, ", %s *a%d", m->v.tname, i);
|
|
}
|
|
str_addf(&HDR, ");\n");
|
|
str_addf(&SRC, ") {\n");
|
|
|
|
for (i = 0; i < method.params.p.len; i++) {
|
|
get_member(&mbrs[i], "m->args", "\t", strf(&buf, "*a%d", i));
|
|
}
|
|
|
|
str_addf(&SRC, "}\n");
|
|
}
|
|
|
|
free(mbrs);
|
|
}
|
|
#endif
|
|
|
|
static void declare(struct node *file_node, const char *format, int num) {
|
|
struct node *n;
|
|
str_addf(&HDR, "\n");
|
|
for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) {
|
|
if (n->n.which == Node__struct && !n->n._struct.isGroup) {
|
|
switch (num) {
|
|
case 3:
|
|
str_addf(&HDR, format, n->name.str, n->name.str, n->name.str);
|
|
break;
|
|
case 2:
|
|
str_addf(&HDR, format, n->name.str, n->name.str);
|
|
break;
|
|
case 1:
|
|
str_addf(&HDR, format, n->name.str);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
struct capn capn;
|
|
CodeGeneratorRequest_ptr root;
|
|
struct CodeGeneratorRequest req;
|
|
struct node *file_node, *n;
|
|
struct node *all_files = NULL, *all_structs = NULL;
|
|
int i, j;
|
|
|
|
if (capn_init_fp(&capn, stdin, 0)) {
|
|
fprintf(stderr, "failed to read schema from stdin\n");
|
|
return -1;
|
|
}
|
|
|
|
g_valseg.data = calloc(1, capn.seglist->len);
|
|
g_valseg.cap = capn.seglist->len;
|
|
|
|
root.p = capn_getp(capn_root(&capn), 0, 1);
|
|
read_CodeGeneratorRequest(&req, root);
|
|
|
|
for (i = 0; i < capn_len(req.nodes); i++) {
|
|
n = calloc(1, sizeof(*n));
|
|
get_Node(&n->n, req.nodes, i);
|
|
insert_node(n);
|
|
|
|
switch (n->n.which) {
|
|
case Node_file:
|
|
n->next = all_files;
|
|
all_files = n;
|
|
break;
|
|
|
|
case Node__struct:
|
|
n->next = all_structs;
|
|
all_structs = n;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (n = all_structs; n != NULL; n = n->next) {
|
|
n->fields = calloc(capn_len(n->n._struct.fields), sizeof(n->fields[0]));
|
|
for (j = 0; j < capn_len(n->n._struct.fields); j++) {
|
|
decode_field(n->fields, n->n._struct.fields, j);
|
|
}
|
|
}
|
|
|
|
for (n = all_files; n != NULL; n = n->next) {
|
|
struct str b = STR_INIT;
|
|
|
|
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(nest.id);
|
|
if (nn) {
|
|
resolve_names(&b, nn, nest.name, n);
|
|
}
|
|
}
|
|
|
|
str_release(&b);
|
|
}
|
|
|
|
for (i = 0; i < capn_len(req.requestedFiles); i++) {
|
|
struct CodeGeneratorRequest_RequestedFile file_req;
|
|
static struct str b = STR_INIT;
|
|
char *p;
|
|
FILE *srcf, *hdrf;
|
|
|
|
g_valc = 0;
|
|
g_valseg.len = 0;
|
|
g_val0used = 0;
|
|
g_nullused = 0;
|
|
capn_init_malloc(&g_valcapn);
|
|
capn_append_segment(&g_valcapn, &g_valseg);
|
|
|
|
get_CodeGeneratorRequest_RequestedFile(&file_req, req.requestedFiles, i);
|
|
file_node = find_node(file_req.id);
|
|
if (file_node == NULL) {
|
|
fprintf(stderr, "invalid file_node specified\n");
|
|
exit(2);
|
|
}
|
|
|
|
str_reset(&HDR);
|
|
str_reset(&SRC);
|
|
|
|
str_addf(&HDR, "#ifndef CAPN_%X%X\n", (uint32_t) (file_node->n.id >> 32), (uint32_t) file_node->n.id);
|
|
str_addf(&HDR, "#define CAPN_%X%X\n", (uint32_t) (file_node->n.id >> 32), (uint32_t) file_node->n.id);
|
|
str_addf(&HDR, "/* AUTO GENERATED - DO NOT EDIT */\n");
|
|
str_addf(&HDR, "#include <capn.h>\n\n");
|
|
str_addf(&HDR, "#if CAPN_VERSION != 1\n");
|
|
str_addf(&HDR, "#error \"version mismatch between capn.h and generated code\"\n");
|
|
str_addf(&HDR, "#endif\n\n");
|
|
|
|
for (j = 0; j < capn_len(file_req.imports); j++) {
|
|
struct CodeGeneratorRequest_RequestedFile_Import im;
|
|
get_CodeGeneratorRequest_RequestedFile_Import(&im, file_req.imports, j);
|
|
str_addf(&HDR, "#include \"%s.h\"\n", im.name.str);
|
|
}
|
|
|
|
str_addf(&HDR, "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
|
|
|
|
declare(file_node, "struct %s;\n", 1);
|
|
declare(file_node, "typedef struct {capn_ptr p;} %s_ptr;\n", 1);
|
|
declare(file_node, "typedef struct {capn_ptr p;} %s_list;\n", 1);
|
|
|
|
for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) {
|
|
if (n->n.which == Node__enum) {
|
|
define_enum(n);
|
|
}
|
|
}
|
|
|
|
for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) {
|
|
if (n->n.which == Node__const) {
|
|
define_const(n);
|
|
}
|
|
}
|
|
|
|
for (n = file_node->file_nodes; n != NULL; n = n->next_file_node) {
|
|
if (n->n.which == Node__struct && !n->n._struct.isGroup) {
|
|
define_struct(n);
|
|
}
|
|
}
|
|
|
|
declare(file_node, "%s_ptr new_%s(struct capn_segment*);\n", 2);
|
|
declare(file_node, "%s_list new_%s_list(struct capn_segment*, int len);\n", 2);
|
|
declare(file_node, "void read_%s(struct %s*, %s_ptr);\n", 3);
|
|
declare(file_node, "void write_%s(const struct %s*, %s_ptr);\n", 3);
|
|
declare(file_node, "void get_%s(struct %s*, %s_list, int i);\n", 3);
|
|
declare(file_node, "void set_%s(const struct %s*, %s_list, int i);\n", 3);
|
|
|
|
str_addf(&HDR, "\n#ifdef __cplusplus\n}\n#endif\n#endif\n");
|
|
|
|
/* write out the header */
|
|
|
|
hdrf = fopen(strf(&b, "%s.h", file_node->n.displayName.str), "w");
|
|
if (!hdrf) {
|
|
fprintf(stderr, "failed to open %s: %s\n", b.str, strerror(errno));
|
|
exit(2);
|
|
}
|
|
fwrite(HDR.str, 1, HDR.len, hdrf);
|
|
fclose(hdrf);
|
|
|
|
/* write out the source */
|
|
|
|
srcf = fopen(strf(&b, "%s.c", file_node->n.displayName.str), "w");
|
|
if (!srcf) {
|
|
fprintf(stderr, "failed to open %s: %s\n", b.str, strerror(errno));
|
|
exit(2);
|
|
}
|
|
p = strrchr(file_node->n.displayName.str, '/');
|
|
fprintf(srcf, "#include \"%s.h\"\n", p ? p+1 : file_node->n.displayName.str);
|
|
fprintf(srcf, "/* AUTO GENERATED - DO NOT EDIT */\n");
|
|
|
|
if (g_val0used)
|
|
fprintf(srcf, "static const capn_text capn_val0 = {0,\"\"};\n");
|
|
if (g_nullused)
|
|
fprintf(srcf, "static const capn_ptr capn_null = {CAPN_NULL};\n");
|
|
|
|
if (g_valseg.len > 8) {
|
|
size_t k;
|
|
fprintf(srcf, "static const uint8_t capn_buf[%lu] = {", g_valseg.len-8);
|
|
for (k = 8; k < g_valseg.len; k++) {
|
|
if (k > 8)
|
|
fprintf(srcf, ",");
|
|
if ((k % 8) == 0)
|
|
fprintf(srcf, "\n\t");
|
|
fprintf(srcf, "%u", ((uint8_t*)g_valseg.data)[k]);
|
|
}
|
|
fprintf(srcf, "\n};\n");
|
|
|
|
fprintf(srcf, "static const struct capn_segment capn_seg = {{0},0,0,0,(char*)&capn_buf[0],%lu,%lu};\n",
|
|
g_valseg.len-8, g_valseg.len-8);
|
|
}
|
|
|
|
fwrite(SRC.str, 1, SRC.len, srcf);
|
|
fclose(srcf);
|
|
|
|
capn_free(&g_valcapn);
|
|
}
|
|
|
|
return 0;
|
|
}
|