diff --git a/TODO.TXT b/TODO.TXT index 5277752..e42a658 100644 --- a/TODO.TXT +++ b/TODO.TXT @@ -12,5 +12,5 @@ X C transpiler for unpacking X C transpiler for packing X setup tests X add bitmanip operators - handling of overflown or negative expression +X handling of overflown or negative expression release 1.0.0 diff --git a/c/result.h b/c/result.h new file mode 100644 index 0000000..fe20140 --- /dev/null +++ b/c/result.h @@ -0,0 +1,10 @@ +#pragma once + +typedef enum biner_result_t { + BINER_RESULT_COMPLETED, + BINER_RESULT_CONTINUE, + + BINER_RESULT_ERROR_THRESHOULD_, + + BINER_RESULT_MEMORY_ERROR, +} biner_result_t; diff --git a/test/main.c b/test/main.c index 0fea754..ee44515 100644 --- a/test/main.c +++ b/test/main.c @@ -10,8 +10,15 @@ #include #include "../c/pack.h" +#include "../c/result.h" #include "../c/unpack.h" -#include "../c/zone.h" + +static inline void* biner_malloc_(size_t sz, void* udata) { + (void) udata; + + /* returning NULL can abort the unpacking */ + return malloc(sz); +} #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" @@ -67,10 +74,11 @@ int main(void) { .sex = SEX_CAT, .role = ROLE_STUDENT, - .property_count = 2, + .property_count = 3, .properties = (strpair_t[]) { - { .key = str_("like"), .value = str_("rat"), }, - { .key = str_("hate"), .value = str_("dog"), }, + { .key = str_("like"), .value = str_("rat"), }, + { .key = str_("hate"), .value = str_("dog"), }, + { .key = str_("empty"), .value = str_(""), }, }, .student = { @@ -85,13 +93,18 @@ int main(void) { user_t dst = {0}; size_t b = 0; - bool completed = false; - while (!completed) { + biner_result_t result = BINER_RESULT_CONTINUE; + while (result == BINER_RESULT_CONTINUE) { uint8_t c; - completed = user_pack(&pack_ctx, &src, &c); - if (user_unpack(&unpack_ctx, &dst, c) != completed) { + result = user_pack(&pack_ctx, &src, &c); + if (result >= BINER_RESULT_ERROR_THRESHOULD_) { + fprintf(stderr, "unexpected error happened\n"); + return EXIT_FAILURE; + } + + if (user_unpack(&unpack_ctx, &dst, c) != result) { fprintf(stderr, "fail at the %zu byte: ", b); - if (completed) { + if (result == BINER_RESULT_COMPLETED) { fprintf(stderr, "pack function finsihed but unpack not\n"); } else { fprintf(stderr, "unpack function finsihed but pack not\n"); diff --git a/transpile_c.c b/transpile_c.c index 96500c2..62e488e 100644 --- a/transpile_c.c +++ b/transpile_c.c @@ -290,6 +290,7 @@ static void print_struct_member_context_struct_( 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; @@ -342,6 +343,8 @@ static void print_struct_member_pack_code_each_( 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: @@ -353,7 +356,7 @@ static void print_struct_member_pack_code_each_( 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_") {0}; "); + fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; "); } fprintf(info->p->dst, "body%zu: ", info->m->index); @@ -377,9 +380,11 @@ static void print_struct_member_pack_code_each_( } if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { - fprintf(info->p->dst, "if ("); + 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, "_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, @@ -409,11 +414,11 @@ static void print_struct_member_pack_code_each_( 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_") {0}; "); + fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; "); } fprintf(info->p->dst, "ctx->byte = 0; "); } - fprintf(info->p->dst, "} return false; "); + fprintf(info->p->dst, "} return BINER_RESULT_CONTINUE; "); if (info->m->condition != 0) { fprintf(info->p->dst, "} "); @@ -445,8 +450,12 @@ static void print_struct_member_unpack_code_each_( 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); ", + "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: @@ -458,7 +467,7 @@ static void print_struct_member_unpack_code_each_( 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_") {0}; "); + fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; "); } fprintf(info->p->dst, "body%zu: ", info->m->index); @@ -482,9 +491,11 @@ static void print_struct_member_unpack_code_each_( } if (info->t->name == BINER_TREE_STRUCT_MEMBER_TYPE_NAME_USER_DECL) { - fprintf(info->p->dst, "if ("); + 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, "_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, @@ -514,11 +525,11 @@ static void print_struct_member_unpack_code_each_( 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_") {0}; "); + fprintf(info->p->dst, CONTEXT_SUFFIX_") { .udata = ctx->udata, }; "); } fprintf(info->p->dst, "ctx->byte = 0; "); } - fprintf(info->p->dst, "} return false; "); + fprintf(info->p->dst, "} return BINER_RESULT_CONTINUE; "); if (info->m->condition != 0) { fprintf(info->p->dst, "} "); @@ -536,20 +547,45 @@ static inline void print_struct_member_iteration_code_( 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 true; "); + "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]); "); + fprintf(p->dst, + "return (++ctx->step >= sizeof(steps_)/sizeof(steps_[0]))?" + " BINER_RESULT_COMPLETED:" + " BINER_RESULT_CONTINUE; "); } static void print_decls_( @@ -597,7 +633,7 @@ static void print_decls_( print_struct_member_context_struct_(p, body, CONTEXT_SUFFIX_); print_typedef_footer_(p, name, CONTEXT_SUFFIX_); - print_func_header_(p, "bool", name, "_pack"); + 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 "); @@ -608,7 +644,7 @@ static void print_decls_( p, body, &print_struct_member_pack_code_each_); fprintf(p->dst, "}\n"); - print_func_header_(p, "bool", name, "_unpack"); + 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);