diff --git a/.gitignore b/.gitignore index 056d00e..87f2b0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp /.build +/test diff --git a/CMakeLists.txt b/CMakeLists.txt index b955dce..2b9b25c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,10 +24,11 @@ add_executable(biner) target_sources(biner PRIVATE main.c + transpile_c.c tree.c ${BISON_biner-parser_OUTPUTS} ${FLEX_biner-scanner_OUTPUTS} PUBLIC - zone.h + c/zone.h ) target_include_directories(biner PRIVATE . ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/TODO.TXT b/TODO.TXT index 0655053..8016240 100644 --- a/TODO.TXT +++ b/TODO.TXT @@ -8,5 +8,7 @@ X enum support X constant support X conditional switching support X union support - transpiler for C +X C transpiler for unpacking + C transpiler for packing + add bitmanip operators release 1.0.0 diff --git a/biner.l b/biner.l index 405c8d0..21d8bd2 100644 --- a/biner.l +++ b/biner.l @@ -6,7 +6,7 @@ #include #include "./tree.h" -#include "./zone.h" +#include "./c/zone.h" #include "generated/biner.y.h" diff --git a/biner.y b/biner.y index 2738171..a9fbaeb 100644 --- a/biner.y +++ b/biner.y @@ -8,7 +8,7 @@ #include #include "./tree.h" -#include "./zone.h" +#include "./c/zone.h" #define ctx (biner_tree_parse_context_) @@ -248,8 +248,13 @@ unqualified_struct_member_type YYABORT; } } else { - t->name = BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL; - t->decl = decl; + if (ref(biner_tree_decl_t, decl)->type == BINER_TREE_DECL_TYPE_STRUCT) { + t->name = BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL; + t->decl = decl; + } else { + yyerrorf("'%s' is not struct", ref(char, $1)); + YYABORT; + } } } ; @@ -303,7 +308,7 @@ mul_expr unary_expr : operand | '!' operand { - $$ = create_operator_($2, BINER_TREE_EXPR_TYPE_OPERATOR_NOT, 0); + $$ = create_operator_(0, BINER_TREE_EXPR_TYPE_OPERATOR_NOT, $2); } ; @@ -443,7 +448,7 @@ static inline bool unstringify_struct_member_type_name_( biner_tree_struct_member_type_name_t* name, biner_zone_ptr(char) str) { for (size_t i = 0; i < BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_; ++i) { - const char* item = biner_tree_struct_member_type_name_string_map[i]; + const char* item = biner_tree_struct_member_type_name_meta_map[i].name; if (item != NULL && strcmp(ref(char, str), item) == 0) { *name = (biner_tree_struct_member_type_name_t) i; return true; diff --git a/c/unpack.h b/c/unpack.h new file mode 100644 index 0000000..c69b9ad --- /dev/null +++ b/c/unpack.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define unpack_Nbit_(N) \ + static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \ + assert(s < N/8); \ + *v = (*v & (0xff << (s*8))) | (c << (s*8)); \ + } \ + static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \ + assert(s < N/8); \ + biner_unpack_l##N(v, c, N/8-s-1); \ + } +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define unpack_Nbit_(N) \ + static inline void biner_unpack_b##N(int##N##_t* v, uint8_t c, size_t s) { \ + assert(s < N/8); \ + *v = (*v & (0xff << (s*8))) | (c << (s*8)); \ + } \ + static inline void biner_unpack_l##N(int##N##_t* v, uint8_t c, size_t s) { \ + assert(s < N/8); \ + biner_unpack_b##N(v, c, N/8-s-1); \ + } +#else +# error "byte order unknown" +#endif + +unpack_Nbit_(8); +unpack_Nbit_(16); +unpack_Nbit_(32); +unpack_Nbit_(64); + +#undef unpack_Nbit_ diff --git a/zone.h b/c/zone.h similarity index 100% rename from zone.h rename to c/zone.h diff --git a/main.c b/main.c index 722c576..653123c 100644 --- a/main.c +++ b/main.c @@ -1,77 +1,17 @@ -#include #include #include #include +#include "./transpile.h" #include "./tree.h" -static inline void print_enum_( - const uint8_t* zone, const biner_tree_decl_t* decl) { - assert(zone != NULL); - assert(decl != NULL); - - printf("enum %s:\n", zone + decl->name); - const biner_tree_enum_member_t* member = - (const biner_tree_enum_member_t*) (zone + decl->enum_); - while ((uintptr_t) member != (uintptr_t) zone) { - printf(" %s\n", zone + member->name); - member = (const biner_tree_enum_member_t*) (zone + member->prev); - } -} - -static inline void print_struct_( - const uint8_t* zone, const biner_tree_decl_t* decl) { - assert(zone != NULL); - assert(decl != NULL); - - printf("struct %s:\n", zone + decl->name); - const biner_tree_struct_member_t* member = - (const biner_tree_struct_member_t*) (zone + decl->struct_); - while ((uintptr_t) member != (uintptr_t) zone) { - printf(" %2zu ", member->index); - const biner_tree_struct_member_type_t* type = - (const biner_tree_struct_member_type_t*) (zone + member->type); - if (type->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { - const biner_tree_decl_t* decl = - (const biner_tree_decl_t*) (zone + type->decl); - printf("%8s ", zone + decl->name); - } else { - printf("%8s ", - biner_tree_struct_member_type_name_string_map[type->name]); - } - if (member->condition == 0) { - printf("%s", zone + member->name); - } else { - printf("(%s)", zone + member->name); - } - printf("\n"); - member = (const biner_tree_struct_member_t*) (zone + member->prev); - } -} - int main(void) { const uint8_t* zone = biner_tree_parse(stdin); if (zone == NULL) return EXIT_FAILURE; - const biner_tree_root_t* root = (const biner_tree_root_t*) zone; - - const biner_tree_decl_t* decl = - (const biner_tree_decl_t*) (zone + root->decls); - while ((uintptr_t) decl != (uintptr_t) zone) { - switch (decl->type) { - case BINER_TREE_DECL_TYPE_CONST: - printf("const %s\n", zone + decl->name); - break; - case BINER_TREE_DECL_TYPE_ENUM: - print_enum_(zone, decl); - break; - case BINER_TREE_DECL_TYPE_STRUCT: - print_struct_(zone, decl); - break; - default: - ; - } - decl = (const biner_tree_decl_t*) (zone + decl->prev); - } + biner_transpile_c(&(biner_transpile_param_t) { + .zone = zone, + .dst = stdout, + }); return EXIT_SUCCESS; } diff --git a/transpile.h b/transpile.h new file mode 100644 index 0000000..88ba0cc --- /dev/null +++ b/transpile.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +typedef struct biner_transpile_param_t { + const uint8_t* zone; + FILE* dst; +} biner_transpile_param_t; + +bool +biner_transpile_c( + const biner_transpile_param_t* p +); diff --git a/transpile_c.c b/transpile_c.c new file mode 100644 index 0000000..f7dae3a --- /dev/null +++ b/transpile_c.c @@ -0,0 +1,500 @@ +#include "./transpile.h" + +#include +#include +#include +#include +#include +#include + +#include "./tree.h" + +#define PACK_CONTEXT_SUFFIX_ "_pack_context_t" +#define UNPACK_CONTEXT_SUFFIX_ "_unpack_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"}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F16] = {"f16", "float"}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F32] = {"f32", "float"}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F64] = {"f64", "double"}, +}; + +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); + +# define print_operator_(op) do { \ + if (e->operands.l) { \ + print_expr_(p, (const biner_tree_expr_t*) (p->zone+e->operands.l)); \ + } \ + fprintf(p->dst, op); \ + if (e->operands.r) { \ + print_expr_(p, (const biner_tree_expr_t*) (p->zone+e->operands.r)); \ + } \ + } while (0) + + 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; + case BINER_TREE_EXPR_TYPE_OPERATOR_EQUAL: + print_operator_("=="); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_NEQUAL: + print_operator_("!="); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_GREATER_EQUAL: + print_operator_(">="); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_LESS_EQUAL: + print_operator_("<="); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_GREATER: + print_operator_(">"); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_LESS: + print_operator_("<"); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_NOT: + print_operator_("!"); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_ADD: + print_operator_("+"); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_SUB: + print_operator_("-"); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_MUL: + print_operator_("*"); + break; + case BINER_TREE_EXPR_TYPE_OPERATOR_DIV: + print_operator_("/"); + break; + } + + fprintf(p->dst, ")"); + +# undef print_operator_ +} + +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, "union { "); + while ((uintptr_t*) m != (uintptr_t*) p->zone) { + const biner_tree_struct_member_type_t* t = + (const biner_tree_struct_member_type_t*) (p->zone+m->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+m->name); + } + m = (const biner_tree_struct_member_t*) (p->zone+m->prev); + } + fprintf(p->dst, "} subctx; "); +} + +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); + + 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, + "s->%s = malloc(sizeof(*s->%s)*ctx->count_max); ", + name, 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: + ; + } + + 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) { + const biner_tree_decl_t* d = + (const biner_tree_decl_t*) (info->p->zone+info->t->decl); + + fprintf(info->p->dst, "if ("); + print_fixed_decl_name_(info->p, (const char*) (info->p->zone+d->name)); + fprintf(info->p->dst, "_unpack(&ctx->subctx.%s, &s->%s%s, c)) { ", name, name, suffix); + } 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); + } + + 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; "); + 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; "); + break; + default: + fprintf(info->p->dst, "goto NEXT; "); + } + fprintf(info->p->dst, "} return false; "); + + 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_( + const biner_transpile_param_t* p, const biner_tree_struct_member_t* m) { + assert(p != NULL); + assert(m != NULL); + + 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, "}; "); + + fprintf(p->dst, + "if (ctx->step >= sizeof(steps_)/sizeof(steps_[0])) return true; "); + fprintf(p->dst, "goto *steps_[ctx->step]; "); + + struct_member_each_(p, m, print_struct_member_unpack_code_each_, SIZE_MAX); + + fprintf(p->dst, "NEXT: "); + fprintf(p->dst, "return ++ctx->step >= sizeof(steps_)/sizeof(steps_[0]); "); +} + +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 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_); + + 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_); + + print_typedef_header_(p, "enum", name, "_t"); + print_enum_member_decls_(p, body); + print_typedef_footer_(p, name, "_t"); + + 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_); + + print_typedef_header_(p, "struct", name, "_t"); + struct_member_each_(p, body, print_struct_member_decl_, SIZE_MAX); + print_typedef_footer_(p, name, "_t"); + + print_typedef_header_(p, "struct", name, PACK_CONTEXT_SUFFIX_); + print_struct_member_context_struct_(p, body, PACK_CONTEXT_SUFFIX_); + print_typedef_footer_(p, name, PACK_CONTEXT_SUFFIX_); + + print_typedef_header_(p, "struct", name, UNPACK_CONTEXT_SUFFIX_); + print_struct_member_context_struct_(p, body, UNPACK_CONTEXT_SUFFIX_); + print_typedef_footer_(p, name, UNPACK_CONTEXT_SUFFIX_); + + print_func_header_(p, "bool", name, "_unpack"); + print_fixed_decl_name_(p, name); + fprintf(p->dst, "_unpack_context_t* ctx, "); + print_fixed_decl_name_(p, name); + fprintf(p->dst, "_t* s, "); + fprintf(p->dst, "uint8_t c) { "); + print_struct_member_unpack_code_(p, body); + 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; +} diff --git a/tree.c b/tree.c index 310e3e5..5a6e8b6 100644 --- a/tree.c +++ b/tree.c @@ -8,22 +8,32 @@ #include #include -#include "./zone.h" +#include "./c/zone.h" #include "generated/biner.y.h" -const char* const biner_tree_struct_member_type_name_string_map +const biner_tree_struct_member_type_name_meta_t +biner_tree_struct_member_type_name_meta_map [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_] = { - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT8] = "uint8_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT16] = "uint16_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT32] = "uint32_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT64] = "uint64_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT8] = "int8_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT16] = "int16_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT32] = "int32_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT64] = "int64_t", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_FLOAT32] = "float", - [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_FLOAT64] = "double", + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU8] = {"lu8", 1}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU16] = {"lu16", 2}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU32] = {"lu32", 4}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU64] = {"lu64", 8}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI8] = {"li8", 1}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI16] = {"li16", 2}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI32] = {"li32", 4}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI64] = {"li64", 8}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU8] = {"bu8", 1}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU16] = {"bu16", 2}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU32] = {"bu32", 4}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU64] = {"bu64", 8}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI8] = {"bi8", 1}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI16] = {"bi16", 2}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI32] = {"bi32", 4}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI64] = {"bi64", 8}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F16] = {"f16", 2}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F32] = {"f32", 4}, + [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F64] = {"f64", 8}, }; biner_tree_parse_context_t biner_tree_parse_context_ = {0}; diff --git a/tree.h b/tree.h index 32f9cf8..1fc221a 100644 --- a/tree.h +++ b/tree.h @@ -8,7 +8,7 @@ #include #include -#include "./zone.h" +#include "./c/zone.h" typedef struct biner_tree_expr_t biner_tree_expr_t; typedef struct biner_tree_struct_member_t biner_tree_struct_member_t; @@ -46,22 +46,37 @@ typedef struct biner_tree_expr_t { } biner_tree_expr_t; typedef enum biner_tree_struct_member_type_name_t { - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT8, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT16, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT32, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_UINT64, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT8, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT16, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT32, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_INT64, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_FLOAT32, - BINER_TREE_STRUCT_MEMBER_TYPE_NAME_FLOAT64, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU8, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU16, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU32, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LU64, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI8, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI16, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI32, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_LI64, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU8, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU16, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU32, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BU64, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI8, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI16, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI32, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_BI64, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F16, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F32, + BINER_TREE_STRUCT_MEMBER_TYPE_NAME_F64, BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL, BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_, } biner_tree_struct_member_type_name_t; -extern const char* const biner_tree_struct_member_type_name_string_map +typedef struct biner_tree_struct_member_type_name_meta_t { + const char* name; + size_t size; +} biner_tree_struct_member_type_name_meta_t; + +extern const biner_tree_struct_member_type_name_meta_t +biner_tree_struct_member_type_name_meta_map [BINER_TREE_STRUCT_MEMBER_TYPE_NAME_MAX_]; typedef enum biner_tree_struct_member_type_qualifier_t {