subcompiler now outputs struct defns, get, set, read, write funcs
This commit is contained in:
parent
8bb9759e8c
commit
8db142a9a0
5 changed files with 815 additions and 50 deletions
2
Makefile
2
Makefile
|
|
@ -14,7 +14,7 @@ clean:
|
|||
capn.so: capn-malloc.o capn-stream.o capn.o
|
||||
$(CC) -shared $(LDFLAGS) $^ -o $@
|
||||
|
||||
capnpc-c: compiler/capnpc-c.o compiler/schema.capnp.o capn.so
|
||||
capnpc-c: compiler/capnpc-c.o compiler/schema.capnp.o compiler/str.o capn.so
|
||||
$(CC) $(LDFLAGS) $^ -o $@
|
||||
|
||||
test: capn-test
|
||||
|
|
|
|||
|
|
@ -1,34 +1,603 @@
|
|||
#include "schema.capnp.h"
|
||||
#include "str.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct scope {
|
||||
struct node {
|
||||
struct capn_tree hdr;
|
||||
struct scope *enclosing;
|
||||
capn_text name;
|
||||
uint64_t id;
|
||||
struct Node n;
|
||||
struct node *next;
|
||||
struct node *first_child, *next_child;
|
||||
struct str name;
|
||||
union {
|
||||
struct StructNode structNode;
|
||||
struct EnumNode enumNode;
|
||||
struct InterfaceNode interfaceNode;
|
||||
struct ConstNode constNode;
|
||||
struct FileNode fileNode;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct scope *find_scope(struct scope *s, uint64_t id) {
|
||||
while (s && s->id != id) {
|
||||
s = (struct scope*) s->hdr.link[s->id < id];
|
||||
static struct node *g_files;
|
||||
static FILE *HDR, *SRC;
|
||||
|
||||
static struct capn_tree *g_node_tree;
|
||||
|
||||
struct node *find_node(uint64_t id) {
|
||||
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 %#llx\n", id);
|
||||
exit(2);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
struct capn_tree *insert_scope(struct capn_tree *root, struct scope *s) {
|
||||
struct capn_tree **x = &root;
|
||||
static void insert_node(struct node *s) {
|
||||
struct capn_tree **x = &g_node_tree;
|
||||
while (*x) {
|
||||
s->hdr.parent = *x;
|
||||
x = &(*x)->link[((struct scope*)*x)->id < s->id];
|
||||
x = &(*x)->link[((struct node*)*x)->n.id < s->n.id];
|
||||
}
|
||||
*x = &s->hdr;
|
||||
return capn_tree_insert(root, &s->hdr);
|
||||
g_node_tree = capn_tree_insert(g_node_tree, &s->hdr);
|
||||
}
|
||||
|
||||
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 = n->n.nestedNodes.p.len-1; i >= 0; i--) {
|
||||
struct Node_NestedNode nest;
|
||||
get_Node_NestedNode(&nest, n->n.nestedNodes, i);
|
||||
resolve_names(b, find_node(nest.id), nest.name, file);
|
||||
}
|
||||
|
||||
n->next_child = file->first_child;
|
||||
file->first_child = n;
|
||||
str_setlen(b, sz);
|
||||
}
|
||||
|
||||
static void define_enum(struct node *n) {
|
||||
int i;
|
||||
|
||||
fprintf(HDR, "\nenum %s {", n->name.str);
|
||||
for (i = 0; i < n->u.enumNode.enumerants.p.len; i++) {
|
||||
struct EnumNode_Enumerant ee;
|
||||
get_EnumNode_Enumerant(&ee, n->u.enumNode.enumerants, i);
|
||||
if (i) {
|
||||
fprintf(HDR, ",");
|
||||
}
|
||||
fprintf(HDR, "\n\t%s_%s = %d", n->name.str, ee.name.str, i);
|
||||
}
|
||||
fprintf(HDR, "\n};\n");
|
||||
}
|
||||
|
||||
struct member {
|
||||
unsigned int is_valid : 1;
|
||||
struct StructNode_Member m;
|
||||
struct StructNode_Field f;
|
||||
struct StructNode_Union u;
|
||||
struct Type t;
|
||||
struct Value v;
|
||||
struct node *type;
|
||||
struct Type list;
|
||||
struct member *mbrs;
|
||||
int idx;
|
||||
};
|
||||
|
||||
static void set_member(FILE *f, struct member *m, const char *tab, const char *var) {
|
||||
if (m->t.body_tag == Type_voidType)
|
||||
return;
|
||||
|
||||
fputs(tab, f);
|
||||
|
||||
switch (m->t.body_tag) {
|
||||
case Type_voidType:
|
||||
break;
|
||||
case Type_boolType:
|
||||
fprintf(f, "err = err || capn_write1(p.p, %d, %s);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_int8Type:
|
||||
fprintf(f, "err = err || capn_write8(p.p, %d, (uint8_t) %s);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_int16Type:
|
||||
case Type_enumType:
|
||||
fprintf(f, "err = err || capn_write16(p.p, %d, (uint16_t) %s);\n", 2*m->f.offset, var);
|
||||
break;
|
||||
case Type_int32Type:
|
||||
fprintf(f, "err = err || capn_write32(p.p, %d, (uint32_t) %s);\n", 4*m->f.offset, var);
|
||||
break;
|
||||
case Type_int64Type:
|
||||
fprintf(f, "err = err || capn_write64(p.p, %d, (uint64_t) %s);\n", 8*m->f.offset, var);
|
||||
break;
|
||||
case Type_uint8Type:
|
||||
fprintf(f, "err = err || capn_write8(p.p, %d, %s);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_uint16Type:
|
||||
fprintf(f, "err = err || capn_write16(p.p, %d, %s);\n", 2*m->f.offset, var);
|
||||
break;
|
||||
case Type_uint32Type:
|
||||
fprintf(f, "err = err || capn_write32(p.p, %d, %s);\n", 4*m->f.offset, var);
|
||||
break;
|
||||
case Type_uint64Type:
|
||||
fprintf(f, "err = err || capn_write64(p.p, %d, %s);\n", 8*m->f.offset, var);
|
||||
break;
|
||||
case Type_float32Type:
|
||||
fprintf(f, "err = err || capn_write_float(p.p, %d, %s, 0.0f);\n", 4*m->f.offset, var);
|
||||
break;
|
||||
case Type_float64Type:
|
||||
fprintf(f, "err = err || capn_write_double(p.p, %d, %s, 0.0);\n", 4*m->f.offset, var);
|
||||
break;
|
||||
case Type_textType:
|
||||
fprintf(f, "err = err || capn_set_text(p.p, %d, %s);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_dataType:
|
||||
fprintf(f, "err = err || capn_set_data(p.p, %d, %s);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
fprintf(f, "err = err || capn_setp(p.p, %d, %s.p);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_objectType:
|
||||
fprintf(f, "err = err || capn_setp(p.p, %d, %s);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_listType:
|
||||
switch (m->list.body_tag) {
|
||||
case Type_boolType:
|
||||
case Type_int8Type:
|
||||
case Type_uint8Type:
|
||||
case Type_int16Type:
|
||||
case Type_uint16Type:
|
||||
case Type_enumType:
|
||||
case Type_int32Type:
|
||||
case Type_uint32Type:
|
||||
case Type_int64Type:
|
||||
case Type_uint64Type:
|
||||
case Type_float32Type:
|
||||
case Type_float64Type:
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
fprintf(f, "err = err || capn_setp(p.p, %d, %s.p);\n", m->f.offset, var);
|
||||
break;
|
||||
case Type_voidType:
|
||||
case Type_textType:
|
||||
case Type_dataType:
|
||||
case Type_objectType:
|
||||
case Type_listType:
|
||||
fprintf(f, "err = err || capn_setp(p.p, %d, %s);\n", m->f.offset, var);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_member(FILE *f, struct member *m, const char *tab, const char *var) {
|
||||
if (m->t.body_tag == Type_voidType)
|
||||
return;
|
||||
|
||||
fputs(tab, f);
|
||||
fputs(var, f);
|
||||
|
||||
switch (m->t.body_tag) {
|
||||
case Type_voidType:
|
||||
break;
|
||||
case Type_boolType:
|
||||
fprintf(f, " = (capn_read8(p.p, %d) & %d) != 0;\n",
|
||||
m->f.offset/8, 1 << (m->f.offset%8));
|
||||
break;
|
||||
case Type_int8Type:
|
||||
fprintf(f, " = (int8_t) capn_read8(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_int16Type:
|
||||
fprintf(f, " = (int16_t) capn_read16(p.p, %d);\n", 2*m->f.offset);
|
||||
break;
|
||||
case Type_int32Type:
|
||||
fprintf(f, " = (int32_t) capn_read32(p.p, %d);\n", 4*m->f.offset);
|
||||
break;
|
||||
case Type_int64Type:
|
||||
fprintf(f, " = (int64_t) capn_read64(p.p, %d);\n", 8*m->f.offset);
|
||||
break;
|
||||
case Type_uint8Type:
|
||||
fprintf(f, " = capn_read8(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_uint16Type:
|
||||
fprintf(f, " = capn_read16(p.p, %d);\n", 2*m->f.offset);
|
||||
break;
|
||||
case Type_uint32Type:
|
||||
fprintf(f, " = capn_read32(p.p, %d);\n", 4*m->f.offset);
|
||||
break;
|
||||
case Type_uint64Type:
|
||||
fprintf(f, " = capn_read64(p.p, %d);\n", 8*m->f.offset);
|
||||
break;
|
||||
case Type_float32Type:
|
||||
fprintf(f, " = capn_read_float(p.p, %d, 0.0f);\n", 4*m->f.offset);
|
||||
break;
|
||||
case Type_float64Type:
|
||||
fprintf(f, " = capn_read_double(p.p, %d, 0.0);\n", 8*m->f.offset);
|
||||
break;
|
||||
case Type_textType:
|
||||
fprintf(f, " = capn_get_text(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_dataType:
|
||||
fprintf(f, " = capn_get_data(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_enumType:
|
||||
fprintf(f, " = (enum %s) capn_read16(p.p, %d);\n", m->type->name.str, 2*m->f.offset);
|
||||
break;
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
fprintf(f, ".p = capn_getp(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_objectType:
|
||||
fprintf(f, " = capn_getp(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_listType:
|
||||
switch (m->list.body_tag) {
|
||||
case Type_boolType:
|
||||
case Type_int8Type:
|
||||
case Type_uint8Type:
|
||||
case Type_int16Type:
|
||||
case Type_uint16Type:
|
||||
case Type_enumType:
|
||||
case Type_int32Type:
|
||||
case Type_uint32Type:
|
||||
case Type_int64Type:
|
||||
case Type_uint64Type:
|
||||
case Type_float32Type:
|
||||
case Type_float64Type:
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
fprintf(f, ".p = capn_getp(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
case Type_voidType:
|
||||
case Type_textType:
|
||||
case Type_dataType:
|
||||
case Type_objectType:
|
||||
case Type_listType:
|
||||
fprintf(f, " = capn_getp(p.p, %d);\n", m->f.offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void union_cases(struct node *n, struct member *m, int set, int mask) {
|
||||
static struct str buf = STR_INIT;
|
||||
struct member *u = NULL;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < m->u.members.p.len; j++) {
|
||||
if (mask & (1 << m->mbrs[j].t.body_tag)) {
|
||||
u = &m->mbrs[j];
|
||||
fprintf(SRC, "\tcase %s_%s:\n", n->name.str, u->m.name.str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!u)
|
||||
return;
|
||||
|
||||
str_reset(&buf);
|
||||
str_addf(&buf, "s->%s.%s", m->m.name.str, u->m.name.str);
|
||||
|
||||
if (u->t.body_tag == Type_voidType) {
|
||||
/* nothing to do */
|
||||
} else if (set) {
|
||||
set_member(SRC, u, "\t\t", buf.str);
|
||||
} else {
|
||||
get_member(SRC, u, "\t\t", buf.str);
|
||||
}
|
||||
|
||||
fprintf(SRC, "\t\tbreak;\n");
|
||||
}
|
||||
|
||||
static void do_union(struct node *n, struct member *m, int set) {
|
||||
if (set) {
|
||||
fprintf(SRC, "\terr = err || capn_write16(p.p, %d, s->%s_tag);\n",
|
||||
2*m->u.discriminantOffset, m->m.name.str);
|
||||
} else {
|
||||
fprintf(SRC, "\ts->%s_tag = (enum %s_%s) capn_read16(p.p, %d);\n",
|
||||
m->m.name.str, n->name.str, m->m.name.str, 2*m->u.discriminantOffset);
|
||||
}
|
||||
|
||||
fprintf(SRC, "\n\tswitch (s->%s_tag) {\n", m->m.name.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(n, m, set, (1 << Type_voidType));
|
||||
union_cases(n, m, set, (1 << Type_boolType));
|
||||
union_cases(n, m, set, (1 << Type_int8Type) | (1 << Type_uint8Type));
|
||||
union_cases(n, m, set, (1 << Type_int16Type) | (1 << Type_uint16Type) | (1 << Type_enumType));
|
||||
union_cases(n, m, set, (1 << Type_int32Type) | (1 << Type_uint32Type) | (1 << Type_float32Type));
|
||||
union_cases(n, m, set, (1 << Type_int64Type) | (1 << Type_uint64Type) | (1 << Type_float64Type));
|
||||
union_cases(n, m, set, (1 << Type_textType));
|
||||
union_cases(n, m, set, (1 << Type_dataType));
|
||||
union_cases(n, m, set, (1 << Type_structType) | (1 << Type_interfaceType) | (1 << Type_objectType) | (1 << Type_listType));
|
||||
|
||||
fprintf(SRC, "\t}\n");
|
||||
}
|
||||
|
||||
static void print_member(FILE *f, struct member *m, const char *tab) {
|
||||
if (m->t.body_tag == Type_voidType)
|
||||
return;
|
||||
|
||||
fputs(tab, f);
|
||||
|
||||
switch (m->t.body_tag) {
|
||||
case Type_voidType:
|
||||
break;
|
||||
case Type_boolType:
|
||||
fprintf(f, "unsigned int %s : 1;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int8Type:
|
||||
fprintf(f, "int8_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int16Type:
|
||||
fprintf(f, "int16_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int32Type:
|
||||
fprintf(f, "int32_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int64Type:
|
||||
fprintf(f, "int64_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_uint8Type:
|
||||
fprintf(f, "uint8_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_uint16Type:
|
||||
fprintf(f, "uint16_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_uint32Type:
|
||||
fprintf(f, "uint32_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_uint64Type:
|
||||
fprintf(f, "uint64_t %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_float32Type:
|
||||
fprintf(f, "float %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_float64Type:
|
||||
fprintf(f, "double %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_textType:
|
||||
fprintf(f, "capn_text %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_dataType:
|
||||
fprintf(f, "capn_data %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_enumType:
|
||||
fprintf(f, "enum %s %s;\n", m->type->name.str, m->m.name.str);
|
||||
break;
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
fprintf(f, "%s_ptr %s;\n", m->type->name.str, m->m.name.str);
|
||||
break;
|
||||
case Type_objectType:
|
||||
fprintf(f, "capn_ptr %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_listType:
|
||||
switch (m->list.body_tag) {
|
||||
case Type_voidType:
|
||||
fprintf(f, "capn_ptr %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_boolType:
|
||||
fprintf(f, "capn_list1 %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int8Type:
|
||||
case Type_uint8Type:
|
||||
fprintf(f, "capn_list8 %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int16Type:
|
||||
case Type_uint16Type:
|
||||
case Type_enumType:
|
||||
fprintf(f, "capn_list16 %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int32Type:
|
||||
case Type_uint32Type:
|
||||
fprintf(f, "capn_list32 %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_int64Type:
|
||||
case Type_uint64Type:
|
||||
fprintf(f, "capn_list64 %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_float32Type:
|
||||
fprintf(f, "capn_list_float %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_float64Type:
|
||||
fprintf(f, "capn_list_double %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_textType:
|
||||
case Type_dataType:
|
||||
case Type_objectType:
|
||||
case Type_listType:
|
||||
fprintf(f, "capn_ptr %s;\n", m->m.name.str);
|
||||
break;
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
fprintf(f, "%s_list %s;\n", m->type->name.str, m->m.name.str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct member *decode_member(struct member *mbrs, StructNode_Member_list l, int i) {
|
||||
struct member m;
|
||||
m.is_valid = 1;
|
||||
m.idx = i;
|
||||
get_StructNode_Member(&m.m, l, i);
|
||||
|
||||
if (m.m.codeOrder >= l.p.len) {
|
||||
fprintf(stderr, "unexpectedly large code order %d >= %d\n", m.m.codeOrder, l.p.len);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
if (m.m.body_tag == StructNode_Member_fieldMember) {
|
||||
read_StructNode_Field(&m.f, m.m.body.fieldMember);
|
||||
read_Type(&m.t, m.f.type);
|
||||
read_Value(&m.v, m.f.defaultValue);
|
||||
|
||||
switch (m.t.body_tag) {
|
||||
case Type_enumType:
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
m.type = find_node(m.t.body.enumType);
|
||||
break;
|
||||
|
||||
case Type_listType:
|
||||
read_Type(&m.list, m.t.body.listType);
|
||||
|
||||
switch (m.list.body_tag) {
|
||||
case Type_enumType:
|
||||
case Type_structType:
|
||||
case Type_interfaceType:
|
||||
m.type = find_node(m.list.body.enumType);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&mbrs[m.m.codeOrder], &m, sizeof(m));
|
||||
return &mbrs[m.m.codeOrder];
|
||||
}
|
||||
|
||||
static void define_struct(struct node *n) {
|
||||
static struct str buf = STR_INIT;
|
||||
|
||||
int i, j, mlen = n->u.structNode.members.p.len;
|
||||
struct member *mbrs = calloc(mlen, sizeof(*mbrs));
|
||||
|
||||
/* get list of members in code order and emit union enums */
|
||||
for (i = 0; i < mlen; i++) {
|
||||
struct member *m = decode_member(mbrs, n->u.structNode.members, i);
|
||||
|
||||
if (m->m.body_tag == StructNode_Member_unionMember) {
|
||||
int first, ulen;
|
||||
|
||||
/* get union members in code order */
|
||||
read_StructNode_Union(&m->u, m->m.body.unionMember);
|
||||
ulen = m->u.members.p.len;
|
||||
m->mbrs = calloc(ulen, sizeof(*m->mbrs));
|
||||
for (j = 0; j < ulen; j++) {
|
||||
decode_member(m->mbrs, m->u.members, j);
|
||||
}
|
||||
|
||||
/* emit union enum definition */
|
||||
first = 1;
|
||||
fprintf(HDR, "\nenum %s_%s {", n->name.str, m->m.name.str);
|
||||
for (j = 0; j < ulen; j++) {
|
||||
struct member *u = &m->mbrs[j];
|
||||
if (!u->is_valid) continue;
|
||||
if (!first) fprintf(HDR, ",");
|
||||
fprintf(HDR, "\n\t%s_%s = %d", n->name.str, u->m.name.str, u->idx);
|
||||
first = 0;
|
||||
}
|
||||
fprintf(HDR, "\n};\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* emit struct definition */
|
||||
fprintf(HDR, "\nstruct %s {\n", n->name.str);
|
||||
for (i = 0; i < mlen; i++) {
|
||||
struct member *m = &mbrs[i];
|
||||
if (!m->is_valid)
|
||||
continue;
|
||||
|
||||
switch (m->m.body_tag) {
|
||||
case StructNode_Member_fieldMember:
|
||||
print_member(HDR, m, "\t");
|
||||
break;
|
||||
case StructNode_Member_unionMember:
|
||||
fprintf(HDR, "\tenum %s_%s %s_tag;\n", n->name.str, m->m.name.str, m->m.name.str);
|
||||
fprintf(HDR, "\tunion {\n");
|
||||
for (j = 0; j < m->u.members.p.len; j++) {
|
||||
print_member(HDR, &m->mbrs[j], "\t\t");
|
||||
}
|
||||
fprintf(HDR, "\t} %s;\n", m->m.name.str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(HDR, "};\n");
|
||||
|
||||
fprintf(SRC, "\nvoid read_%s(struct %s *s, %s_ptr p) {\n", n->name.str, n->name.str, n->name.str);
|
||||
for (i = 0; i < mlen; i++) {
|
||||
struct member *m = &mbrs[i];
|
||||
if (!m->is_valid) continue;
|
||||
|
||||
switch (m->m.body_tag) {
|
||||
case StructNode_Member_fieldMember:
|
||||
str_reset(&buf);
|
||||
str_addf(&buf, "s->%s", m->m.name.str);
|
||||
get_member(SRC, m, "\t", buf.str);
|
||||
break;
|
||||
case StructNode_Member_unionMember:
|
||||
do_union(n, m, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(SRC, "}\n");
|
||||
|
||||
fprintf(SRC, "int write_%s(const struct %s *s, %s_ptr p) {\n", n->name.str, n->name.str, n->name.str);
|
||||
fprintf(SRC, "\tint err = 0;\n");
|
||||
for (i = 0; i < mlen; i++) {
|
||||
struct member *m = &mbrs[i];
|
||||
if (!m->is_valid) continue;
|
||||
|
||||
switch (m->m.body_tag) {
|
||||
case StructNode_Member_fieldMember:
|
||||
if (m->t.body_tag != Type_voidType) {
|
||||
str_reset(&buf);
|
||||
str_addf(&buf, "s->%s", m->m.name.str);
|
||||
set_member(SRC, m, "\t", buf.str);
|
||||
}
|
||||
break;
|
||||
case StructNode_Member_unionMember:
|
||||
do_union(n, m, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(SRC, "\treturn err;\n}\n");
|
||||
|
||||
fprintf(SRC, "void get_%s(struct %s *s, %s_list l, int i) {\n", n->name.str, n->name.str, n->name.str);
|
||||
fprintf(SRC, "\t%s_ptr p = {capn_getp(l.p, i)};\n", n->name.str);
|
||||
fprintf(SRC, "\tread_%s(s, p);\n", n->name.str);
|
||||
fprintf(SRC, "}\n");
|
||||
|
||||
fprintf(SRC, "int set_%s(const struct %s *s, %s_list l, int i) {\n", n->name.str, n->name.str, n->name.str);
|
||||
fprintf(SRC, "\t%s_ptr p = {capn_getp(l.p, i)};\n", n->name.str);
|
||||
fprintf(SRC, "\treturn write_%s(s, p);\n", n->name.str);
|
||||
fprintf(SRC, "}\n");
|
||||
}
|
||||
|
||||
static void declare_structs(struct node *n, const char *format, int num) {
|
||||
fprintf(HDR, "\n");
|
||||
for (n = n->first_child; n != NULL; n = n->next_child) {
|
||||
if (n->n.body_tag == Node_structNode) {
|
||||
switch (num) {
|
||||
case 3:
|
||||
fprintf(HDR, format, n->name.str, n->name.str, n->name.str);
|
||||
break;
|
||||
case 1:
|
||||
fprintf(HDR, format, n->name.str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
struct capn capn;
|
||||
CodeGeneratorRequest_ptr root;
|
||||
struct CodeGeneratorRequest req;
|
||||
int i, j;
|
||||
struct node *n;
|
||||
int i;
|
||||
|
||||
if (capn_init_fp(&capn, stdin, 0)) {
|
||||
fprintf(stderr, "failed to read schema from stdin\n");
|
||||
|
|
@ -38,54 +607,112 @@ int main() {
|
|||
root.p = capn_get_root(&capn);
|
||||
read_CodeGeneratorRequest(&req, root);
|
||||
|
||||
for (i = 0; i < req.nodes.p.size; i++) {
|
||||
struct Node N;
|
||||
struct FileNode F;
|
||||
struct StructNode S;
|
||||
struct EnumNode E;
|
||||
struct InterfaceNode I;
|
||||
struct ConstNode C;
|
||||
struct AnnotationNode A;
|
||||
for (i = 0; i < req.nodes.p.len; i++) {
|
||||
n = calloc(1, sizeof(*n));
|
||||
get_Node(&n->n, req.nodes, i);
|
||||
insert_node(n);
|
||||
|
||||
get_Node(&N, req.nodes, i);
|
||||
fprintf(stderr, "node %s id:%#llx scope:%#llx type:%d\n",
|
||||
N.displayName.str, N.id, N.scopeId, N.body_tag);
|
||||
|
||||
switch (N.body_tag) {
|
||||
switch (n->n.body_tag) {
|
||||
case Node_fileNode:
|
||||
read_FileNode(&F, N.body.fileNode);
|
||||
for (j = 0; j < F.imports.p.size; j++) {
|
||||
struct FileNode_Import fi;
|
||||
get_FileNode_Import(&fi, F.imports, j);
|
||||
fprintf(stderr, "\timport %#llx %s\n", fi.id, fi.name.str);
|
||||
}
|
||||
n->next = g_files;
|
||||
g_files = n;
|
||||
read_FileNode(&n->u.fileNode, n->n.body.fileNode);
|
||||
break;
|
||||
case Node_structNode:
|
||||
read_StructNode(&S, N.body.structNode);
|
||||
fprintf(stderr, "\tstruct %d %d %d\n",
|
||||
S.dataSectionWordSize, S.pointerSectionSize, S.preferredListEncoding);
|
||||
for (j = 0; j < S.members.p.size; j++) {
|
||||
}
|
||||
read_StructNode(&n->u.structNode, n->n.body.structNode);
|
||||
break;
|
||||
case Node_enumNode:
|
||||
read_EnumNode(&E, N.body.enumNode);
|
||||
for (j = 0; j < E.enumerants.p.size; j++) {
|
||||
struct EnumNode_Enumerant ee;
|
||||
get_EnumNode_Enumerant(&ee, E.enumerants, j);
|
||||
fprintf(stderr, "\tenum %d %s %d\n", j, ee.name.str, ee.codeOrder);
|
||||
}
|
||||
read_EnumNode(&n->u.enumNode, n->n.body.enumNode);
|
||||
break;
|
||||
case Node_interfaceNode:
|
||||
read_InterfaceNode(&I, N.body.interfaceNode);
|
||||
read_InterfaceNode(&n->u.interfaceNode, n->n.body.interfaceNode);
|
||||
break;
|
||||
case Node_constNode:
|
||||
read_ConstNode(&C, N.body.constNode);
|
||||
read_ConstNode(&n->u.constNode, n->n.body.constNode);
|
||||
break;
|
||||
case Node_annotationNode:
|
||||
read_AnnotationNode(&A, N.body.annotationNode);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = g_files; n != NULL; n = n->next) {
|
||||
struct str b = STR_INIT;
|
||||
|
||||
for (i = n->n.nestedNodes.p.len-1; i >= 0; i--) {
|
||||
struct Node_NestedNode nest;
|
||||
get_Node_NestedNode(&nest, n->n.nestedNodes, i);
|
||||
resolve_names(&b, find_node(nest.id), nest.name, n);
|
||||
}
|
||||
|
||||
str_release(&b);
|
||||
}
|
||||
|
||||
for (i = 0; i < req.requestedFiles.p.len; i++) {
|
||||
struct str b = STR_INIT;
|
||||
struct node *s;
|
||||
char *p;
|
||||
n = find_node(capn_get64(req.requestedFiles, i));
|
||||
|
||||
str_reset(&b);
|
||||
str_addf(&b, "%s.h", n->n.displayName.str);
|
||||
HDR = fopen(b.str, "w");
|
||||
if (!HDR) {
|
||||
fprintf(stderr, "failed to open %s: %s\n", b.str, strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
str_reset(&b);
|
||||
str_addf(&b, "%s.c", n->n.displayName.str);
|
||||
SRC = fopen(b.str, "w");
|
||||
if (!SRC) {
|
||||
fprintf(stderr, "failed to open %s: %s\n", b.str, strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
fprintf(HDR, "#ifndef CAPN_%llx\n", n->n.id);
|
||||
fprintf(HDR, "#define CAPN_%llx\n", n->n.id);
|
||||
fprintf(HDR, "/* AUTO GENERATED DO NOT EDIT*/\n");
|
||||
fprintf(HDR, "#include <capn.h>\n");
|
||||
|
||||
for (i = 0; i < n->u.fileNode.imports.p.len; i++) {
|
||||
struct FileNode_Import im;
|
||||
get_FileNode_Import(&im, n->u.fileNode.imports, i);
|
||||
fprintf(HDR, "#include \"%s.h\"\n", im.name.str);
|
||||
}
|
||||
|
||||
fprintf(HDR, "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n");
|
||||
|
||||
p = strrchr(n->n.displayName.str, '/');
|
||||
fprintf(SRC, "#include \"%s.h\"\n", p ? p+1 : n->n.displayName.str);
|
||||
fprintf(SRC, "/* AUTO GENERATED DO NOT EDIT*/\n");
|
||||
|
||||
declare_structs(n, "struct %s;\n", 1);
|
||||
declare_structs(n, "typedef struct {capn_ptr p;} %s_ptr;\n", 1);
|
||||
declare_structs(n, "typedef struct {capn_ptr p;} %s_list;\n", 1);
|
||||
declare_structs(n, "void read_%s(struct %s*, %s_ptr);\n", 3);
|
||||
declare_structs(n, "int write_%s(const struct %s*, %s_ptr);\n", 3);
|
||||
declare_structs(n, "void get_%s(struct %s*, %s_list, int i);\n", 3);
|
||||
declare_structs(n, "int set_%s(const struct %s*, %s_list, int i);\n", 3);
|
||||
|
||||
for (s = n->first_child; s != NULL; s = s->next_child) {
|
||||
switch (s->n.body_tag) {
|
||||
case Node_structNode:
|
||||
define_struct(s);
|
||||
break;
|
||||
case Node_enumNode:
|
||||
define_enum(s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(HDR, "\n#ifdef __cplusplus\n}\n#endif\n#endif\n");
|
||||
str_release(&b);
|
||||
fclose(HDR);
|
||||
fclose(SRC);
|
||||
HDR = SRC = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,13 +140,13 @@ void read_Type(struct Type *s, Type_ptr p) {
|
|||
s->body.listType.p = capn_getp(p.p, 0);
|
||||
break;
|
||||
case Type_enumType:
|
||||
s->body.enumType = capn_read64(p.p, 0);
|
||||
s->body.enumType = capn_read64(p.p, 8);
|
||||
break;
|
||||
case Type_structType:
|
||||
s->body.structType = capn_read64(p.p, 0);
|
||||
s->body.structType = capn_read64(p.p, 8);
|
||||
break;
|
||||
case Type_interfaceType:
|
||||
s->body.interfaceType = capn_read64(p.p, 0);
|
||||
s->body.interfaceType = capn_read64(p.p, 8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
96
compiler/str.c
Normal file
96
compiler/str.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include "str.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef va_copy
|
||||
# ifdef _MSC_VER
|
||||
# define va_copy(d,s) d = s
|
||||
# elif defined __GNUC__
|
||||
# define va_copy(d,s) __builtin_va_copy(d,s)
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char str_static[] = "\0";
|
||||
|
||||
void str_reserve(struct str *v, int sz) {
|
||||
if (sz < v->cap)
|
||||
return;
|
||||
|
||||
v->cap = (v->cap * 2) + 16;
|
||||
if (sz > v->cap) {
|
||||
v->cap = (sz + 8) & ~7;
|
||||
}
|
||||
|
||||
if (v->str == str_static) {
|
||||
v->str = NULL;
|
||||
}
|
||||
|
||||
v->str = realloc(v->str, v->cap + 1);
|
||||
}
|
||||
|
||||
void str_add(struct str *v, const char *str, int sz) {
|
||||
if (sz < 0)
|
||||
sz = strlen(str);
|
||||
str_reserve(v, v->len + sz);
|
||||
memcpy(v->str+v->len, str, sz);
|
||||
v->len += sz;
|
||||
v->str[v->len] = '\0';
|
||||
}
|
||||
|
||||
int str_vaddf(struct str *v, const char* format, va_list ap) {
|
||||
str_reserve(v, v->len + 1);
|
||||
|
||||
for (;;) {
|
||||
int ret;
|
||||
|
||||
char* buf = v->str + v->len;
|
||||
int bufsz = v->cap - v->len;
|
||||
|
||||
va_list aq;
|
||||
va_copy(aq, ap);
|
||||
|
||||
/* We initialise buf[bufsz] to \0 to detect when snprintf runs out of
|
||||
* buffer by seeing whether it overwrites it.
|
||||
*/
|
||||
buf[bufsz] = '\0';
|
||||
ret = vsnprintf(buf, bufsz + 1, format, aq);
|
||||
|
||||
if (ret > bufsz) {
|
||||
/* snprintf has told us the size of buffer required (ISO C99
|
||||
* behavior)
|
||||
*/
|
||||
str_reserve(v, v->len + ret);
|
||||
|
||||
} else if (ret >= 0) {
|
||||
/* success */
|
||||
v->len += ret;
|
||||
return ret;
|
||||
|
||||
} else if (buf[bufsz] != '\0') {
|
||||
/* snprintf has returned an error but has written to the end of the
|
||||
* buffer (MSVC behavior). The buffer is not large enough so grow
|
||||
* and retry. This can also occur with a format error if it occurs
|
||||
* right on the boundary, but then we grow the buffer and can
|
||||
* figure out its an error next time around.
|
||||
*/
|
||||
str_reserve(v, v->len + bufsz + 1);
|
||||
|
||||
} else {
|
||||
/* snprintf has returned an error but has not written to the last
|
||||
* character in the buffer. We have a format error.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int str_addf(struct str *v, const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
return str_vaddf(v, format, ap);
|
||||
}
|
||||
|
||||
42
compiler/str.h
Normal file
42
compiler/str.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* vim: set sw=8 ts=8 sts=8 noet: */
|
||||
#include <capn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct str {
|
||||
char *str;
|
||||
int len, cap;
|
||||
};
|
||||
|
||||
extern char str_static[];
|
||||
#define STR_INIT {str_static, 0, 0}
|
||||
|
||||
void str_reserve(struct str *v, int sz);
|
||||
|
||||
static void str_release(struct str *v) {
|
||||
if (v->cap) {
|
||||
free(v->str);
|
||||
}
|
||||
}
|
||||
|
||||
static void str_reset(struct str *v) {
|
||||
v->len = 0;
|
||||
v->str[0] = '\0';
|
||||
}
|
||||
|
||||
static void str_setlen(struct str *v, int sz) {
|
||||
str_reserve(v, sz);
|
||||
v->str[sz] = '\0';
|
||||
v->len = sz;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ATTR(FMT, ARGS) __attribute__((format(printf,FMT,ARGS)))
|
||||
#else
|
||||
#define ATTR(FMT, ARGS)
|
||||
#endif
|
||||
|
||||
void str_add(struct str *v, const char *str, int sz);
|
||||
int str_vaddf(struct str *v, const char *format, va_list ap) ATTR(2,0);
|
||||
int str_addf(struct str *v, const char *format, ...) ATTR(2,3);
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue