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_SHARED "Build DCFG as a shared library" ON)
|
||||||
option(DCFG_BUILD_STATIC "Build DCFG as a static library" OFF)
|
option(DCFG_BUILD_STATIC "Build DCFG as a static library" OFF)
|
||||||
option(DCFG_PTHREAD_SUPPORT "Enable pthreads support" ON)
|
option(DCFG_PTHREAD_SUPPORT "Enable pthreads support" ON)
|
||||||
|
option(DCFG_POSIX_SUPPORT "Enable POSIX support" ON)
|
||||||
|
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
|
||||||
@@ -24,6 +25,9 @@ if(DCFG_BUILD_SHARED)
|
|||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_PTHREAD_SUPPORT)
|
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_PTHREAD_SUPPORT)
|
||||||
endif()
|
endif()
|
||||||
|
if (DCFG_POSIX_SUPPORT)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE DCFG_POSIX_SUPPORT)
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "dcfg")
|
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "dcfg")
|
||||||
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
|
||||||
@@ -38,6 +42,9 @@ if(DCFG_BUILD_STATIC)
|
|||||||
target_link_libraries(${PROJECT_NAME}_static PRIVATE Threads::Threads)
|
target_link_libraries(${PROJECT_NAME}_static PRIVATE Threads::Threads)
|
||||||
target_compile_definitions(${PROJECT_NAME}_static PRIVATE DCFG_PTHREAD_SUPPORT)
|
target_compile_definitions(${PROJECT_NAME}_static PRIVATE DCFG_PTHREAD_SUPPORT)
|
||||||
endif()
|
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")
|
set_target_properties(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME "dcfg")
|
||||||
install(TARGETS ${PROJECT_NAME}_static DESTINATION lib)
|
install(TARGETS ${PROJECT_NAME}_static DESTINATION lib)
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
clang-tools
|
clang-tools
|
||||||
lldb
|
lldb
|
||||||
pkg-config
|
pkg-config
|
||||||
|
tokei
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -20,9 +20,21 @@ typedef struct dcfg_StringView {
|
|||||||
|
|
||||||
typedef void *(*dcfg_AllocFn)(size_t); // This should automatically zero memory.
|
typedef void *(*dcfg_AllocFn)(size_t); // This should automatically zero memory.
|
||||||
typedef void (*dcfg_FreeFn)(void *);
|
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 {
|
typedef struct dcfg_InstanceCreateInfo {
|
||||||
|
// Default using libc
|
||||||
dcfg_AllocFn alloc;
|
dcfg_AllocFn alloc;
|
||||||
dcfg_FreeFn free;
|
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;
|
} dcfg_InstanceCreateInfo;
|
||||||
|
|
||||||
typedef enum dcfg_ValueKind {
|
typedef enum dcfg_ValueKind {
|
||||||
|
159
src/dcfg.c
159
src/dcfg.c
@@ -4,7 +4,16 @@
|
|||||||
#include "vendor/utf8proc.h"
|
#include "vendor/utf8proc.h"
|
||||||
#include "vendor/vec.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 <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -123,35 +132,39 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ValueObjectEntry *entryv;
|
ValueObjectEntry *entryv;
|
||||||
size_t entryc;
|
|
||||||
} ValueObject;
|
} ValueObject;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Value *valuev;
|
Value **valuev;
|
||||||
size_t valuec;
|
|
||||||
} ValueArray;
|
} ValueArray;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
StringView *argv;
|
||||||
|
Value *body;
|
||||||
|
} ValueFunctionF;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool is_builtin;
|
bool is_builtin;
|
||||||
union {
|
union {
|
||||||
Value *(*bi)(Value **argv, size_t argc);
|
Value *(*bi)(Value **argv, size_t argc);
|
||||||
Value *v;
|
ValueFunctionF f;
|
||||||
} v;
|
} v;
|
||||||
} ValueFunction;
|
} ValueFunction;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Value *function;
|
Value *function;
|
||||||
Value **argv;
|
Value **argv;
|
||||||
size_t argc;
|
|
||||||
} ValueFunctionCall;
|
} ValueFunctionCall;
|
||||||
|
|
||||||
struct dcfg_Value {
|
struct dcfg_Value {
|
||||||
|
Instance *instance;
|
||||||
dcfg_ValueType type;
|
dcfg_ValueType type;
|
||||||
SourceLocation location;
|
SourceLocation location;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
int64_t i;
|
int64_t i;
|
||||||
double r;
|
double r;
|
||||||
|
bool b;
|
||||||
StringView s;
|
StringView s;
|
||||||
StringView p;
|
StringView p;
|
||||||
ValueObject o;
|
ValueObject o;
|
||||||
@@ -166,6 +179,10 @@ struct dcfg_Instance {
|
|||||||
|
|
||||||
dcfg_AllocFn alloc;
|
dcfg_AllocFn alloc;
|
||||||
dcfg_FreeFn free;
|
dcfg_FreeFn free;
|
||||||
|
dcfg_RealpathFn realpath;
|
||||||
|
dcfg_FopenFn fopen;
|
||||||
|
dcfg_FseekFn fseek;
|
||||||
|
dcfg_FtellFn ftell;
|
||||||
|
|
||||||
char last_error[256];
|
char last_error[256];
|
||||||
};
|
};
|
||||||
@@ -175,6 +192,13 @@ struct dcfg_Instance {
|
|||||||
|
|
||||||
static void *alloc(size_t size) { return calloc(1, size); }
|
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) {
|
dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) {
|
||||||
assert(create_info);
|
assert(create_info);
|
||||||
|
|
||||||
@@ -192,6 +216,28 @@ dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info) {
|
|||||||
if (!instance->free) {
|
if (!instance->free) {
|
||||||
instance->free = 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;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,19 +945,102 @@ AST *Parser_parse(Parser *parser) { return parser_parse_value(parser); }
|
|||||||
#define ALLOC(sz) (instance->alloc((sz)))
|
#define ALLOC(sz) (instance->alloc((sz)))
|
||||||
#define FREE(ptr) (instance->free((ptr)))
|
#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_Value *dcfg_parse(dcfg_Instance *instance,
|
||||||
dcfg_StringView const file_path) {
|
dcfg_StringView const file_path) {
|
||||||
char path_buf[file_path.size + 1] = {};
|
char path_buf[file_path.size + 1] = {};
|
||||||
memcpy(path_buf, file_path.data, file_path.size);
|
memcpy(path_buf, file_path.data, file_path.size);
|
||||||
|
|
||||||
char *abs = realpath(path_buf, NULL);
|
char *abs = instance->realpath(path_buf);
|
||||||
if (!abs) {
|
if (!abs) {
|
||||||
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
||||||
"realpath: %s", strerror(errno));
|
"realpath: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
StringView abs_sv = SV(abs);
|
StringView abs_sv = SV(abs);
|
||||||
|
|
||||||
FILE *fp = fopen(abs, "r");
|
FILE *fp = instance->fopen(abs, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
FREE(abs);
|
FREE(abs);
|
||||||
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
||||||
@@ -919,7 +1048,7 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fseek(fp, 0, SEEK_END)) {
|
if (instance->fseek(fp, 0, SEEK_END)) {
|
||||||
FREE(abs);
|
FREE(abs);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
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);
|
long const size = ftell(fp);
|
||||||
|
|
||||||
if (fseek(fp, 0, SEEK_SET)) {
|
if (instance->fseek(fp, 0, SEEK_SET)) {
|
||||||
FREE(abs);
|
FREE(abs);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
snprintf(instance->last_error, sizeof(instance->last_error) - 1,
|
||||||
@@ -971,10 +1100,18 @@ dcfg_Value *dcfg_parse(dcfg_Instance *instance,
|
|||||||
return NULL;
|
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 NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void dcfg_destroy(dcfg_Value *value) {
|
void dcfg_destroy(dcfg_Value *value) {
|
||||||
(void)value;
|
(void)value;
|
||||||
// FIXME: Implement
|
// 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