Add basic ast_to_value, make POSIX optional

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-07-25 23:21:33 +03:00
parent 3fdda1bbaa
commit a35a476654
5 changed files with 173 additions and 12 deletions

View File

@@ -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)

View File

@@ -27,6 +27,7 @@
clang-tools
lldb
pkg-config
tokei
];
};
}

View File

@@ -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 {

View File

@@ -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 <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -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_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
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) {

4
tools/loc.sh Executable file
View File

@@ -0,0 +1,4 @@
#/bin/sh
tokei src/dcfg.c include/dcfg.h