// vim:fileencoding=utf-8:foldmethod=marker #include "datatypes.h" #include "dbl_list.h" #include "type_enums.h" #include "wapp_core.h" #define ERR_MSG "Not enough capacity in dst buffer" #define CFILE_DISCLAIMER "/**\n" \ " * THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.\n" \ " */\n\n" void cobject_to_string(Str8 *dst, const CObject *object) { wapp_debug_assert(dst != NULL && object != NULL, "`allocator`, `dst` and `object` should not be NULL"); switch (object->kind) { case COBJECT_CTYPE: ctype_to_string(dst, object->object.c_type); break; case COBJECT_CQUALIFIER: cqualifier_to_string(dst, object->object.c_qualifier); break; case COBJECT_CPOINTERTYPE: cpointertype_to_string(dst, object->object.c_pointertype); break; case COBJECT_CPOINTER: cpointer_to_string(dst, &(object->object.c_pointer)); break; case COBJECT_CENUMVAL: cenumval_to_string(dst, &(object->object.c_enumval)); break; case COBJECT_CENUM: cenum_to_string(dst, &(object->object.c_enum)); break; case COBJECT_CMACRO: cmacro_to_string(dst, &(object->object.c_macro)); break; case COBJECT_CSTRUCT: cstruct_to_string(dst, &(object->object.c_struct)); break; case COBJECT_CUSERTYPE: cusertype_to_string(dst, &(object->object.c_usertype)); break; case COBJECT_CDATATYPE: cdatatype_to_string(dst, &(object->object.c_datatype)); break; case COBJECT_CARG: carg_to_string(dst, &(object->object.c_arg)); break; case COBJECT_CFUNC: cfunc_to_string(dst, &(object->object.c_func)); break; case COBJECT_CINCULDE: cinclude_to_string(dst, &(object->object.c_include)); break; case COBJECT_CHEADER: break; case COBJECT_CSOURCE: break; default: break; } } void ctype_to_string(Str8 *dst, CType ctype) { wapp_runtime_assert(ctypes[ctype].size <= dst->capacity, ERR_MSG); wapp_str8_copy_str8_capped(dst, &ctypes[ctype]); } void cqualifier_to_string(Str8 *dst, CQualifier cqualifier) { wapp_runtime_assert(cqualifiers[cqualifier].size <= dst->capacity, ERR_MSG); wapp_str8_copy_str8_capped(dst, &cqualifiers[cqualifier]); } void cpointertype_to_string(Str8 *dst, CPointerType cpointertype) { wapp_runtime_assert(cpointertypes[cpointertype].size <= dst->capacity, ERR_MSG); wapp_str8_copy_str8_capped(dst, &cpointertypes[cpointertype]); } void cpointer_to_string(Str8 *dst, const CPointer *cpointer) { wapp_debug_assert(dst != NULL && cpointer != NULL, "`dst` and `cpointer` should not be NULL"); u64 total_size = cpointertypes[cpointer->type].size + cqualifiers[cpointer->qualifier].size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(cpointertypes[cpointer->type]), wapp_str8_varg(cqualifiers[cpointer->qualifier])); } void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval) { wapp_debug_assert(dst != NULL && cenumval != NULL, "`dst` and `cenumval` should not be NULL"); Str8 tmp = wapp_str8_buf(CCGEN_BUF_TINY); u64 tmp_size = 0; if (cenumval->value != NULL) { wapp_str8_format(&tmp, " = %d", *(cenumval->value)); tmp_size = tmp.size; } u64 total_size = cenumval->name.size + tmp_size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(cenumval->name), wapp_str8_varg(tmp)); } void cenum_to_string(Str8 *dst, const CEnum *cenum) { wapp_debug_assert(dst != NULL && cenum != NULL, "`dst` and `cenum` should not be NULL"); Str8 header = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 values = wapp_str8_buf(CCGEN_BUF_MAX); Str8 footer = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 tmp = wapp_str8_buf(CCGEN_BUF_LARGE); if (cenum->add_typedef) { wapp_str8_copy_cstr_capped(&header, "typedef enum {\n"); wapp_str8_format(&footer, "} " WAPP_STR8_SPEC ";\n", wapp_str8_varg(cenum->name)); } else { wapp_str8_format(&header, "enum " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cenum->name)); wapp_str8_copy_cstr_capped(&footer, "};\n"); } for (u64 i = 0; i < cenum->values.node_count; ++i) { cenumval_to_string(&tmp, wapp_cenumval_list_get(&(cenum->values), i)->item); // Add 4 for extra characters wapp_runtime_assert(tmp.size + 4 <= values.capacity - values.size, ERR_MSG); wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(" ")); wapp_str8_concat_capped(&values, &tmp); wapp_str8_concat_capped(&values, &wapp_str8_lit_ro(",\n")); } u64 total_size = header.size + values.size + footer.size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(header), wapp_str8_varg(values), wapp_str8_varg(footer)); } void cmacro_to_string(Str8 *dst, const CMacro *cmacro) { wapp_debug_assert(dst != NULL && cmacro != NULL, "`dst` and `cmacro` should not be NULL"); Str8 def = wapp_str8_lit("#define "); u64 total_size = def.size + cmacro->name.size + cmacro->value.size + 1; // Add 1 for newline wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC "\n", wapp_str8_varg(def), wapp_str8_varg(cmacro->name), wapp_str8_varg(cmacro->value)); } void cstruct_to_string(Str8 *dst, const CStruct *cstruct) { wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL"); Str8 declaration = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 definition = wapp_str8_buf(CCGEN_BUF_MAX); declare_cstruct(&declaration, cstruct); define_cstruct(&definition, cstruct); u64 total_size = declaration.size + definition.size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(declaration), wapp_str8_varg(definition)); } void declare_cstruct(Str8 *dst, const CStruct *cstruct) { wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL"); Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX); wapp_str8_format(&tmp, "typedef struct " WAPP_STR8_SPEC " " WAPP_STR8_SPEC ";\n", wapp_str8_varg(cstruct->name), wapp_str8_varg(cstruct->typedef_name.size > 0 ? cstruct->typedef_name : cstruct->name)); wapp_runtime_assert(tmp.size <= dst->capacity, ERR_MSG); wapp_str8_copy_str8_capped(dst, &tmp); } void define_cstruct(Str8 *dst, const CStruct *cstruct) { wapp_debug_assert(dst != NULL && cstruct != NULL, "`dst` and `cstruct` should not be NULL"); Str8 definition = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 args = wapp_str8_buf(CCGEN_BUF_MAX); Str8 footer = wapp_str8_lit_ro("};\n"); Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM); wapp_str8_format(&definition, "struct " WAPP_STR8_SPEC " {\n", wapp_str8_varg(cstruct->name)); for (u64 i = 0; i < cstruct->args.node_count; ++i) { carg_to_string(&tmp, wapp_carg_list_get(&(cstruct->args), i)->item); // Add 4 for extra characters wapp_runtime_assert(tmp.size + 4 <= args.capacity - args.size, ERR_MSG); wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(" ")); wapp_str8_concat_capped(&args, &tmp); wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(";\n")); } u64 total_size = definition.size + args.size + footer.size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(definition), wapp_str8_varg(args), wapp_str8_varg(footer)); } void cusertype_to_string(Str8 *dst, const CUserType *cusertype) { wapp_debug_assert(dst != NULL && cusertype != NULL, "`dst` and `cusertype` should not be NULL"); switch (cusertype->kind) { case CUSERTYPE_CENUM: cenum_to_string(dst, &(cusertype->type.c_enum)); break; case CUSERTYPE_CSTRUCT: cstruct_to_string(dst, &(cusertype->type.c_struct)); break; default: break; } } void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype) { wapp_debug_assert(dst != NULL && cdatatype != NULL, "`dst` and `cdatatype` should not be NULL"); switch (cdatatype->kind) { case CDATATYPE_CTYPE: ctype_to_string(dst, cdatatype->type.c_type); break; case CDATATYPE_CUSERTYPE: cusertype_to_string(dst, &(cdatatype->type.c_usertype)); break; case CDATATYPE_STR: wapp_runtime_assert(cdatatype->type.str.size <= dst->capacity, ERR_MSG); wapp_str8_copy_str8_capped(dst, &(cdatatype->type.str)); break; default: break; } } void carg_to_string(Str8 *dst, const CArg *carg) { wapp_debug_assert(dst != NULL && carg != NULL, "`dst` and `carg` should not be NULL"); Str8 qualifier = wapp_str8_buf(CCGEN_BUF_MEDIUM); Str8 type = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 pointer = wapp_str8_buf(CCGEN_BUF_MEDIUM); Str8 array = wapp_str8_buf(CCGEN_BUF_MEDIUM); cqualifier_to_string(&qualifier, carg->qualifier); cdatatype_to_string(&type, &(carg->type)); wapp_str8_concat_capped(&type, &wapp_str8_lit_ro(" ")); cpointer_to_string(&pointer, &(carg->pointer)); if (carg->is_array) { wapp_str8_copy_cstr_capped(&array, "[]"); } u64 total_size = qualifier.size + type.size + pointer.size + array.size + carg->name.size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC, wapp_str8_varg(qualifier), wapp_str8_varg(type), wapp_str8_varg(pointer), wapp_str8_varg(carg->name), wapp_str8_varg(array)); } void cfunc_to_string(Str8 *dst, const CFunc *cfunc) { wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL"); Str8 qualifiers = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 args = wapp_str8_buf(CCGEN_BUF_LARGE); Str8 ret_type = wapp_str8_buf(CCGEN_BUF_SMALL); Str8 pointer = wapp_str8_buf(CCGEN_BUF_SMALL); Str8 tmp = wapp_str8_buf(CCGEN_BUF_MEDIUM); CQualifier *qf = NULL; CArg *arg = NULL; for (u64 i = 0; i < cfunc->qualifiers.node_count; ++i) { qf = wapp_cqualifier_list_get(&(cfunc->qualifiers), i)->item; if (*qf == CQUALIFIER_NONE) { continue; } cqualifier_to_string(&tmp, *qf); wapp_runtime_assert(tmp.size + 1 <= qualifiers.capacity - qualifiers.size, ERR_MSG); if (qualifiers.size > 0) { wapp_str8_concat_capped(&qualifiers, &wapp_str8_lit_ro(" ")); } wapp_str8_concat_capped(&qualifiers, &tmp); } for (u64 i = 0; i < cfunc->args.node_count; ++i) { arg = wapp_carg_list_get(&(cfunc->args), i)->item; carg_to_string(&tmp, arg); wapp_runtime_assert(tmp.size + 2 <= args.capacity - args.size, ERR_MSG); wapp_str8_concat_capped(&args, &tmp); if (i + 1 < cfunc->args.node_count) { wapp_str8_concat_capped(&args, &wapp_str8_lit_ro(", ")); } } cdatatype_to_string(&ret_type, &(cfunc->ret_type)); cpointer_to_string(&pointer, &(cfunc->pointer)); u64 total_size = cfunc->name.size + qualifiers.size + args.size + ret_type.size + pointer.size + 4; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC " " WAPP_STR8_SPEC WAPP_STR8_SPEC "(" WAPP_STR8_SPEC ")", wapp_str8_varg(qualifiers), wapp_str8_varg(ret_type), wapp_str8_varg(pointer), wapp_str8_varg(cfunc->name), wapp_str8_varg(args)); } void declare_cfunc(Str8 *dst, const CFunc *cfunc) { wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL"); Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX); cfunc_to_string(&tmp, cfunc); wapp_runtime_assert(tmp.size + 2 <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC ";\n", wapp_str8_varg(tmp)); } void define_cfunc(Str8 *dst, const CFunc *cfunc) { wapp_debug_assert(dst != NULL && cfunc != NULL, "`dst` and `cfunc` should not be NULL"); Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX); cfunc_to_string(&tmp, cfunc); wapp_runtime_assert(tmp.size + cfunc->body.size + 8 <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC " {\n" WAPP_STR8_SPEC "\n}\n\n", wapp_str8_varg(tmp), wapp_str8_varg(cfunc->body)); } void cinclude_to_string(Str8 *dst, const CInclude *cinclude) { wapp_debug_assert(dst != NULL && cinclude != NULL, "`dst` and `cinclude` should not be NULL"); Str8 header_str = wapp_str8_buf(CCGEN_BUF_LARGE); if (!cheaderinclude_to_string(&header_str, &(cinclude->header))) { return; } Str8 inc = wapp_str8_lit("#include "); Str8 open_symbol = wapp_str8_buf(CCGEN_BUF_MIN); Str8 close_symbol = wapp_str8_buf(CCGEN_BUF_MIN); if (cinclude->is_local) { wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("\"")); wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro("\"")); if (cinclude->same_dir) { wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("./")); } } else { wapp_str8_concat_capped(&open_symbol, &wapp_str8_lit_ro("<")); wapp_str8_concat_capped(&close_symbol, &wapp_str8_lit_ro(">")); } u64 total_size = header_str.size + inc.size + open_symbol.size + close_symbol.size; wapp_runtime_assert(total_size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC WAPP_STR8_SPEC "\n", wapp_str8_varg(inc), wapp_str8_varg(open_symbol), wapp_str8_varg(header_str), wapp_str8_varg(close_symbol)); } void cheader_to_string(Str8 *dst, const CHeader *cheader) { wapp_debug_assert(dst != NULL && cheader != NULL, "`dst` and `cheader` should not be NULL"); Allocator arena = wapp_mem_arena_allocator_init(MB(64)); Str8 *output = wapp_str8_alloc_buf(&arena, KB(32)); wapp_runtime_assert(output != NULL, "Failed to allocate buffer"); Str8 header_guard_name = wapp_str8_buf(CCGEN_BUF_SMALL); Str8 tmp = wapp_str8_buf(CCGEN_BUF_MAX); // ADD HEADER GUARD AND START C LINKAGE wapp_str8_to_upper(&header_guard_name, &(cheader->name)); wapp_str8_concat_capped(&header_guard_name, &wapp_str8_lit_ro("_H")); wapp_str8_format(&tmp, "#ifndef " WAPP_STR8_SPEC "\n#define " WAPP_STR8_SPEC "\n\n" "#ifdef WAPP_PLATFORM_CPP\nBEGIN_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n", wapp_str8_varg(header_guard_name), wapp_str8_varg(header_guard_name)); wapp_str8_alloc_concat(&arena, output, &tmp); for (u64 i = 0; i < cheader->includes.node_count; ++i) { cinclude_to_string(&tmp, wapp_cinclude_list_get(&(cheader->includes), i)->item); wapp_str8_alloc_concat(&arena, output, &tmp); } if (cheader->includes.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); } for (u64 i = 0; i < cheader->macros.node_count; ++i) { cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->macros), i)->item); wapp_str8_alloc_concat(&arena, output, &tmp); } if (cheader->macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); } if (cheader->cpp_macros.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#ifdef WAPP_PLATFORM_CPP\n")); for (u64 i = 0; i < cheader->cpp_macros.node_count; ++i) { cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->cpp_macros), i)->item); wapp_str8_alloc_concat(&arena, output, &tmp); } wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#else\n")); for (u64 i = 0; i < cheader->c_macros.node_count; ++i) { cmacro_to_string(&tmp, wapp_cmacro_list_get(&(cheader->c_macros), i)->item); wapp_str8_alloc_concat(&arena, output, &tmp); } wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("#endif // !WAPP_PLATFORM_CPP\n\n")); } for (u64 i = 0; i < cheader->decl_types.node_count; ++i) { declare_cstruct(&tmp, wapp_cstruct_list_get(&(cheader->decl_types), i)->item); wapp_str8_alloc_concat(&arena, output, &tmp); } if (cheader->decl_types.node_count > 0) { wapp_str8_alloc_concat(&arena, output, &wapp_str8_lit_ro("\n")); } for (u64 i = 0; i < cheader->types.node_count; ++i) { cusertype_to_string(&tmp, wapp_cusertype_list_get(&(cheader->types), i)->item); wapp_str8_concat_capped(&tmp, &wapp_str8_lit_ro("\n")); wapp_str8_alloc_concat(&arena, output, &tmp); } for (u64 i = 0; i < cheader->funcs.node_count; ++i) { declare_cfunc(&tmp, wapp_cfunc_list_get(&(cheader->funcs), i)->item); wapp_str8_alloc_concat(&arena, output, &tmp); } // END C LINKAGE AND CLOSE HEADER GUARD wapp_str8_format(&tmp, "\n#ifdef WAPP_PLATFORM_CPP\nEND_C_LINKAGE\n#endif // !WAPP_PLATFORM_CPP\n\n" "#endif // !" WAPP_STR8_SPEC "\n", wapp_str8_varg(header_guard_name)); wapp_str8_alloc_concat(&arena, output, &tmp); wapp_runtime_assert(output->size <= dst->capacity, ERR_MSG); wapp_str8_copy_str8_capped(dst, output); wapp_mem_arena_allocator_destroy(&arena); } void csource_to_string(Str8 *dst, const CSource *csource) { (void)dst; (void)csource; } b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude) { wapp_debug_assert(dst != NULL && cheaderinclude != NULL, "`dst` and `cheaderinclude` should not be NULL"); switch (cheaderinclude->kind) { case C_HEADER_INCLUDE_STR: wapp_runtime_assert(cheaderinclude->header.name.size <= dst->capacity, ERR_MSG); wapp_str8_format(dst, WAPP_STR8_SPEC, wapp_str8_varg(cheaderinclude->header.name)); return true; case C_HEADER_INCLUDE_HEADER: // Take extension into account wapp_runtime_assert(cheaderinclude->header.header.name.size + 2 <= dst->capacity, ERR_MSG); wapp_str8_format( dst, WAPP_STR8_SPEC ".%s", wapp_str8_varg(cheaderinclude->header.header.name), cheaderinclude->header.header.extension == CFILE_EXT_H ? "h" : "c" ); return true; default: return false; } return false; }