diff --git a/ccodegen/datatypes.c b/ccodegen/datatypes.c index 0aa5579..3b56529 100644 --- a/ccodegen/datatypes.c +++ b/ccodegen/datatypes.c @@ -1,24 +1,14 @@ // 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" -internal inline void ctype_to_string(Str8 *dst, CType ctype); -internal inline void cqualifier_to_string(Str8 *dst, CQualifier cqualifier); -internal inline void cpointertype_to_string(Str8 *dst, CPointerType cpointertype); -internal inline void cpointer_to_string(Str8 *dst, const CPointer *cpointer); -internal inline void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval); -internal inline void cmacro_to_string(Str8 *dst, const CMacro *cmacro); - void cobject_to_string(Str8 *dst, const CObject *object) { - wapp_debug_assert(dst != NULL object != NULL, "`allocator`, `dst` and `object` should not be NULL"); - - if (object->kind >= COUNT_COBJECTKIND) { - return; - } + wapp_debug_assert(dst != NULL && object != NULL, "`allocator`, `dst` and `object` should not be NULL"); switch (object->kind) { case COBJECT_CTYPE: @@ -37,21 +27,27 @@ void cobject_to_string(Str8 *dst, const CObject *object) { 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: break; case COBJECT_CINCULDE: + cinclude_to_string(dst, &(object->object.c_include)); break; case COBJECT_CHEADER: break; @@ -62,22 +58,22 @@ void cobject_to_string(Str8 *dst, const CObject *object) { } } -internal inline void ctype_to_string(Str8 *dst, CType ctype) { +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]); } -internal inline void cqualifier_to_string(Str8 *dst, CQualifier cqualifier) { +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]); } -internal inline void cpointertype_to_string(Str8 *dst, CPointerType cpointertype) { +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]); } -internal inline void cpointer_to_string(Str8 *dst, const CPointer *cpointer) { +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; @@ -88,7 +84,7 @@ internal inline void cpointer_to_string(Str8 *dst, const CPointer *cpointer) { wapp_str8_varg(cqualifiers[cpointer->qualifier])); } -internal inline void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval) { +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(32); @@ -106,8 +102,42 @@ internal inline void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval) { wapp_str8_varg(tmp)); } -internal inline void cmacro_to_string(Str8 *dst, const CMacro *cmacro) { - wapp_debug_assert(dst != NULL && cenumval != NULL, "`dst` and `cmacro` should not be NULL"); +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(4096); + Str8 values = wapp_str8_buf(8192); + Str8 footer = wapp_str8_buf(4096); + Str8 tmp = wapp_str8_buf(4096); + + 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 @@ -118,3 +148,168 @@ internal inline void cmacro_to_string(Str8 *dst, const CMacro *cmacro) { 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(4096); + Str8 definition = wapp_str8_buf(8192); + + 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(8192); + 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(4096); + Str8 args = wapp_str8_buf(8192); + Str8 footer = wapp_str8_lit_ro("};\n"); + Str8 tmp = wapp_str8_buf(1024); + + 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(1024); + Str8 type = wapp_str8_buf(4096); + Str8 pointer = wapp_str8_buf(1024); + Str8 array = wapp_str8_buf(1024); + + 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 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(4096); + if (!cheaderinclude_to_string(&header_str, &(cinclude->header))) { return; } + + Str8 inc = wapp_str8_lit("#include "); + Str8 open_symbol = wapp_str8_buf(16); + Str8 close_symbol = wapp_str8_buf(16); + + 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)); +} + +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; +} diff --git a/ccodegen/datatypes.h b/ccodegen/datatypes.h index 4dc2533..8ac5e20 100644 --- a/ccodegen/datatypes.h +++ b/ccodegen/datatypes.h @@ -139,7 +139,7 @@ struct cmacro { struct cstruct { Str8 name; CArgList args; - Str8 *typedef_name; + Str8 typedef_name; }; struct cusertype { @@ -232,5 +232,20 @@ struct cobject { }; void cobject_to_string(Str8 *dst, const CObject *object); +void ctype_to_string(Str8 *dst, CType ctype); +void cqualifier_to_string(Str8 *dst, CQualifier cqualifier); +void cpointertype_to_string(Str8 *dst, CPointerType cpointertype); +void cpointer_to_string(Str8 *dst, const CPointer *cpointer); +void cenumval_to_string(Str8 *dst, const CEnumVal *cenumval); +void cenum_to_string(Str8 *dst, const CEnum *cenum); +void cmacro_to_string(Str8 *dst, const CMacro *cmacro); +void cstruct_to_string(Str8 *dst, const CStruct *cstruct); +void declare_cstruct(Str8 *dst, const CStruct *cstruct); +void define_cstruct(Str8 *dst, const CStruct *cstruct); +void cusertype_to_string(Str8 *dst, const CUserType *cusertype); +void cdatatype_to_string(Str8 *dst, const CDataType *cdatatype); +void carg_to_string(Str8 *dst, const CArg *carg); +void cinclude_to_string(Str8 *dst, const CInclude *cinclude); +b32 cheaderinclude_to_string(Str8 *dst, const CHeaderInclude *cheaderinclude); #endif // !DATATYPES_H