Add basic ast_to_value, make POSIX optional
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
@@ -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)
|
||||
|
@@ -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 {
|
||||
|
159
src/dcfg.c
159
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 <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,10 +1100,18 @@ 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) {
|
||||
(void)value;
|
||||
// FIXME: Implement
|
||||
|
4
tools/loc.sh
Executable file
4
tools/loc.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#/bin/sh
|
||||
|
||||
tokei src/dcfg.c include/dcfg.h
|
||||
|
Reference in New Issue
Block a user