From 867a273e22d6ea2953529099634e672bfa3e6722 Mon Sep 17 00:00:00 2001 From: Slendi Date: Fri, 25 Jul 2025 23:21:33 +0300 Subject: [PATCH] Add basic ast_to_value, make POSIX optional Signed-off-by: Slendi --- CMakeLists.txt | 7 +++ flake.nix | 1 + include/dcfg.h | 12 ++++ src/dcfg.c | 161 +++++++++++++++++++++++++++++++++++++++++++++---- tools/loc.sh | 4 ++ 5 files changed, 173 insertions(+), 12 deletions(-) create mode 100755 tools/loc.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e6c510..3b46b4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_C_EXTENSIONS OFF) option(DCFG_BUILD_SHARED "Build DCFG as a shared library" ON) option(DCFG_BUILD_STATIC "Build DCFG as a static library" OFF) option(DCFG_PTHREAD_SUPPORT "Enable pthreads support" ON) +option(DCFG_POSIX_SUPPORT "Enable POSIX support" ON) find_package(Threads) @@ -24,6 +25,9 @@ if(DCFG_BUILD_SHARED) target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads) target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_PTHREAD_SUPPORT) endif() + if (DCFG_POSIX_SUPPORT) + target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_POSIX_SUPPORT) + endif() set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "dcfg") install(TARGETS ${PROJECT_NAME} DESTINATION lib) @@ -38,6 +42,9 @@ if(DCFG_BUILD_STATIC) target_link_libraries(${PROJECT_NAME}_static PRIVATE Threads::Threads) target_compile_definitions(${PROJECT_NAME}_static PRIVATE DCFG_PTHREAD_SUPPORT) endif() + if (DCFG_POSIX_SUPPORT) + target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_POSIX_SUPPORT) + endif() set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME "dcfg") install(TARGETS ${PROJECT_NAME}_static DESTINATION lib) diff --git a/flake.nix b/flake.nix index 796e38c..946a1ad 100644 --- a/flake.nix +++ b/flake.nix @@ -27,6 +27,7 @@ clang-tools lldb pkg-config + tokei ]; }; } diff --git a/include/dcfg.h b/include/dcfg.h index 1f52fb6..a6f8968 100644 --- a/include/dcfg.h +++ b/include/dcfg.h @@ -20,9 +20,21 @@ typedef struct dcfg_StringView { typedef void *(*dcfg_AllocFn)(size_t); // This should automatically zero memory. typedef void (*dcfg_FreeFn)(void *); +typedef char *(*dcfg_RealpathFn)(char const *); +typedef void *(*dcfg_FopenFn)(char const *, char const *); +typedef int (*dcfg_FseekFn)(void *, size_t, int); +typedef long (*dcfg_FtellFn)(void *); + typedef struct dcfg_InstanceCreateInfo { + // Default using libc dcfg_AllocFn alloc; dcfg_FreeFn free; + + // If POSIX support is enabled, all of those are defined if NULL. + dcfg_RealpathFn realpath; + dcfg_FopenFn fopen; + dcfg_FseekFn fseek; + dcfg_FtellFn ftell; } dcfg_InstanceCreateInfo; typedef enum dcfg_ValueKind { diff --git a/src/dcfg.c b/src/dcfg.c index 47dc7c2..b4f9467 100644 --- a/src/dcfg.c +++ b/src/dcfg.c @@ -4,7 +4,16 @@ #include "vendor/utf8proc.h" #include "vendor/vec.h" -#define _POSIX_C_SOURCE 200809L +#ifdef DCFG_POSIX_SUPPORT +#ifdef __sun +// FIXME: Fix this stupid shit! +#error "realpath() is dumb and stupid on sun. sorry not sorry." +#endif +#define _XOPEN_SOURCE 200809L +#else +#define _POSIX_C_SOURCE 0L +#endif + #include #include #include @@ -123,35 +132,39 @@ typedef struct { typedef struct { ValueObjectEntry *entryv; - size_t entryc; } ValueObject; typedef struct { - Value *valuev; - size_t valuec; + Value **valuev; } ValueArray; +typedef struct { + StringView *argv; + Value *body; +} ValueFunctionF; + typedef struct { bool is_builtin; union { Value *(*bi)(Value **argv, size_t argc); - Value *v; + ValueFunctionF f; } v; } ValueFunction; typedef struct { Value *function; Value **argv; - size_t argc; } ValueFunctionCall; struct dcfg_Value { + Instance *instance; dcfg_ValueType type; SourceLocation location; union { int64_t i; double r; + bool b; StringView s; StringView p; ValueObject o; @@ -166,6 +179,10 @@ struct dcfg_Instance { dcfg_AllocFn alloc; dcfg_FreeFn free; + dcfg_RealpathFn realpath; + dcfg_FopenFn fopen; + dcfg_FseekFn fseek; + dcfg_FtellFn ftell; char last_error[256]; }; @@ -175,6 +192,13 @@ struct dcfg_Instance { static void *alloc(size_t size) { return calloc(1, size); } +#ifdef DCFG_POSIX_SUPPORT +static char *realpath_(char const *s) { return realpath(s, NULL); } +void *fopen_(char const *f, char const *a) { return fopen(f, a); } +int fseek_(void *f, size_t p, int o) { return fseek(f, p, o); } +long ftell_(void *f) { return ftell(f); } +#endif + dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) { assert(create_info); @@ -192,6 +216,28 @@ dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) { if (!instance->free) { instance->free = free; } +#ifdef DCFG_POSIX_SUPPORT + if (!instance->realpath) { + instance->realpath = realpath_; + } + if (!instance->fopen) { + instance->fopen = fopen_; + } + if (!instance->fseek) { + instance->fseek = fseek_; + } + if (!instance->ftell) { + instance->ftell = ftell_; + } +#endif + + assert(instance->alloc); + assert(instance->free); + assert(instance->realpath); + assert(instance->fopen); + assert(instance->fseek); + assert(instance->ftell); + return instance; } @@ -899,19 +945,102 @@ AST *Parser_parse(Parser *parser) { return parser_parse_value(parser); } #define ALLOC(sz) (instance->alloc((sz))) #define FREE(ptr) (instance->free((ptr))) +Value *ast_to_value(dcfg_Instance *instance, AST *root) { + Value *value = ALLOC(sizeof(*value)); + value->instance = instance; + if (root->kind == ASTKind_Key) { + // FIXME: Implement + FREE(value); + return NULL; + } else if (root->kind == ASTKind_Path) { + value->type = dcfg_ValueType_Path; + value->v.p = root->v.p; + } else if (root->kind == ASTKind_Boolean) { + value->type = dcfg_ValueType_Boolean; + value->v.b = root->v.b; + } else if (root->kind == ASTKind_Integer) { + value->type = dcfg_ValueType_Integer; + value->v.i = root->v.i; + } else if (root->kind == ASTKind_Real) { + value->type = dcfg_ValueType_Real; + value->v.r = root->v.r; + } else if (root->kind == ASTKind_Block) { + // FIXME: Implement + FREE(value); + return NULL; + } else if (root->kind == ASTKind_Array) { + value->type = dcfg_ValueType_Array; + value->v.a.valuev = vector_create(); + for (size_t i = 0; i < vector_size(root->v.a.childv); i++) { + Value *v = ast_to_value(instance, root->v.a.childv[i]); + if (!v) { + for (size_t i = 0; i < vector_size(value->v.a.valuev); i++) { + dcfg_destroy(value->v.a.valuev[i]); + } + vector_free(value->v.a.valuev); + FREE(value); + return NULL; + } + vector_add(&value->v.a.valuev, v); + } + } else if (root->kind == ASTKind_Function) { + value->type = dcfg_ValueType_Function; + value->v.f.is_builtin = false; + value->v.f.v.f.argv = vector_create(); + for (size_t i = 0; i < vector_size(root->v.f.argv); i++) { + vector_add(&value->v.f.v.f.argv, root->v.f.argv[i]); + } + Value *v = ast_to_value(instance, root->v.f.body); + if (!v) { + vector_free(value->v.f.v.f.argv); + FREE(value); + return NULL; + } + value->v.f.v.f.body = v; + } else if (root->kind == ASTKind_ASTKind_MemberAccess) { + // FIXME: Implement + FREE(value); + return NULL; + } else if (root->kind == ASTKind_FunctionCall) { + value->type = dcfg_ValueType_FunctionCall; + Value *function = ast_to_value(instance, root->v.fc.function); + if (!function) { + FREE(value); + return NULL; + } + value->v.c.function = function; + value->v.c.argv = vector_create(); + + for (size_t i = 0; i < vector_size(root->v.fc.argv); i++) { + Value *arg = ast_to_value(instance, root->v.fc.argv[i]); + if (!arg) { + // TODO: Free argv values + for (size_t i = 0; i < vector_size(value->v.c.argv); i++) { + dcfg_destroy(value->v.c.argv[i]); + } + vector_free(value->v.c.argv); + FREE(value); + return NULL; + } + vector_add(&value->v.c.argv, arg); + } + } + return value; +} + dcfg_Value *dcfg_parse(dcfg_Instance *instance, dcfg_StringView const file_path) { char path_buf[file_path.size + 1] = {}; memcpy(path_buf, file_path.data, file_path.size); - char *abs = realpath(path_buf, NULL); + char *abs = instance->realpath(path_buf); if (!abs) { snprintf(instance->last_error, sizeof(instance->last_error) - 1, "realpath: %s", strerror(errno)); } StringView abs_sv = SV(abs); - FILE *fp = fopen(abs, "r"); + FILE *fp = instance->fopen(abs, "r"); if (!fp) { FREE(abs); snprintf(instance->last_error, sizeof(instance->last_error) - 1, @@ -919,7 +1048,7 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance, return NULL; } - if (fseek(fp, 0, SEEK_END)) { + if (instance->fseek(fp, 0, SEEK_END)) { FREE(abs); fclose(fp); snprintf(instance->last_error, sizeof(instance->last_error) - 1, @@ -929,7 +1058,7 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance, long const size = ftell(fp); - if (fseek(fp, 0, SEEK_SET)) { + if (instance->fseek(fp, 0, SEEK_SET)) { FREE(abs); fclose(fp); snprintf(instance->last_error, sizeof(instance->last_error) - 1, @@ -971,8 +1100,16 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance, return NULL; } - // FIXME: Get Value * from AST - return NULL; + Value *v = ast_to_value(instance, ast); + if (!v) { + dcfg_destroy(v); + FREE(abs); + FREE((void *)str.data); + fclose(fp); + return NULL; + } + + return v; } void dcfg_destroy(dcfg_Value *value) { diff --git a/tools/loc.sh b/tools/loc.sh new file mode 100755 index 0000000..37dd4c4 --- /dev/null +++ b/tools/loc.sh @@ -0,0 +1,4 @@ +#/bin/sh + +tokei src/dcfg.c include/dcfg.h +