From 680eda773b2baf555461c2d64a8ee5de77f7f8f9 Mon Sep 17 00:00:00 2001 From: fennecdjay Date: Tue, 3 Nov 2020 20:27:24 +0100 Subject: [PATCH] :art: Introduce '#require' --- ast | 2 +- include/arg.h | 2 +- include/engine.h | 2 +- include/gwi.h | 4 +- include/gwiondata.h | 2 +- include/plug.h | 26 ++-- src/arg.c | 22 ++- src/compile.c | 1 - src/gwion.c | 17 +-- src/gwiondata.c | 2 +- src/import/import_internals.c | 7 + src/lib/engine.c | 14 +- src/parse/scan0.c | 9 +- src/plug.c | 246 ++++++++++++++++++---------------- 14 files changed, 186 insertions(+), 170 deletions(-) diff --git a/ast b/ast index 42250676..1811fe81 160000 --- a/ast +++ b/ast @@ -1 +1 @@ -Subproject commit 42250676d6164fdc0b8505b0939cb21713cf6782 +Subproject commit 1811fe812817a12968c905c61165b146dc6a17e2 diff --git a/include/arg.h b/include/arg.h index ae9746ad..22b4bdf8 100644 --- a/include/arg.h +++ b/include/arg.h @@ -3,9 +3,9 @@ typedef struct Arg_ { struct CArg arg; + struct Map_ mod; struct Vector_ add; struct Vector_ lib; - struct Vector_ mod; struct Vector_ config; struct SoundInfo_ *si; m_bool loop; diff --git a/include/engine.h b/include/engine.h index 728d16e6..4d1c008c 100644 --- a/include/engine.h +++ b/include/engine.h @@ -1,4 +1,4 @@ #ifndef __ENGINE #define __ENGINE -ANN m_bool type_engine_init(const Gwion gwion, const Vector); +ANN m_bool type_engine_init(const Gwion gwion); #endif diff --git a/include/gwi.h b/include/gwi.h index 6cee9bca..d20124fd 100644 --- a/include/gwi.h +++ b/include/gwi.h @@ -4,7 +4,7 @@ #define loc(gwi) loc_cpy(gwi->gwion->mp, gwi->loc) struct Gwi_ { - struct Gwion_* gwion; + struct Gwion_ *const gwion; Ast body; struct ImportCK *ck; struct OperCK *oper; // _misc @@ -15,4 +15,6 @@ struct Gwi_ { static inline Tmpl* gwi_tmpl(const Gwi gwi) { return new_tmpl_base(gwi->gwion->mp, gwi->ck->tmpl); } + +ANN m_bool gwi_run(const Gwion gwion, m_bool (*f)(const Gwi)); #endif diff --git a/include/gwiondata.h b/include/gwiondata.h index 046f15b7..eccc3d15 100644 --- a/include/gwiondata.h +++ b/include/gwiondata.h @@ -8,7 +8,7 @@ typedef struct GwionData_ { struct Vector_ child2; struct Vector_ reserved; struct Passes_ *passes; - PlugInfo* plug; + struct Map_ plug; } GwionData; ANN GwionData* new_gwiondata(MemPool); diff --git a/include/plug.h b/include/plug.h index 2065ae5d..57fa37dd 100644 --- a/include/plug.h +++ b/include/plug.h @@ -1,30 +1,22 @@ #ifndef __PLUG #define __PLUG -enum plug_t { - GWPLUG_DL, - GWPLUG_IMPORT, - GWPLUG_MODULE, - GWPLUG_LAST -}; - -typedef struct PlugInfo_ { - struct Map_ drv; - struct Vector_ vec[GWPLUG_LAST]; -} PlugInfo; - -ANN PlugInfo* new_pluginfo(MemPool, Vector); -ANN void plug_run(const struct Gwion_*, const Vector); +ANN m_bool plug_ini(const struct Gwion_*, const Vector); +ANN m_bool driver_ini(const struct Gwion_*); +ANN void plug_run(const struct Gwion_*, const Map); ANN void free_plug(const struct Gwion_*); ANN void* get_module(const struct Gwion_*, const m_str); +ANN void set_module(const struct Gwion_ *gwion, const m_str name, void *const ptr); +ANN m_bool plugin_ini(struct Gwion_ *gwion, const m_str iname); + #define GWIMPORT_NAME import -#define GWMODSTR_NAME gwmodstr #define GWMODINI_NAME gwmodini #define GWMODEND_NAME gwmodend -#define GWDRIVER_NAME gwmodend -#define GWMODSTR(a) m_str GWMODSTR_NAME() { return #a; } +#define GWDRIVER_NAME gwdriver +#define GWDEPEND_NAME gwdepend #define GWMODINI(a) ANN2(1) void* GWMODINI_NAME(const struct Gwion_ *gwion NUSED, const Vector args NUSED) #define GWMODEND(a) ANN void GWMODEND_NAME(const struct Gwion_ *gwion NUSED, void* self NUSED) #define GWDRIVER(a) ANN void GWDRIVER_NAME(DriverData* d) +#define GWDEPEND ANN m_str* GWDEPEND_NAME(void) #endif diff --git a/src/arg.c b/src/arg.c index 36e90dd2..495c4577 100644 --- a/src/arg.c +++ b/src/arg.c @@ -31,18 +31,18 @@ ANN static m_str plug_dir(void) { } ANN static void arg_init(Arg* arg) { + map_init(&arg->mod); vector_init(&arg->add); vector_init(&arg->lib); - vector_init(&arg->mod); vector_init(&arg->config); vector_add(&arg->lib, (vtype)plug_dir()); } ANN void arg_release(Arg* arg) { + map_release(&arg->mod); vector_release(&arg->add); xfree((m_str)vector_front(&arg->lib)); vector_release(&arg->lib); - vector_release(&arg->mod); config_end(&arg->config); vector_release(&arg->config); } @@ -72,6 +72,22 @@ ANN2(1) static inline void arg_set_pass(const Gwion gwion, const m_str str) { free_vector(gwion->mp, v); } +ANN2(1) static void module_arg(const Map map, m_str str) { + m_str val = strchr(str, '='); + if(val) { + *val = '\0'; + ++val; + } + const m_str key = str; + for(m_uint i = 0; i < map_size(map); ++i) { + if(!strcmp(key, (m_str)VKEY(map, i))) { + free((m_str)VKEY(map, i)); + break; + } + } + map_set(map, (vtype)key, (vtype)val); +} + ANN m_bool _arg_parse(const Gwion gwion, Arg* arg) { struct CArg *ca = &arg->arg; for(ca->idx = 1; ca->idx < ca->argc; ++ca->idx) { @@ -91,7 +107,7 @@ ANN m_bool _arg_parse(const Gwion gwion, Arg* arg) { break; case 'm': CHECK_OB((tmp = option_argument(ca))) - vector_add(&arg->mod, (vtype)tmp); + module_arg(&arg->mod, tmp); break; case 'l': CHECK_OB((tmp = option_argument(ca))) diff --git a/src/compile.c b/src/compile.c index 9c1644a5..4227f17d 100644 --- a/src/compile.c +++ b/src/compile.c @@ -117,7 +117,6 @@ ANN static inline m_bool _check(struct Gwion_* gwion, struct Compiler* c) { } ANN static m_uint _compile(struct Gwion_* gwion, struct Compiler* c) { -// CHECK_BB(compiler_open(gwion->mp, c)) if(compiler_open(gwion->mp, c) < 0) return 0; if(_check(gwion, c) < 0) { diff --git a/src/gwion.c b/src/gwion.c index 99036808..9cce298c 100644 --- a/src/gwion.c +++ b/src/gwion.c @@ -13,21 +13,10 @@ #include "pass.h" // fork_clean #include "shreduler_private.h" -ANN static void driver_arg(const Gwion gwion, Driver *di) { - for(m_uint i = 0; i < map_size(&gwion->data->plug->drv); ++i) { - const m_str name = (m_str)VKEY(&gwion->data->plug->drv, i); - const size_t len = strlen(name); - if(!strncmp(name, di->si->arg, len)) { - di->func = (f_bbqset)VVAL(&gwion->data->plug->drv, i); - break; - } - } -} - ANN m_bool gwion_audio(const Gwion gwion) { Driver *const di = gwion->vm->bbq; if(di->si->arg) - driver_arg(gwion, di); + driver_ini(gwion); di->func(di->driver); CHECK_BB(di->driver->ini(gwion->vm, di)); driver_alloc(di); @@ -35,7 +24,7 @@ ANN m_bool gwion_audio(const Gwion gwion) { } ANN static inline m_bool gwion_engine(const Gwion gwion) { - return type_engine_init(gwion, &gwion->data->plug->vec[GWPLUG_IMPORT]) > 0; + return type_engine_init(gwion) > 0; } ANN static inline void gwion_compile(const Gwion gwion, const Vector v) { @@ -72,7 +61,7 @@ ANN static void gwion_core(const Gwion gwion) { } ANN static m_bool gwion_ok(const Gwion gwion, Arg* arg) { - gwion->data->plug = new_pluginfo(gwion->mp, &arg->lib); + CHECK_BB(plug_ini(gwion, &arg->lib)) shreduler_set_loop(gwion->vm->shreduler, arg->loop); if(gwion_audio(gwion) > 0) { plug_run(gwion, &arg->mod); diff --git a/src/gwiondata.c b/src/gwiondata.c index 5f74b697..a85cd6a5 100644 --- a/src/gwiondata.c +++ b/src/gwiondata.c @@ -48,7 +48,7 @@ ANN void free_gwiondata(const struct Gwion_ *gwion) { map_release(&data->id); vector_release(&data->reserved); free_passes(gwion->mp, data->passes); - if(data->plug) + if(data->plug.ptr) free_plug(gwion); free_gwiondata_cpy(gwion->mp, data); } diff --git a/src/import/import_internals.c b/src/import/import_internals.c index 659c4978..69438f01 100644 --- a/src/import/import_internals.c +++ b/src/import/import_internals.c @@ -27,3 +27,10 @@ ANN void gwi_reset(const Gwi gwi) { } env_reset(gwi->gwion->env); } + +ANN m_bool gwi_run(const Gwion gwion, m_bool (*f)(const Gwi)) { + struct loc_t_ loc = {}; + OperCK oper = {}; + struct Gwi_ gwi = { .gwion=gwion, .loc=&loc, .oper=&oper }; + return f(&gwi); +} diff --git a/src/lib/engine.c b/src/lib/engine.c index 3a7c36f0..a438d67e 100644 --- a/src/lib/engine.c +++ b/src/lib/engine.c @@ -164,19 +164,9 @@ ANN static m_bool import_core_libs(const Gwi gwi) { return GW_OK; } -ANN m_bool type_engine_init(const Gwion gwion, const Vector plug_dirs) { +ANN m_bool type_engine_init(const Gwion gwion) { gwion->env->name = "[builtin]"; - struct loc_t_ loc = {}; - OperCK oper = {}; - struct Gwi_ gwi = { .gwion=gwion, .loc=&loc, .oper=&oper }; - CHECK_BB(import_core_libs(&gwi)) - push_global(gwion, "[plugins]"); - gwion->env->name = "[imported]"; - for(m_uint i = 0; i < vector_size(plug_dirs); ++i) { - m_bool (*import)(Gwi) = (m_bool(*)(Gwi))vector_at(plug_dirs, i); - if(import && import(&gwi) < 0) - gwi_reset(&gwi); - } + CHECK_BB(gwi_run(gwion, import_core_libs)) push_global(gwion, "[user]"); return GW_OK; } diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 6317cba4..3563e3e4 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -355,9 +355,12 @@ ANN static Type scan0_class_def_init(const Env env, const Class_Def cdef) { } ANN static m_bool scan0_stmt_list(const Env env, Stmt_List list) { - do if(list->stmt->stmt_type == ae_stmt_pp && list->stmt->d.stmt_pp.pp_type == ae_pp_include) - env->name = list->stmt->d.stmt_pp.data; - while((list = list->next)); + do if(list->stmt->stmt_type == ae_stmt_pp) { + if(list->stmt->d.stmt_pp.pp_type == ae_pp_include) + env->name = list->stmt->d.stmt_pp.data; + else if(list->stmt->d.stmt_pp.pp_type == ae_pp_require) + CHECK_BB(plugin_ini(env->gwion, list->stmt->d.stmt_pp.data)) + } while((list = list->next)); return GW_OK; } diff --git a/src/plug.c b/src/plug.c index 75724b18..619e6377 100644 --- a/src/plug.c +++ b/src/plug.c @@ -1,6 +1,7 @@ #ifndef BUILD_ON_WINDOWS #include #include +#include #else #include #endif @@ -13,19 +14,13 @@ #include "instr.h" #include "object.h" #include "import.h" +#include "gwi.h" -typedef m_bool (*import)(Gwi); -typedef m_str (*modstr)(void); +typedef m_bool (*plugin)(Gwi); typedef void* (*modini)(const struct Gwion_*, const Vector); -typedef void* (*modrun)(const struct Gwion_*, void*); typedef void* (*modend)(const struct Gwion_*, void*); +typedef m_str* (*gwdeps)(void); -struct Plug_ { - m_str name; - modini ini; - modend end; - void* self; -}; #define STR_EXPAND(tok) #tok #define STR(tok) STR_EXPAND(tok) #ifndef BUILD_ON_WINDOWS @@ -44,53 +39,33 @@ struct Plug_ { struct PlugHandle { MemPool mp; - PlugInfo* pi; - void *dl; - m_str file; - m_str name; + Map map; + size_t len; }; -ANN static struct Plug_* new_plug(MemPool p, const modini ini) { +typedef struct Plug_ { + void *dl; + void *self; + int mod; + int imp; +} *Plug; + +ANN static struct Plug_* new_plug(MemPool p, void *dl) { struct Plug_ *plug = mp_calloc(p, Plug); - plug->ini = ini; + plug->dl = dl; return plug; } -ANN static void plug_import(struct PlugHandle *h) { - const import imp = DLSYM(h->dl, import, GWIMPORT_NAME); - if(imp) - vector_add(&h->pi->vec[GWPLUG_IMPORT], (vtype)imp); -} - -ANN static void plug_module(struct PlugHandle *h) { - const modini ini = DLSYM(h->dl, modini, GWMODINI_NAME); - if(ini) { - struct Plug_ *plug = new_plug(h->mp, ini); - plug->name = h->name; - plug->end = DLSYM(h->dl, modend, GWMODEND_NAME); - vector_add(&h->pi->vec[GWPLUG_MODULE], (vtype)plug); - } -} - -ANN static void plug_driver(struct PlugHandle *h) { - const f_bbqset drv = DLSYM(h->dl, f_bbqset, GWDRIVER_NAME); - if(drv) - map_set(&h->pi->drv, (vtype)h->name, (vtype)drv); -} - -ANN static inline m_str plug_name(struct PlugHandle *h) { - const modstr str = DLSYM(h->dl, modstr, GWMODSTR_NAME); - return str ? str() : NULL; -} - ANN static void plug_get(struct PlugHandle *h, const m_str c) { - h->dl = DLOPEN(c, RTLD_LAZY | RTLD_GLOBAL); - if(h->dl) { - vector_add(&h->pi->vec[GWPLUG_DL], (vtype)h->dl); - h->name = plug_name(h); - plug_import(h); - plug_module(h); - plug_driver(h); + void *dl = DLOPEN(c, RTLD_LAZY | RTLD_GLOBAL); + const m_str pname = c + h->len + 1; + const size_t sz = strlen(pname) - 3; + char name[PATH_MAX]; + memcpy(name, pname, sz); + name[sz] = '\0'; + if(dl) { + Plug plug = new_plug(h->mp, dl); + map_set(h->map, (vtype)strdup(name), (vtype)plug); } else gw_err(_("error in %s."), DLERROR()); } @@ -113,99 +88,142 @@ ANN static void plug_get_all(struct PlugHandle *h, const m_str name) { strcpy(c, name); strcpy(c + strlen(name) - 4, filedata.cFileName); plug_get(h, c); - } while(FindNextFile(file,&filedata)); + } while(FindNextFile(file, &filedata)); FindClose(file); #endif } -ANN2(1) static void* pp_ini(const struct Gwion_ *gwion, const Vector v) { - pparg_run(gwion->ppa, v); - return NULL; -} - -ANN static void register_pp(const struct PlugHandle* h) { - struct Plug_ *plug = new_plug(h->mp, pp_ini); - plug->name = "pp"; - vector_add(&h->pi->vec[GWPLUG_MODULE], (vtype)plug); -} - -ANN PlugInfo* new_pluginfo(MemPool p, const Vector list) { - PlugInfo *pi = (PlugInfo*)mp_calloc(p, PlugInfo); - for(m_uint i = 0; i < GWPLUG_LAST; ++i) - vector_init(&pi->vec[i]); - map_init(&pi->drv); - struct PlugHandle h = { .mp=p, .pi=pi }; - register_pp(&h); +ANN m_bool plug_ini(const struct Gwion_ *gwion, const Vector list) { + const Map map = &gwion->data->plug; + map_init(map); + struct PlugHandle h = { .mp=gwion->mp, .map=map }; for(m_uint i = 0; i < vector_size(list); i++) { const m_str dir = (m_str)vector_at(list, i); - char name[strlen(dir) + 6]; + h.len = strlen(dir); + char name[PATH_MAX]; sprintf(name, "%s/*.so", dir); plug_get_all(&h, name); } - return pi; + return GW_OK; } -ANN static void plug_free_module(const struct Gwion_* gwion, const Vector v) { - for(m_uint i = 0; i < vector_size(v); ++i) { - struct Plug_ *plug = (struct Plug_*)vector_at(v, i); - if(plug->end) - plug->end(gwion, plug->self); - mp_free(gwion->mp, Plug, plug); +void free_plug(const struct Gwion_ *gwion) { + const Map map = &gwion->data->plug; + for(m_uint i = 0; i < map_size(map); ++i) { + const Plug plug = (Plug)VVAL(map, i); + const modend end = DLSYM(plug->dl, modend, GWMODEND_NAME); + if(end) + end(gwion, plug->self); + free((m_str)VKEY(map, i)); + DLCLOSE(plug->dl); } + map_release(map); } -ANN static inline void plug_free_dls(const Vector v) { +ANN static void plug_free_arg(MemPool p, const Vector v) { for(m_uint i = 0; i < vector_size(v); ++i) - DLCLOSE((void*)vector_at(v, i)); -} - -void free_plug(const struct Gwion_ *gwion) { - PlugInfo *p = gwion->data->plug; - struct Vector_ * const v = p->vec; - plug_free_module(gwion, &v[GWPLUG_MODULE]); - plug_free_dls(&v[GWPLUG_DL]); - for(m_uint i = 0; i < GWPLUG_LAST; ++i) - vector_release(&v[i]); - map_release(&p->drv); - mp_free(gwion->mp, PlugInfo, p); + free_mstr(p, (m_str)vector_at(v, i)); + free_vector(p, v); } -ANN static Vector get_arg(MemPool p, const m_str name, const Vector v) { - const size_t len = strlen(name); - for(m_uint i = vector_size(v) + 1; --i;) { - const m_str str = (m_str)vector_at(v, i - 1); - if(!strncmp(name, str, len)) { - vector_rem(v, i-1); - const m_str arg = strchr(str, '='); - return arg ? split_args(p, arg+1) : NULL; +ANN void set_module(const struct Gwion_ *gwion, const m_str name, void *const ptr) { + const Map map = &gwion->data->plug; + for(m_uint j = 0; j < map_size(map); ++j) { + if(!strcmp(name, (m_str)VKEY(map, j))) { + Plug plug = (Plug)VVAL(map, j); + if(plug->mod) + return; + plug->mod = 1; + plug->self = ptr; + return; } } - return NULL; } -ANN static void plug_free_arg(MemPool p, const Vector v) { - for(m_uint i = 0; i < vector_size(v); ++i) - free_mstr(p, (m_str)vector_at(v, i)); - free_vector(p, v); +ANN void plug_run(const struct Gwion_ *gwion, const Map mod) { + const Map map = &gwion->data->plug; + for(m_uint i = 0; i < map_size(mod); ++i) { + const m_str name = (m_str)VKEY(mod, i); + const m_str opt = (m_str)VVAL(mod, i); + for(m_uint j = 0; j < map_size(map); ++j) { + if(!strcmp(name, (m_str)VKEY(map, j))) { + Plug plug = (Plug)VVAL(map, j); + const Vector arg = opt ? split_args(gwion->mp, opt) : NULL; + const modini ini = DLSYM(plug->dl, modini, GWMODINI_NAME); + plug->self = ini(gwion, arg); + if(arg) + plug_free_arg(gwion->mp, arg); + } + } + } } -ANN void plug_run(const struct Gwion_ *gwion, const Vector args) { - const Vector v = &gwion->data->plug->vec[GWPLUG_MODULE]; - for(m_uint i = 0; i < vector_size(v); ++i) { - struct Plug_ *plug = (struct Plug_*)vector_at(v, i); - const Vector arg = get_arg(gwion->mp, plug->name, args); - plug->self = plug->ini(gwion, arg); - if(arg) - plug_free_arg(gwion->mp, arg); +ANN static m_bool dependencies(struct Gwion_ *gwion, const Plug plug) { + const gwdeps dep = DLSYM(plug->dl, gwdeps, GWDEPEND_NAME); + if(dep) { + m_str *deps = dep(); + while(*deps) { + CHECK_BB(plugin_ini(gwion, *deps)) + ++deps; + } } + return GW_OK; +} + +ANN m_bool plugin_ini(struct Gwion_ *gwion, const m_str iname) { + const Map map = &gwion->data->plug; + for(m_uint i = 0; i < map_size(map); ++i) { + const Plug plug = (Plug)VVAL(map, i); + if(plug->imp) + return GW_OK; + const m_str name = (m_str)VKEY(map, i); + if(!strcmp(name, iname)) { + const plugin imp = DLSYM(plug->dl, plugin, GWIMPORT_NAME); + if(!imp) + break; + plug->imp = 1; + CHECK_BB(dependencies(gwion, plug)) + const m_uint scope = env_push_global(gwion->env); + const m_bool ret = gwi_run(gwion, imp); + env_pop(gwion->env, scope); + return ret; + } + } + gw_err("no such plugin '%s'\n", iname); + return GW_ERROR; +} + +ANN m_bool driver_ini(const struct Gwion_ *gwion) { + const Map map = &gwion->data->plug; + m_str dname = gwion->vm->bbq->si->arg; + m_str opt = strchr(dname, '='); + const char c = opt ? *opt : '\0'; + if(opt) + *opt = '\0'; + for(m_uint i = 0; i < map_size(map); ++i) { + const m_str name = (m_str)VKEY(map, i); + if(!strcmp(name, dname)) { + const Plug plug = (Plug)VVAL(map, i); + const f_bbqset drv = DLSYM(plug->dl, f_bbqset, GWDRIVER_NAME); + if(!drv) + break; + gwion->vm->bbq->func = drv; + if(opt) + *opt = c; + return GW_OK; + } + } + gw_err("can't find driver '%s'\n", dname); + return GW_ERROR; } ANN void* get_module(const struct Gwion_ *gwion, const m_str name) { - const Vector v = &gwion->data->plug->vec[GWPLUG_MODULE]; - for(m_uint i = 0; i < vector_size(v); ++i) { - struct Plug_ *plug = (struct Plug_*)vector_at(v, i); - if(!strcmp(name, plug->name)) + const Map map = &gwion->data->plug; + for(m_uint i = 0; i < map_size(map); ++i) { + if(!strcmp(name, (m_str)VKEY(map, i))) { + const Plug plug = (Plug)VVAL(map, i); return plug->self; + } } return NULL; } -- 2.43.0