biner/transpile_c.c

680 lines
22 KiB
C

#include "./transpile.h"
#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "./tree.h"
#define CONTEXT_SUFFIX_ "_pack_context_t"
typedef struct struct_member_type_name_meta_t {
const char* func;
const char* type;
} struct_member_type_name_meta_t;
static const struct_member_type_name_meta_t struct_member_type_name_meta_map_
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_] = {
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU8] = {"l8", "uint8_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU16] = {"l16", "uint16_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU32] = {"l32", "uint32_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU64] = {"l64", "uint64_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI8] = {"l8", "int8_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI16] = {"l16", "int16_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI32] = {"l32", "int32_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI64] = {"l64", "int64_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU8] = {"b8", "uint8_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU16] = {"b16", "uint16_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU32] = {"b32", "uint32_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU64] = {"b64", "uint64_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI8] = {"b8", "int8_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI16] = {"b16", "int16_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI32] = {"b32", "int32_t"},
[BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI64] = {"b64", "int64_t"},
};
static const char* const expr_operator_string_map_
[BINER_TREE_EXPR_TYPE_OPERATOR_MAX_] = {
[BINER_TREE_EXPR_TYPE_OPERATOR_EQUAL] = "==",
[BINER_TREE_EXPR_TYPE_OPERATOR_NEQUAL] = "!=",
[BINER_TREE_EXPR_TYPE_OPERATOR_GREATER_EQUAL] = ">=",
[BINER_TREE_EXPR_TYPE_OPERATOR_LESS_EQUAL] = "<=",
[BINER_TREE_EXPR_TYPE_OPERATOR_GREATER] = ">",
[BINER_TREE_EXPR_TYPE_OPERATOR_LESS] = "<",
[BINER_TREE_EXPR_TYPE_OPERATOR_AND] = "&&",
[BINER_TREE_EXPR_TYPE_OPERATOR_OR] = "||",
[BINER_TREE_EXPR_TYPE_OPERATOR_NOT] = "!",
[BINER_TREE_EXPR_TYPE_OPERATOR_ADD] = "+",
[BINER_TREE_EXPR_TYPE_OPERATOR_SUB] = "-",
[BINER_TREE_EXPR_TYPE_OPERATOR_MUL] = "*",
[BINER_TREE_EXPR_TYPE_OPERATOR_DIV] = "/",
[BINER_TREE_EXPR_TYPE_OPERATOR_BIT_AND] = "&",
[BINER_TREE_EXPR_TYPE_OPERATOR_BIT_OR] = "|",
[BINER_TREE_EXPR_TYPE_OPERATOR_BIT_NOT] = "~",
[BINER_TREE_EXPR_TYPE_OPERATOR_BIT_XOR] = "^",
[BINER_TREE_EXPR_TYPE_OPERATOR_BIT_LSHIFT] = "<<",
[BINER_TREE_EXPR_TYPE_OPERATOR_BIT_RSHIFT] = ">>",
};
typedef struct struct_member_info_t {
const biner_transpile_param_t* p;
const biner_tree_struct_member_t* m;
const biner_tree_struct_member_type_t* t;
bool union_begin;
bool union_end;
bool union_member;
size_t offset;
} struct_member_info_t;
typedef void (*struct_member_each_func_t)(const struct_member_info_t*);
static size_t struct_member_each_(
const biner_transpile_param_t* p,
const biner_tree_struct_member_t* m,
struct_member_each_func_t f,
size_t next_index) {
assert(p != NULL);
assert(m != NULL);
assert(f != NULL);
struct_member_info_t info = {
.p = p,
.m = m,
.t = (const biner_tree_struct_member_type_t*) (p->zone+m->type),
.union_begin = (m->index == next_index),
};
if (m->prev != 0) {
const biner_tree_struct_member_t* prev =
(const biner_tree_struct_member_t*) (p->zone+m->prev);
if (prev->index == m->index) {
info.union_end = !info.union_begin;
info.union_begin = false;
info.union_member = true;
}
info.offset = struct_member_each_(p, prev, f, m->index);
}
if (info.union_begin) info.union_member = true;
const size_t size =
biner_tree_struct_member_type_name_meta_map[info.t->name].size;
f(&info);
return info.offset + size;
}
static inline void print_fixed_decl_name_(
const biner_transpile_param_t* p, const char* name) {
assert(p != NULL);
assert(name != NULL);
const char* end = name;
while (*end) ++end;
if (name+2 <= end && strcmp(end-2, "_t") == 0) end -= 2;
fprintf(p->dst, "%.*s", (int) (end-name), name);
}
static inline void print_typedef_header_(
const biner_transpile_param_t* p,
const char* kind,
const char* type,
const char* name) {
assert(p != NULL);
assert(kind != NULL);
assert(type != NULL);
assert(name != NULL);
fprintf(p->dst, "typedef %s ", kind);
print_fixed_decl_name_(p, type);
fprintf(p->dst, "%s { ", name);
}
static inline void print_typedef_footer_(
const biner_transpile_param_t* p,
const char* type,
const char* name) {
assert(p != NULL);
assert(type != NULL);
assert(name != NULL);
fprintf(p->dst, "} ");
print_fixed_decl_name_(p, type);
fprintf(p->dst, "%s;\n", name);
}
static inline void print_func_header_(
const biner_transpile_param_t* p,
const char* ret,
const char* type,
const char* name) {
assert(p != NULL);
assert(type != NULL);
assert(name != NULL);
fprintf(p->dst, "static inline %s ", ret);
print_fixed_decl_name_(p, type);
fprintf(p->dst, "%s(", name);
}
static void print_struct_member_reference_(
const biner_transpile_param_t* p,
const biner_tree_struct_member_reference_t* r) {
assert(p != NULL);
assert(r != NULL);
if (r->prev != 0) {
print_struct_member_reference_(
p, (const biner_tree_struct_member_reference_t*) (p->zone+r->prev));
}
const biner_tree_struct_member_t* m =
(const biner_tree_struct_member_t*) (p->zone+r->member);
fprintf(p->dst, "%s", p->zone+m->name);
if (r->prev != 0) fprintf(p->dst, ".");
}
static void print_expr_(
const biner_transpile_param_t* p, const biner_tree_expr_t* e) {
assert(p != NULL);
assert(e != NULL);
fprintf(p->dst, "(");
switch (e->type) {
case BINER_TREE_EXPR_TYPE_OPERAND_INTEGER:
fprintf(p->dst, "%"PRIi64, e->i);
break;
case BINER_TREE_EXPR_TYPE_OPERAND_REFERENCE:
fprintf(p->dst, "s->");
print_struct_member_reference_(
p, (const biner_tree_struct_member_reference_t*) (p->zone+e->r));
break;
default:
if (e->operands.l) {
print_expr_(p, (const biner_tree_expr_t*) (p->zone+e->operands.l));
}
fprintf(p->dst, expr_operator_string_map_[e->type]);
if (e->operands.r) {
print_expr_(p, (const biner_tree_expr_t*) (p->zone+e->operands.r));
}
}
fprintf(p->dst, ")");
}
static void print_enum_member_decls_(
const biner_transpile_param_t* p,
const biner_tree_enum_member_t* m) {
assert(p != NULL);
assert(m != NULL);
if (m->prev != 0) {
print_enum_member_decls_(
p, (const biner_tree_enum_member_t*) (p->zone+m->prev));
}
fprintf(p->dst, "%s=", p->zone+m->name);
print_expr_(p, (const biner_tree_expr_t*) (p->zone+m->expr));
fprintf(p->dst, ",");
}
static void print_enum_member_validation_code_(
const biner_transpile_param_t* p,
const biner_tree_enum_member_t* m) {
assert(p != NULL);
assert(m != NULL);
fprintf(p->dst, "return true");
while ((uintptr_t) m != (uintptr_t) p->zone) {
fprintf(p->dst, " && v == %s", p->zone+m->name);
m = (const biner_tree_enum_member_t*) (p->zone+m->prev);
}
fprintf(p->dst, ";");
}
static void print_struct_member_type_name_(
const biner_transpile_param_t* p,
const biner_tree_struct_member_type_t* t) {
assert(p != NULL);
assert(t != NULL);
if (t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
const biner_tree_decl_t* d = (const biner_tree_decl_t*) (p->zone+t->decl);
print_fixed_decl_name_(p, (const char*) (p->zone+d->name));
fprintf(p->dst, "_t");
return;
}
const char* name = struct_member_type_name_meta_map_[t->name].type;
assert(name != NULL);
fprintf(p->dst, "%s", name);
}
static void print_struct_member_decl_(const struct_member_info_t* info) {
assert(info != NULL);
if (info->union_begin) fprintf(info->p->dst, "union { ");
print_struct_member_type_name_(info->p, info->t);
fprintf(info->p->dst, " ");
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_NONE:
fprintf(info->p->dst, "%s", info->p->zone+info->m->name);
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
fprintf(info->p->dst, "%s[", info->p->zone+info->m->name);
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, "]");
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
fprintf(info->p->dst, "*%s", info->p->zone+info->m->name);
break;
}
fprintf(info->p->dst, "; ");
if (info->union_end) fprintf(info->p->dst, "}; ");
}
static void print_struct_member_context_struct_(
const biner_transpile_param_t* p,
const biner_tree_struct_member_t* m,
const char* suffix) {
assert(p != NULL);
assert(m != NULL);
fprintf(p->dst, "size_t step; ");
fprintf(p->dst, "size_t count; ");
fprintf(p->dst, "size_t count_max; ");
fprintf(p->dst, "size_t byte; ");
fprintf(p->dst, "void* udata; ");
bool require_subctx = false;
const biner_tree_struct_member_t* itr = m;
while ((uintptr_t) itr != (uintptr_t) p->zone) {
const biner_tree_struct_member_type_t* t =
(const biner_tree_struct_member_type_t*) (p->zone+itr->type);
if (t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
require_subctx = true;
}
itr = (const biner_tree_struct_member_t*) (p->zone+itr->prev);
}
if (require_subctx) {
fprintf(p->dst, "union { ");
itr = m;
while ((uintptr_t) itr != (uintptr_t) p->zone) {
const biner_tree_struct_member_type_t* t =
(const biner_tree_struct_member_type_t*) (p->zone+itr->type);
if (t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
const biner_tree_decl_t* d = (const biner_tree_decl_t*) (p->zone+t->decl);
print_fixed_decl_name_(p, (const char*) (p->zone+d->name));
fprintf(p->dst, "%s %s; ", suffix, p->zone+itr->name);
}
itr = (const biner_tree_struct_member_t*) (p->zone+itr->prev);
}
fprintf(p->dst, "} subctx; ");
}
}
static void print_struct_member_pack_code_each_(
const struct_member_info_t* info) {
assert(info != NULL);
const char* name = (const char*) (info->p->zone+info->m->name);
/* only available when info->p->name == USER_DECL */
const biner_tree_decl_t* d =
(const biner_tree_decl_t*) (info->p->zone+info->t->decl);
const char* dname = (const char*) (info->p->zone+d->name);
if (!info->union_member || info->union_begin) {
fprintf(info->p->dst, "init%zu: ", info->m->index);
fprintf(info->p->dst, "++ctx->step; ctx->byte = 0; ");
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
fprintf(info->p->dst, "ctx->count_max = ");
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, "; ");
fprintf(info->p->dst,
"if (ctx->count_max <= 0) { ++ctx->step; goto CONTINUE; } ");
fprintf(info->p->dst, "ctx->count = 0; ");
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
fprintf(info->p->dst, "ctx->count = 0; ");
break;
default:
;
}
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "body%zu: ", info->m->index);
}
if (info->m->condition != 0) {
fprintf(info->p->dst, "if (");
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->m->condition));
fprintf(info->p->dst, ") {");
}
const char* suffix = "";
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
suffix = "[ctx->count]";
break;
default:
;
}
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "result = ");
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, "_pack(&ctx->subctx.%s, &s->%s%s, c); ", name, name, suffix);
fprintf(info->p->dst,
"if (result != BINER_RESULT_COMPLETED) { return result; } else { ");
} else {
const char* func = struct_member_type_name_meta_map_[info->t->name].func;
fprintf(info->p->dst,
"biner_pack_%s(&s->%s%s, c, ctx->byte); ", func, name, suffix);
const size_t sz = biner_tree_struct_member_type_name_meta_map[info->t->name].size;
fprintf(info->p->dst, "if (++ctx->byte >= %zu) { ", sz);
}
bool reset = false;
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
fprintf(info->p->dst,
"if (++ctx->count >= ctx->count_max) goto NEXT; ctx->byte = 0; ");
reset = true;
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
fprintf(info->p->dst, "if (++ctx->count >= ");
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, ") goto NEXT; ctx->byte = 0; ");
reset = true;
break;
default:
fprintf(info->p->dst, "goto NEXT; ");
}
if (reset) {
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "ctx->byte = 0; ");
}
fprintf(info->p->dst, "} return BINER_RESULT_CONTINUE; ");
if (info->m->condition != 0) {
fprintf(info->p->dst, "} ");
if (!info->union_member || info->union_end) {
fprintf(info->p->dst, "goto NEXT; ");
}
}
}
static void print_struct_member_unpack_code_each_(
const struct_member_info_t* info) {
assert(info != NULL);
const char* name = (const char*) (info->p->zone+info->m->name);
/* only available when info->p->name == USER_DECL */
const biner_tree_decl_t* d =
(const biner_tree_decl_t*) (info->p->zone+info->t->decl);
const char* dname = (const char*) (info->p->zone+d->name);
if (!info->union_member || info->union_begin) {
fprintf(info->p->dst, "init%zu: ", info->m->index);
fprintf(info->p->dst, "++ctx->step; ctx->byte = 0; ");
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
fprintf(info->p->dst, "ctx->count_max = ");
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, "; ");
fprintf(info->p->dst,
"if (ctx->count_max <= 0) { ++ctx->step; goto CONTINUE; } ");
fprintf(info->p->dst,
"s->%s = biner_malloc_(sizeof(*s->%s)*ctx->count_max, ctx->udata); ",
name, name);
fprintf(info->p->dst,
"if (s->%s == NULL) { return BINER_RESULT_MEMORY_ERROR; } ", name);
fprintf(info->p->dst, "ctx->count = 0; ");
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
fprintf(info->p->dst, "ctx->count = 0; ");
break;
default:
;
}
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "body%zu: ", info->m->index);
}
if (info->m->condition != 0) {
fprintf(info->p->dst, "if (");
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->m->condition));
fprintf(info->p->dst, ") {");
}
const char* suffix = "";
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
suffix = "[ctx->count]";
break;
default:
;
}
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "result = ");
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c); ", name, name, suffix);
fprintf(info->p->dst,
"if (result != BINER_RESULT_COMPLETED) { return result; } else { ");
} else {
const char* func = struct_member_type_name_meta_map_[info->t->name].func;
fprintf(info->p->dst,
"biner_unpack_%s(&s->%s%s, c, ctx->byte); ", func, name, suffix);
const size_t sz = biner_tree_struct_member_type_name_meta_map[info->t->name].size;
fprintf(info->p->dst, "if (++ctx->byte >= %zu) { ", sz);
}
bool reset = false;
switch (info->t->qualifier) {
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY:
fprintf(info->p->dst,
"if (++ctx->count >= ctx->count_max) goto NEXT; ");
reset = true;
break;
case BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_STATIC_ARRAY:
fprintf(info->p->dst, "if (++ctx->count >= ");
print_expr_(
info->p, (const biner_tree_expr_t*) (info->p->zone+info->t->expr));
fprintf(info->p->dst, ") goto NEXT; ");
reset = true;
break;
default:
fprintf(info->p->dst, "goto NEXT; ");
}
if (reset) {
if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
fprintf(info->p->dst, "ctx->subctx.%s = (", name);
print_fixed_decl_name_(info->p, dname);
fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; ");
}
fprintf(info->p->dst, "ctx->byte = 0; ");
}
fprintf(info->p->dst, "} return BINER_RESULT_CONTINUE; ");
if (info->m->condition != 0) {
fprintf(info->p->dst, "} ");
if (!info->union_member || info->union_end) {
fprintf(info->p->dst, "goto NEXT; ");
}
}
}
static inline void print_struct_member_iteration_code_(
const biner_transpile_param_t* p,
const biner_tree_struct_member_t* m,
struct_member_each_func_t f) {
assert(p != NULL);
assert(m != NULL);
assert(f != NULL);
bool require_continue = false;
bool require_result_var = false;
const biner_tree_struct_member_t* itr = m;
while ((uintptr_t) itr != (uintptr_t) p->zone) {
const biner_tree_struct_member_type_t* t =
(const biner_tree_struct_member_type_t*) (p->zone+itr->type);
if (t->qualifier == BINER_TREE_STRUCT_MEMBER_TYPE_QUALIFIER_DYNAMIC_ARRAY) {
require_continue = true;
}
if (t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) {
require_result_var = true;
}
itr = (const biner_tree_struct_member_t*) (p->zone+itr->prev);
}
fprintf(p->dst, "static const void* const steps_[] = { ");
for (size_t i = 0; i <= m->index; ++i) {
fprintf(p->dst, "&&init%zu, &&body%zu, ", i, i);
}
fprintf(p->dst, "}; ");
if (require_result_var) {
fprintf(p->dst, "biner_result_t result; ");
}
if (require_continue) {
fprintf(p->dst, "CONTINUE: ");
}
fprintf(p->dst,
"if (ctx->step >= sizeof(steps_)/sizeof(steps_[0]))"
" return BINER_RESULT_COMPLETED; ");
fprintf(p->dst, "goto *steps_[ctx->step]; ");
struct_member_each_(p, m, f, SIZE_MAX);
fprintf(p->dst, "NEXT: ");
fprintf(p->dst,
"return (++ctx->step >= sizeof(steps_)/sizeof(steps_[0]))?"
" BINER_RESULT_COMPLETED:"
" BINER_RESULT_CONTINUE; ");
}
static void print_decls_(
const biner_transpile_param_t* p, const biner_tree_decl_t* d) {
assert(p != NULL);
assert(d != NULL);
if (d->prev != 0) {
print_decls_(p, (const biner_tree_decl_t*) (p->zone+d->prev));
}
const bool only_type = biner_transpile_is_option_enabled(p, "--only-type");
const bool only_func = biner_transpile_is_option_enabled(p, "--only-func");
const bool type = only_type || (!only_type && !only_func);
const bool func = only_func || (!only_type && !only_func);
const char* name = (const char*) (p->zone+d->name);
switch (d->type) {
case BINER_TREE_DECL_TYPE_CONST: {
const biner_tree_expr_t* body =
(const biner_tree_expr_t*) (p->zone+d->const_);
if (type) {
fprintf(p->dst, "#define %s (", name);
print_expr_(p, body);
fprintf(p->dst, ")\n");
}
} break;
case BINER_TREE_DECL_TYPE_ENUM: {
const biner_tree_enum_member_t* body =
(const biner_tree_enum_member_t*) (p->zone+d->enum_);
if (type) {
print_typedef_header_(p, "enum", name, "_t");
print_enum_member_decls_(p, body);
print_typedef_footer_(p, name, "_t");
}
if (func) {
print_func_header_(p, "bool", name, "_validate");
fprintf(p->dst, "uintmax_t v) { ");
print_enum_member_validation_code_(p, body);
fprintf(p->dst, "}\n");
}
} break;
case BINER_TREE_DECL_TYPE_STRUCT: {
const biner_tree_struct_member_t* body =
(const biner_tree_struct_member_t*) (p->zone+d->struct_);
if (type) {
print_typedef_header_(p, "struct", name, "_t");
struct_member_each_(p, body, print_struct_member_decl_, SIZE_MAX);
print_typedef_footer_(p, name, "_t");
}
if (type) {
print_typedef_header_(p, "struct", name, CONTEXT_SUFFIX_);
print_struct_member_context_struct_(p, body, CONTEXT_SUFFIX_);
print_typedef_footer_(p, name, CONTEXT_SUFFIX_);
}
if (func) {
print_func_header_(p, "biner_result_t", name, "_pack");
print_fixed_decl_name_(p, name);
fprintf(p->dst, CONTEXT_SUFFIX_"* ctx, ");
fprintf(p->dst, "const ");
print_fixed_decl_name_(p, name);
fprintf(p->dst, "_t* s, ");
fprintf(p->dst, "uint8_t* c) { ");
print_struct_member_iteration_code_(
p, body, &print_struct_member_pack_code_each_);
fprintf(p->dst, "}\n");
}
if (func) {
print_func_header_(p, "biner_result_t", name, "_unpack");
print_fixed_decl_name_(p, name);
fprintf(p->dst, CONTEXT_SUFFIX_"* ctx, ");
print_fixed_decl_name_(p, name);
fprintf(p->dst, "_t* s, ");
fprintf(p->dst, "uint8_t c) { ");
print_struct_member_iteration_code_(
p, body, &print_struct_member_unpack_code_each_);
fprintf(p->dst, "}\n");
}
} break;
}
}
bool biner_transpile_c(const biner_transpile_param_t* p) {
assert(p != NULL);
const biner_tree_root_t* root = (const biner_tree_root_t*) p->zone;
print_decls_(p, (const biner_tree_decl_t*) (p->zone+root->decls));
return true;
}