1 |
|
|
#ifndef BUILD_ON_WINDOWS |
2 |
|
|
#include <glob.h> |
3 |
|
|
#include <dlfcn.h> |
4 |
|
|
#else |
5 |
|
|
#include <windows.h> |
6 |
|
|
#endif |
7 |
|
|
#include "gwion_util.h" |
8 |
|
|
#include "gwion_ast.h" |
9 |
|
|
#include "gwion_env.h" |
10 |
|
|
#include "vm.h" |
11 |
|
|
#include "gwion.h" |
12 |
|
|
#include "operator.h" |
13 |
|
|
#include "instr.h" |
14 |
|
|
#include "object.h" |
15 |
|
|
#include "import.h" |
16 |
|
|
|
17 |
|
|
typedef m_bool (*import)(Gwi); |
18 |
|
|
typedef m_str (*modstr)(void); |
19 |
|
|
typedef void* (*modini)(const struct Gwion_*, const Vector); |
20 |
|
|
typedef void* (*modrun)(const struct Gwion_*, void*); |
21 |
|
|
typedef void* (*modend)(const struct Gwion_*, void*); |
22 |
|
|
|
23 |
|
|
struct Plug_ { |
24 |
|
|
m_str name; |
25 |
|
|
modini ini; |
26 |
|
|
modend end; |
27 |
|
|
void* self; |
28 |
|
|
}; |
29 |
|
|
#define STR_EXPAND(tok) #tok |
30 |
|
|
#define STR(tok) STR_EXPAND(tok) |
31 |
|
|
#ifndef BUILD_ON_WINDOWS |
32 |
|
|
#include <dlfcn.h> |
33 |
|
|
#define DLOPEN(dl, b) dlopen(dl, b) |
34 |
|
|
#define DLSYM(dl, t, a) (t)(intptr_t)dlsym(dl, STR(a)); |
35 |
|
|
#define DLCLOSE(dl) dlclose(dl); |
36 |
|
|
#define DLERROR() dlerror() |
37 |
|
|
#else |
38 |
|
|
#include "windows.h" |
39 |
|
|
#define DLOPEN(dl, b) LoadLibrary(dl) |
40 |
|
|
#define DLSYM(dl, t, a) (t)(intptr_t)GetProcAddress(dl, STR(a)); |
41 |
|
|
#define DLCLOSE(dl) FreeLibrary(dl); |
42 |
|
|
#define DLERROR() "plugin" |
43 |
|
|
#endif |
44 |
|
|
|
45 |
|
|
struct PlugHandle { |
46 |
|
|
MemPool mp; |
47 |
|
|
PlugInfo* pi; |
48 |
|
|
void *dl; |
49 |
|
|
m_str file; |
50 |
|
|
m_str name; |
51 |
|
|
}; |
52 |
|
|
|
53 |
|
734 |
ANN static struct Plug_* new_plug(MemPool p, const modini ini) { |
54 |
|
734 |
struct Plug_ *plug = mp_calloc(p, Plug); |
55 |
|
734 |
plug->ini = ini; |
56 |
|
734 |
return plug; |
57 |
|
|
} |
58 |
|
|
|
59 |
|
75 |
ANN static void plug_import(struct PlugHandle *h) { |
60 |
|
75 |
const import imp = DLSYM(h->dl, import, GWIMPORT_NAME); |
61 |
✓✓ |
75 |
if(imp) |
62 |
|
69 |
vector_add(&h->pi->vec[GWPLUG_IMPORT], (vtype)imp); |
63 |
|
75 |
} |
64 |
|
|
|
65 |
|
75 |
ANN static void plug_module(struct PlugHandle *h) { |
66 |
|
75 |
const modini ini = DLSYM(h->dl, modini, GWMODINI_NAME); |
67 |
✓✓ |
75 |
if(ini) { |
68 |
|
4 |
struct Plug_ *plug = new_plug(h->mp, ini); |
69 |
|
4 |
plug->name = h->name; |
70 |
|
4 |
plug->end = DLSYM(h->dl, modend, GWMODEND_NAME); |
71 |
|
4 |
vector_add(&h->pi->vec[GWPLUG_MODULE], (vtype)plug); |
72 |
|
|
} |
73 |
|
75 |
} |
74 |
|
|
|
75 |
|
75 |
ANN static void plug_driver(struct PlugHandle *h) { |
76 |
|
75 |
const f_bbqset drv = DLSYM(h->dl, f_bbqset, GWDRIVER_NAME); |
77 |
✓✓ |
75 |
if(drv) |
78 |
|
6 |
map_set(&h->pi->drv, (vtype)h->name, (vtype)drv); |
79 |
|
75 |
} |
80 |
|
|
|
81 |
|
75 |
ANN static inline m_str plug_name(struct PlugHandle *h) { |
82 |
|
75 |
const modstr str = DLSYM(h->dl, modstr, GWMODSTR_NAME); |
83 |
✓✓ |
75 |
return str ? str() : NULL; |
84 |
|
|
} |
85 |
|
|
|
86 |
|
76 |
ANN static void plug_get(struct PlugHandle *h, const m_str c) { |
87 |
|
76 |
h->dl = DLOPEN(c, RTLD_LAZY | RTLD_GLOBAL); |
88 |
✓✓ |
76 |
if(h->dl) { |
89 |
|
75 |
vector_add(&h->pi->vec[GWPLUG_DL], (vtype)h->dl); |
90 |
|
75 |
h->name = plug_name(h); |
91 |
|
75 |
plug_import(h); |
92 |
|
75 |
plug_module(h); |
93 |
|
75 |
plug_driver(h); |
94 |
|
|
} else |
95 |
|
1 |
gw_err(_("error in %s."), DLERROR()); |
96 |
|
76 |
} |
97 |
|
|
|
98 |
|
808 |
ANN static void plug_get_all(struct PlugHandle *h, const m_str name) { |
99 |
|
|
#ifndef BUILD_ON_WINDOWS |
100 |
|
|
glob_t results; |
101 |
✓✓ |
808 |
if(glob(name, 0, NULL, &results)) |
102 |
|
732 |
return; |
103 |
✓✓ |
152 |
for(m_uint i = 0; i < results.gl_pathc; i++) |
104 |
|
76 |
plug_get(h, results.gl_pathv[i]); |
105 |
|
76 |
globfree(&results); |
106 |
|
|
#else |
107 |
|
|
WIN32_FIND_DATA filedata; |
108 |
|
|
HANDLE file = FindFirstFile(name, &filedata); |
109 |
|
|
if(file == INVALID_HANDLE_VALUE) |
110 |
|
|
return; |
111 |
|
|
do { |
112 |
|
|
char c[PATH_MAX]; |
113 |
|
|
strcpy(c, name); |
114 |
|
|
strcpy(c + strlen(name) - 4, filedata.cFileName); |
115 |
|
|
plug_get(h, c); |
116 |
|
|
} while(FindNextFile(file,&filedata)); |
117 |
|
|
FindClose(file); |
118 |
|
|
#endif |
119 |
|
|
} |
120 |
|
|
|
121 |
|
730 |
ANN2(1) static void* pp_ini(const struct Gwion_ *gwion, const Vector v) { |
122 |
|
730 |
pparg_run(gwion->ppa, v); |
123 |
|
730 |
return NULL; |
124 |
|
|
} |
125 |
|
|
|
126 |
|
730 |
ANN static void register_pp(const struct PlugHandle* h) { |
127 |
|
730 |
struct Plug_ *plug = new_plug(h->mp, pp_ini); |
128 |
|
730 |
plug->name = "pp"; |
129 |
|
730 |
vector_add(&h->pi->vec[GWPLUG_MODULE], (vtype)plug); |
130 |
|
730 |
} |
131 |
|
|
|
132 |
|
730 |
ANN PlugInfo* new_pluginfo(MemPool p, const Vector list) { |
133 |
|
730 |
PlugInfo *pi = (PlugInfo*)mp_calloc(p, PlugInfo); |
134 |
✓✓ |
2920 |
for(m_uint i = 0; i < GWPLUG_LAST; ++i) |
135 |
|
2190 |
vector_init(&pi->vec[i]); |
136 |
|
730 |
map_init(&pi->drv); |
137 |
|
730 |
struct PlugHandle h = { .mp=p, .pi=pi }; |
138 |
|
730 |
register_pp(&h); |
139 |
✓✓ |
1538 |
for(m_uint i = 0; i < vector_size(list); i++) { |
140 |
|
808 |
const m_str dir = (m_str)vector_at(list, i); |
141 |
|
808 |
char name[strlen(dir) + 6]; |
142 |
|
808 |
sprintf(name, "%s/*.so", dir); |
143 |
|
808 |
plug_get_all(&h, name); |
144 |
|
|
} |
145 |
|
730 |
return pi; |
146 |
|
|
} |
147 |
|
|
|
148 |
|
729 |
ANN static void plug_free_module(const struct Gwion_* gwion, const Vector v) { |
149 |
✓✓ |
1462 |
for(m_uint i = 0; i < vector_size(v); ++i) { |
150 |
|
733 |
struct Plug_ *plug = (struct Plug_*)vector_at(v, i); |
151 |
✓✓ |
733 |
if(plug->end) |
152 |
|
4 |
plug->end(gwion, plug->self); |
153 |
|
733 |
mp_free(gwion->mp, Plug, plug); |
154 |
|
|
} |
155 |
|
729 |
} |
156 |
|
|
|
157 |
|
729 |
ANN static inline void plug_free_dls(const Vector v) { |
158 |
✓✓ |
804 |
for(m_uint i = 0; i < vector_size(v); ++i) |
159 |
|
75 |
DLCLOSE((void*)vector_at(v, i)); |
160 |
|
729 |
} |
161 |
|
|
|
162 |
|
729 |
void free_plug(const struct Gwion_ *gwion) { |
163 |
|
729 |
PlugInfo *p = gwion->data->plug; |
164 |
|
729 |
struct Vector_ * const v = p->vec; |
165 |
|
729 |
plug_free_module(gwion, &v[GWPLUG_MODULE]); |
166 |
|
729 |
plug_free_dls(&v[GWPLUG_DL]); |
167 |
✓✓ |
2916 |
for(m_uint i = 0; i < GWPLUG_LAST; ++i) |
168 |
|
2187 |
vector_release(&v[i]); |
169 |
|
729 |
map_release(&p->drv); |
170 |
|
729 |
mp_free(gwion->mp, PlugInfo, p); |
171 |
|
729 |
} |
172 |
|
|
|
173 |
|
734 |
ANN static Vector get_arg(MemPool p, const m_str name, const Vector v) { |
174 |
|
734 |
const size_t len = strlen(name); |
175 |
✓✓ |
1547 |
for(m_uint i = vector_size(v) + 1; --i;) { |
176 |
|
81 |
const m_str str = (m_str)vector_at(v, i - 1); |
177 |
✓✓ |
81 |
if(!strncmp(name, str, len)) { |
178 |
|
2 |
vector_rem(v, i-1); |
179 |
|
2 |
const m_str arg = strchr(str, '='); |
180 |
✓✗ |
2 |
return arg ? split_args(p, arg+1) : NULL; |
181 |
|
|
} |
182 |
|
|
} |
183 |
|
732 |
return NULL; |
184 |
|
|
} |
185 |
|
|
|
186 |
|
2 |
ANN static void plug_free_arg(MemPool p, const Vector v) { |
187 |
✓✓ |
7 |
for(m_uint i = 0; i < vector_size(v); ++i) |
188 |
|
5 |
free_mstr(p, (m_str)vector_at(v, i)); |
189 |
|
2 |
free_vector(p, v); |
190 |
|
2 |
} |
191 |
|
|
|
192 |
|
730 |
ANN void plug_run(const struct Gwion_ *gwion, const Vector args) { |
193 |
|
730 |
const Vector v = &gwion->data->plug->vec[GWPLUG_MODULE]; |
194 |
✓✓ |
1464 |
for(m_uint i = 0; i < vector_size(v); ++i) { |
195 |
|
734 |
struct Plug_ *plug = (struct Plug_*)vector_at(v, i); |
196 |
|
734 |
const Vector arg = get_arg(gwion->mp, plug->name, args); |
197 |
|
734 |
plug->self = plug->ini(gwion, arg); |
198 |
✓✓ |
734 |
if(arg) |
199 |
|
2 |
plug_free_arg(gwion->mp, arg); |
200 |
|
|
} |
201 |
|
730 |
} |
202 |
|
|
|
203 |
|
2 |
ANN void* get_module(const struct Gwion_ *gwion, const m_str name) { |
204 |
|
2 |
const Vector v = &gwion->data->plug->vec[GWPLUG_MODULE]; |
205 |
✓✓ |
5 |
for(m_uint i = 0; i < vector_size(v); ++i) { |
206 |
|
4 |
struct Plug_ *plug = (struct Plug_*)vector_at(v, i); |
207 |
✓✓ |
4 |
if(!strcmp(name, plug->name)) |
208 |
|
1 |
return plug->self; |
209 |
|
|
} |
210 |
|
1 |
return NULL; |
211 |
|
|
} |