feat: use dynamic arrays and string builder

This commit is contained in:
2026-01-25 18:37:41 +01:00
parent 959cac75eb
commit b6c57c2741

84
cmeta.h
View File

@@ -15,21 +15,6 @@ typedef struct {
} Struct_Info;
// AUTO GENERATED CODE //
static Struct_Info foo_struct_info = { // cmeta.h:214
.name = "Foo_Struct", // cmeta.h:215
.fields_count = 1, // cmeta.h:216
.fields = (Field_Info[1]) { // cmeta.h:217
{ .type = "int", .name = "int_field" }, // cmeta.h:219
}, // cmeta.h:221
}; // cmeta.h:222
static Struct_Info bar_struct_info = { // cmeta.h:214
.name = "Bar_Struct", // cmeta.h:215
.fields_count = 2, // cmeta.h:216
.fields = (Field_Info[2]) { // cmeta.h:217
{ .type = "int", .name = "int_field" }, // cmeta.h:219
{ .type = "long", .name = "long_fields" }, // cmeta.h:219
}, // cmeta.h:221
}; // cmeta.h:222
// AUTO GENERATED CODE //
// #define CMETA_COMPTIME
@@ -51,12 +36,24 @@ typedef struct {
char* name;
} Parsed_Field_Info;
typedef struct {
Parsed_Field_Info* items;
size_t count;
size_t capacity;
} Parsed_Field_Infos;
typedef struct {
char* name;
size_t fields_count;
Parsed_Field_Info *fields;
} Parsed_Struct_Info;
typedef struct {
Parsed_Struct_Info* items;
size_t count;
size_t capacity;
} Parsed_Struct_Infos;
typedef struct {
char* data;
size_t capacity;
@@ -81,6 +78,18 @@ void sb_append(String_Builder* sb, const char* data) {
sb->data[sb->length] = '\0';
}
#define da_append(da, item) \
do { \
if ((da)->count + 1 > (da)->capacity) { \
size_t new_capacity = (da)->capacity == 0 ? 64 : (da)->capacity * 2; \
while ((da)->count + 1 > new_capacity) { \
new_capacity *= 2; \
} \
(da)->items = realloc((da)->items, new_capacity * sizeof(*(da)->items)); \
} \
(da)->items[(da)->count++] = (item); \
} while (0) \
bool lexer_expect_keyword(const char* expected) {
stb_c_lexer_get_token(&lexer);
@@ -132,8 +141,7 @@ bool parse_struct(Parsed_Struct_Info* info) {
bool result = false;
char* name = NULL;
size_t fields_count = 0;
Parsed_Field_Info fields[16] = {0}; // TODO: use dynamic array
Parsed_Field_Infos fields = {0};
if (!lexer_expect_keyword("typedef")) goto fail;
if (!lexer_expect_keyword("struct")) goto fail;
@@ -155,9 +163,11 @@ bool parse_struct(Parsed_Struct_Info* info) {
if (!lexer_expect(CLEX_id, "field name")) goto fail;
char* field_name = strdup(lexer.string);
fields[fields_count].type = field_type;
fields[fields_count].name = field_name;
fields_count += 1;
Parsed_Field_Info field = {
.type = field_type,
.name = field_name,
};
da_append(&fields, field);
if(!lexer_expect(';', NULL)) goto fail;
}
@@ -166,21 +176,22 @@ bool parse_struct(Parsed_Struct_Info* info) {
name = strdup(lexer.string);
info->name = name;
info->fields_count = fields_count;
info->fields = (Parsed_Field_Info*)calloc(fields_count, sizeof(Parsed_Field_Info));
for(size_t i = 0; i < fields_count; i += 1) {
info->fields[i].type = fields[i].type;
info->fields[i].name = fields[i].name;
info->fields_count = fields.count;
info->fields = (Parsed_Field_Info*)calloc(info->fields_count, sizeof(Parsed_Field_Info));
for(size_t i = 0; i < info->fields_count; i += 1) {
info->fields[i].type = fields.items[i].type;
info->fields[i].name = fields.items[i].name;
}
result = true;
fail:
if(!result) {
free(name);
for(size_t i = 0; i < fields_count; i += 1) {
free(fields[i].name);
free(fields[i].type);
for(size_t i = 0; i < fields.count; i += 1) {
free(fields.items[i].name);
free(fields.items[i].type);
}
free(fields.items);
}
return result;
@@ -254,7 +265,7 @@ fail:
return result;
}
bool generate_output_file(const char* output_path, Parsed_Struct_Info *struct_infos, size_t struct_infos_count) {
bool generate_output_file(const char* output_path, Parsed_Struct_Infos struct_infos) {
const char* GENERATION_MARK = "// AUTO GENERATED CODE //\n";
const size_t GENERATION_MARK_LEN = strlen(GENERATION_MARK);
@@ -287,8 +298,8 @@ bool generate_output_file(const char* output_path, Parsed_Struct_Info *struct_in
// write up to the generation mark, including it
fwrite(header_content, generate_begin + GENERATION_MARK_LEN - header_content, 1, stream);
for (size_t i = 0; i < struct_infos_count; i += 1) {
generate_struct_info(stream, struct_infos[i]);
for (size_t i = 0; i < struct_infos.count; i += 1) {
generate_struct_info(stream, struct_infos.items[i]);
}
fwrite(generate_end, strlen(generate_end), 1, stream);
@@ -315,7 +326,6 @@ bool preprocess_file(const char* file_path, String_Builder* result) {
size_t line_num = 0;
char file_name[512];
// TODO: use dynamic array instead
size_t cursor = 0;
result->length = 0;
@@ -351,8 +361,7 @@ bool process_file(const char* input_file) {
stb_c_lexer_init(&lexer, input_content.data, input_content.data + input_content.length, string_store, sizeof(string_store) / sizeof(char));
// find and parse all structs
size_t struct_infos_count = 0;
Parsed_Struct_Info struct_infos[16]; // TODO: use dynamic array
Parsed_Struct_Infos struct_infos = {0};
while (true) {
char* mark = lexer.parse_point;
@@ -361,13 +370,14 @@ bool process_file(const char* input_file) {
if (lexer.token == CLEX_id && strcmp(lexer.string, "typedef") == 0) {
lexer.parse_point = mark;
if (parse_struct(&struct_infos[struct_infos_count])) {
struct_infos_count += 1;
Parsed_Struct_Info struct_info = {0};
if (parse_struct(&struct_info)) {
da_append(&struct_infos, struct_info);
}
}
}
if (!generate_output_file(__FILE__, struct_infos, struct_infos_count)) return false;
if (!generate_output_file(__FILE__, struct_infos)) return false;
return true;
}