flush
[m6w6/ext-psi] / src / validator.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/param.h>
5 #include <dlfcn.h>
6
7 #include <jit/jit.h>
8
9 #include "validator.h"
10
11 PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
12 {
13 if (!V) {
14 V = malloc(sizeof(*V));
15 }
16 memset(V, 0, sizeof(*V));
17
18 PSI_DataExchange((PSI_Data *) V, (PSI_Data *) P);
19
20 return V;
21 }
22
23 void PSI_ValidatorDtor(PSI_Validator *V)
24 {
25 PSI_DataDtor((PSI_Data *) V);
26 memset(V, 0, sizeof(*V));
27 }
28
29 void PSI_ValidatorFree(PSI_Validator **V)
30 {
31 if (*V) {
32 PSI_ValidatorDtor(*V);
33 free(*V);
34 *V = NULL;
35 }
36 }
37
38 static int validate_lib(PSI_Validator *V) {
39 char lib[MAXPATHLEN];
40 const char *ptr = V->lib;
41 size_t len;
42
43 if (!ptr) {
44 /* FIXME: assume stdlib */
45 return 1;
46 } else if (!strchr(ptr, '/')) {
47 #ifdef DARWIN
48 len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
49 #else
50 len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
51 #endif
52 if (MAXPATHLEN == len) {
53 V->error(PSI_WARNING, "Library name too long: '%s'", ptr);
54 }
55 lib[len] = 0;
56 ptr = lib;
57 }
58 if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
59 V->error(PSI_WARNING, "Could not open library '%s': %s.", V->lib, dlerror());
60 return 0;
61 }
62 return 1;
63 }
64 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
65 size_t i;
66
67 if (type->real) {
68 return 1;
69 }
70 for (i = 0; i < defs->count; ++i) {
71 if (!strcmp(defs->list[i]->alias, type->name)) {
72 type->real = defs->list[i]->type;
73 return 1;
74 }
75 }
76 return 0;
77 }
78 static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) {
79 if (type->type == PSI_T_NAME) {
80 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
81 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
82 " Use 'typedef <type> <basic_type>;' statement",
83 type->name, arg->var->name);
84 return 0;
85 }
86 }
87 return 1;
88 }
89 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
90 /* FIXME: check def->alias */
91 if (def->type->type == PSI_T_NAME) {
92 V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'",
93 def->type->name, def->alias);
94 return 0;
95 }
96 return 1;
97 }
98 static inline int validate_typedefs(PSI_Validator *V) {
99 size_t i;
100
101 for (i = 0; i < V->defs->count; ++i) {
102 if (!validate_typedef(V, V->defs->list[i])) {
103 return 0;
104 }
105 }
106
107 return 1;
108 }
109 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
110 {
111 if (!strcmp(func->var->name, "dlsym")) {
112 V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
113 return 0;
114 }
115
116 if (!validate_decl_type(V, func, func->type)) {
117 return 0;
118 }
119
120 decl->dlptr = dlsym(V->dlopened, func->var->name);
121 if (!decl->dlptr) {
122 V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
123 func->var->name, dlerror());
124 }
125 return 1;
126 }
127 static const char * const abi_ccs[] = {
128 "default", /* \ */
129 "extern", /* > - all the same */
130 "cdecl", /* / */
131 "stdcall",
132 "fastcall",
133 };
134 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
135 size_t i;
136
137 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++ i) {
138 if (strcasecmp(abi->convention, abi_ccs[i])) {
139 return 1;
140 }
141 }
142 V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
143 return 0;
144 }
145 static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) {
146 if (!validate_decl_type(V, arg, arg->type)) {
147 return 0;
148 }
149 return 1;
150 }
151 static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) {
152 size_t i;
153
154 for (i = 0; i < args->count; ++i) {
155 if (!validate_decl_arg(V, decl, args->args[i])) {
156 return 0;
157 }
158 }
159 return 1;
160 }
161 static inline int validate_decl(PSI_Validator *V, decl *decl) {
162 if (!validate_decl_abi(V, decl->abi)) {
163 return 0;
164 }
165 if (!validate_decl_func(V, decl, decl->func)) {
166 return 0;
167 }
168 if (decl->args && !validate_decl_args(V, decl, decl->args)) {
169 return 0;
170 }
171 return 1;
172 }
173 static inline int validate_decls(PSI_Validator *V) {
174 size_t i;
175
176 for (i = 0; i < V->decls->count; ++i) {
177 if (!validate_decl(V, V->decls->list[i])) {
178 return 0;
179 }
180 }
181 return 1;
182 }
183
184 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
185 /* FIXME */
186 return 1;
187 }
188 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
189 return 1;
190 }
191 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
192 size_t i;
193
194 for (i = 0; i < args->count; ++i) {
195 if (!validate_impl_arg(V, impl, args->args[i])) {
196 return 0;
197 }
198 }
199 return 1;
200 }
201 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
202 /* FIXME: does name need any validation? */
203 if (!validate_impl_type(V, impl, func->return_type)) {
204 return 0;
205 }
206 if (func->args && !validate_impl_args(V, impl, func->args)) {
207 return 0;
208 }
209 return 1;
210 }
211 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
212 size_t i;
213
214 for (i = 0; i < decls->count; ++i) {
215 if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
216 return decls->list[i];
217 }
218 }
219 return NULL;
220 }
221
222 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
223 /* okay,
224 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
225 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
226 * - we can have any count of set stmts; processing out vars
227 * - we can have any count of free stmts; freeing any out vars
228 */
229 size_t i, j, k;
230 return_stmt *ret;
231 decl *decl;
232
233 if (!stmts) {
234 V->error(PSI_WARNING, "Missing body for implementation %s!",
235 impl->func->name);
236 return 0;
237 }
238 if (stmts->ret.count != 1) {
239 if (stmts->ret.count > 1) {
240 V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
241 "found %zu, exactly one is needed",
242 impl->func->name, stmts->ret.count);
243 } else {
244 V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
245 impl->func->name);
246 }
247 return 0;
248 }
249
250 ret = stmts->ret.list[0];
251 decl = locate_impl_decl(V->decls, ret);
252 if (!decl) {
253 V->error(PSI_WARNING, "Missing declaration for implementation %s",
254 impl->func->name);
255 return 0;
256 }
257
258 /* check that we have a let stmt for every decl arg */
259 for (i = 0; i < decl->args->count; ++i) {
260 decl_arg *darg = decl->args->args[i];
261 int check = 0;
262
263 for (j = 0; j < stmts->let.count; ++j) {
264 let_stmt *let = stmts->let.list[j];
265
266 if (!strcmp(let->var->name, darg->var->name)) {
267 darg->let = let;
268 check = 1;
269 break;
270 }
271 }
272 if (!check) {
273 V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
274 "of declaration '%s' for implementation '%s'",
275 darg->type->name, (int) darg->var->pointer_level, "*****",
276 darg->var->name, decl->func->var->name, impl->func->name);
277 return 0;
278 }
279 }
280 /* check that the let_value references a known variable or NULL */
281 for (i = 0; i < stmts->let.count; ++i) {
282 let_stmt *let = stmts->let.list[i];
283 int check = 0;
284
285 if (let->val->var) {
286 for (j = 0; j < impl->func->args->count; ++j) {
287 impl_arg *iarg = impl->func->args->args[j];
288
289 if (!strcmp(let->val->var->name, iarg->var->name)) {
290 let->arg = iarg;
291 check = 1;
292 break;
293 }
294 }
295 if (!check) {
296 V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
297 " for variable '%s' of implementation '%s'",
298 let->val->var->name, let->var->name, impl->func->name);
299 return 0;
300 }
301 }
302 }
303 /* check that set stmts reference known variables */
304 for (i = 0; i < stmts->set.count; ++i) {
305 set_stmt *set = stmts->set.list[i];
306 int check = 0;
307
308 for (j = 0; j < impl->func->args->count; ++j) {
309 impl_arg *iarg = impl->func->args->args[j];
310
311 if (!strcmp(set->var->name, iarg->var->name)) {
312 set->arg = iarg;
313 check = 1;
314 break;
315 }
316 }
317 if (!check) {
318 V->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement"
319 " of implementation '%s'",
320 set->var->name, impl->func->name);
321 return 0;
322 }
323
324 for (j = 0; j < set->val->vars->count; ++j) {
325 decl_var *set_var = set->val->vars->vars[j];
326
327 check = 0;
328 for (k = 0; k < decl->args->count; ++k) {
329 decl_arg *set_arg = decl->args->args[k];
330
331 if (!strcmp(set_var->name, set_arg->var->name)) {
332 check = 1;
333 set_var->arg = set_arg;
334 break;
335 }
336 }
337
338 if (!check) {
339 V->error(PSI_WARNING, "Unknown value '%s' of `set` statement"
340 " for variable '$%s' of implementation '%s'",
341 set_var->name, set->arg->var->name, impl->func->name);
342 return 0;
343 }
344 }
345 }
346 /* check free stmts */
347 for (i = 0; i < stmts->fre.count; ++i) {
348 free_stmt *fre = stmts->fre.list[i];
349
350 for (j = 0; j < fre->vars->count; ++j) {
351 decl_var *free_var = fre->vars->vars[j];
352 int check = 0;
353
354 if (!strcmp(free_var->name, decl->func->var->name)) {
355 continue;
356 }
357 for (k = 0; k < decl->args->count; ++k) {
358 decl_arg *free_arg = decl->args->args[k];
359
360 if (!strcmp(free_var->name, free_arg->var->name)) {
361 check = 1;
362 free_var->arg = free_arg;
363 break;
364 }
365 }
366
367 if (!check) {
368 V->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
369 " of implementation '%s'",
370 free_var->name, impl->func->name);
371 return 0;
372 }
373 }
374 }
375
376 impl->decl = decl;
377
378 return 1;
379 }
380
381 static inline int validate_impl(PSI_Validator *V, impl *impl) {
382 if (!validate_impl_func(V, impl, impl->func)) {
383 return 0;
384 }
385 if (!validate_impl_stmts(V, impl, impl->stmts)) {
386 return 0;
387 }
388 return 1;
389 }
390 static inline int validate_impls(PSI_Validator *V) {
391 size_t i;
392
393 for (i = 0; i < V->impls->count; ++i) {
394 if (!validate_impl(V, V->impls->list[i])) {
395 return 0;
396 }
397 }
398 return 1;
399 }
400
401 int PSI_ValidatorValidate(PSI_Validator *V)
402 {
403 if (!validate_lib(V)) {
404 return 0;
405 }
406 if (V->defs && !validate_typedefs(V)) {
407 return 0;
408 }
409 if (V->decls && !validate_decls(V)) {
410 return 0;
411 }
412 if (V->impls && !validate_impls(V)) {
413 return 0;
414 }
415 return 1;
416 }