7c7a245abee60d27e54581163a583ecbe297971b
[m6w6/ext-psi] / src / context_validate.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include "php.h"
6
7 #include <sys/param.h>
8 #include <dlfcn.h>
9
10 #include "php_psi.h"
11 #include "php_psi_stdinc.h"
12 #include "php_psi_stdtypes.h"
13 #include "php_psi_macros.h"
14 #include "php_psi_redirs.h"
15
16 #include "calc.h"
17 #include "marshal.h"
18 #include "engine.h"
19
20 static int validate_lib(PSI_Data *data, void **dlopened) {
21 char lib[MAXPATHLEN];
22 const char *ptr = data->psi.file.ln;
23 size_t len;
24
25 if (!ptr) {
26 /* FIXME: assume stdlib */
27 return 1;
28 } else if (!strchr(ptr, '/')) {
29 len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX);
30 if (MAXPATHLEN == len) {
31 data->error(NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
32 }
33 lib[len] = 0;
34 ptr = lib;
35 }
36 if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
37 data->error(NULL, PSI_WARNING, "Could not open library '%s': %s.",
38 data->psi.file.ln, dlerror());
39 return 0;
40 }
41 return 1;
42 }
43
44 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
45 size_t i;
46 struct psi_std_type *stdtyp;
47
48 if (type->real) {
49 return 1;
50 }
51 if (defs) for (i = 0; i < defs->count; ++i) {
52 decl_arg *def = defs->list[i];
53
54 if (def->type->type != type->type && !strcmp(def->var->name, type->name)) {
55 type->real = def->type;
56 return 1;
57 }
58 }
59 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
60 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
61 type->type = stdtyp->type_tag;
62 return 1;
63 }
64 }
65
66 return 0;
67 }
68
69 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
70 size_t i;
71
72 if (type->strct) {
73 return 1;
74 }
75 if (structs) for (i = 0; i < structs->count; ++i) {
76 if (!strcmp(structs->list[i]->name, type->name)) {
77 type->strct = structs->list[i];
78 return 1;
79 }
80 }
81 return 0;
82 }
83
84 static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
85 size_t i;
86
87 if (type->enm) {
88 return 1;
89 }
90 if (enums) for (i = 0; i < enums->count; ++i) {
91 if (!strcmp(enums->list[i]->name, type->name)) {
92 type->enm = enums->list[i];
93 return 1;
94 }
95 }
96 return 0;
97 }
98
99 static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
100 switch (type->type) {
101 case PSI_T_CHAR:
102 case PSI_T_SHORT:
103 case PSI_T_INT:
104 case PSI_T_LONG:
105 case PSI_T_NAME:
106 if (!locate_decl_type_alias(data->defs, type)) {
107 return 0;
108 }
109 if (type->real) {
110 return validate_decl_type(data, type->real);
111 }
112 return 1;
113 case PSI_T_STRUCT:
114 if (!locate_decl_type_struct(data->structs, type)) {
115 return 0;
116 }
117 break;
118 case PSI_T_ENUM:
119 if (!locate_decl_type_enum(data->enums, type)) {
120 return 0;
121 }
122 }
123 return 1;
124 }
125 static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
126 if (!validate_decl_type(data, def->type)) {
127 data->error(def->token, PSI_WARNING,
128 "Type '%s' cannot be aliased to %s'%s'",
129 def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",
130 def->var->name);
131 return 0;
132 }
133 return 1;
134 }
135
136 static inline int validate_constant(PSI_Data *data, constant *c) {
137 /* FIXME */
138 return 1;
139 }
140
141 static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
142 if (!validate_decl_type(data, arg->type)) {
143 data->error(arg->type->token, PSI_WARNING,
144 "Cannot use '%s'(%d) as type for decl var '%s'",
145 arg->type->name, arg->type->type, arg->var->name);
146 return 0;
147 }
148 return 1;
149 }
150
151 static int psi_sort_struct_arg_cmp(const void *_a, const void *_b) {
152 decl_arg *a = *(decl_arg **)_a, *b = *(decl_arg **)_b;
153
154 if (a->layout->pos == b->layout->pos) {
155 if (a->layout->len == b->layout->len) {
156 return 0;
157 } else if (a->layout->len > b->layout->len) {
158 return -1;
159 } else {
160 return 1;
161 }
162 } else if (a->layout->pos > b->layout->pos) {
163 return 1;
164 } else {
165 return -1;
166 }
167 }
168 static void psi_sort_struct_arg_swp(void *a, void *b) {
169 decl_arg **_a = a, **_b = b, *_c;
170
171 _c = *_b;
172 *_b = *_a;
173 *_a = _c;
174 }
175 static inline void psi_sort_struct_args(decl_struct *s) {
176 zend_insert_sort(s->args->args, s->args->count, sizeof(*s->args->args),
177 psi_sort_struct_arg_cmp, psi_sort_struct_arg_swp);
178 }
179
180 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
181 size_t i;
182
183 for (i = 0; i < s->args->count; ++i) {
184 if (!validate_decl_arg(data, s->args->args[i])) {
185 return 0;
186 }
187 }
188
189 for (i = 0; i < s->args->count; ++i) {
190 decl_arg *darg = s->args->args[i];
191
192 if (!validate_decl_arg(data, darg)) {
193 return 0;
194 }
195
196 ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
197 darg->var->arg = darg;
198
199 if (darg->layout) {
200 size_t size;
201
202 if (darg->var->array_size) {
203 size = psi_t_size(real_decl_type(darg->type)->type) * darg->var->array_size;
204 } else if (darg->var->pointer_level) {
205 size = psi_t_size(PSI_T_POINTER);
206 } else {
207 decl_type *real = real_decl_type(darg->type);
208
209 if (real->type == PSI_T_STRUCT) {
210 size = real->strct->size;
211 } else {
212 size = psi_t_size(real->type);
213 }
214 }
215 if (darg->layout->len != size) {
216 data->error(darg->token, PSI_WARNING,
217 "Computed length %zu of %s.%s does not match"
218 " pre-defined length %zu of type '%s'",
219 darg->layout->len, s->name, darg->var->name, size,
220 darg->type->name);
221 return 0;
222 }
223 } else {
224 token_t t;
225 size_t size, align;
226
227 if (darg->var->pointer_level && (!darg->var->array_size || darg->var->pointer_level == 1)) {
228 t = PSI_T_POINTER;
229 } else {
230 t = real_decl_type(darg->type)->type;
231 }
232
233 switch (t) {
234 case PSI_T_STRUCT:
235 if (!validate_decl_struct(data, real_decl_type(darg->type)->strct)) {
236 return 0;
237 }
238 size = real_decl_type(darg->type)->strct->size;
239 break;
240 default:
241 size = psi_t_size(t) * (darg->var->array_size ?: 1);
242 break;
243 }
244
245 if (i) {
246 decl_arg *last = s->args->args[i-1];
247
248 align = psi_t_align(t, last->layout->pos + last->layout->len);
249 } else {
250 align = 0;
251 }
252
253 darg->layout = init_decl_struct_layout(align, size);
254 }
255 if (s->size < darg->layout->pos + darg->layout->len) {
256 s->size = darg->layout->pos + darg->layout->len;
257 /* FIXME: align struct */
258 }
259 }
260
261 psi_sort_struct_args(s);
262
263 return 1;
264 }
265
266 static const char * const abi_ccs[] = {
267 "default", /* \ */
268 "extern", /* > - all the same */
269 "cdecl", /* / */
270 "mscdecl",
271 "stdcall",
272 "fastcall",
273 };
274 static inline int validate_decl_abi(PSI_Data *data, decl_abi *abi) {
275 size_t i;
276
277 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) {
278 if (strcasecmp(abi->convention, abi_ccs[i])) {
279 return 1;
280 }
281 }
282 return 0;
283 }
284 static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func)
285 {
286 struct psi_func_redir *redir;
287
288 if (!strcmp(func->var->name, "dlsym")) {
289 data->error(func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)");
290 return 0;
291 }
292
293 if (!validate_decl_arg(data, func)) {
294 return 0;
295 }
296 for (redir = &psi_func_redirs[0]; redir->name; ++redir) {
297 if (!strcmp(func->var->name, redir->name)) {
298 decl->call.sym = redir->func;
299 }
300 }
301 if (!decl->call.sym) {
302 #ifndef RTLD_NEXT
303 # define RTLD_NEXT ((void *) -1l)
304 #endif
305 decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name);
306 if (!decl->call.sym) {
307 data->error(func->token, PSI_WARNING,
308 "Failed to locate symbol '%s': %s",
309 func->var->name, dlerror());
310 }
311 }
312 return 1;
313 }
314
315 static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
316 if (!validate_decl_abi(data, decl->abi)) {
317 data->error(decl->abi->token, PSI_WARNING,
318 "Invalid calling convention: '%s'", decl->abi->token->text);
319 return 0;
320 }
321 if (!validate_decl_func(data, dl, decl, decl->func)) {
322 return 0;
323 }
324 if (decl->args) {
325 size_t i;
326
327 for (i = 0; i < decl->args->count; ++i) {
328 if (!validate_decl_arg(data, decl->args->args[i])) {
329 return 0;
330 }
331 }
332 }
333 return 1;
334 }
335 static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
336 size_t i;
337
338 if (args) for (i = 0; i < args->count; ++i) {
339 decl_arg *arg = args->args[i];
340
341 if (!strcmp(var->name, arg->var->name)) {
342 ZEND_ASSERT(!var->arg || var->arg == arg);
343 return var->arg = arg;
344 }
345 }
346 if (func && !strcmp(var->name, func->var->name)) {
347 return var->arg = func;
348 }
349
350 return NULL;
351 }
352 static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) {
353 if (s->args) {
354 return locate_decl_var_arg(var, s->args, NULL);
355 }
356
357 return NULL;
358 }
359 static inline constant *locate_num_exp_constant(num_exp *exp, constants *consts) {
360 size_t i;
361
362 for (i = 0; i < consts->count; ++i) {
363 constant *cnst = consts->list[i];
364
365 if (!strcmp(cnst->name, exp->u.numb)) {
366 free(exp->u.numb);
367 return exp->u.cnst = cnst;
368 }
369 }
370
371 return NULL;
372 }
373 static inline decl_enum_item *locate_num_exp_enum_item_ex(num_exp *exp, decl_enum *e) {
374 size_t k;
375
376 if (e) for (k = 0; k < e->items->count; ++k) {
377 decl_enum_item *i = e->items->list[k];
378
379 if (!strcmp(i->name, exp->u.dvar->name)) {
380 free_decl_var(exp->u.dvar);
381 exp->t = PSI_T_ENUM;
382 exp->u.enm = i;
383 return i;
384 }
385 }
386 return NULL;
387 }
388 static inline decl_enum_item *locate_num_exp_enum_item(num_exp *exp, decl_enums *enums) {
389 size_t j;
390
391 if (enums) for (j = 0; j < enums->count; ++j) {
392 decl_enum *e = enums->list[j];
393 decl_enum_item *i = locate_num_exp_enum_item_ex(exp, e);
394
395 if (i) {
396 return i;
397 }
398 }
399 return NULL;
400 }
401 static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
402 if (exp->operand) {
403 switch (exp->operator) {
404 case PSI_T_PLUS:
405 exp->calculator = psi_calc_add;
406 break;
407 case PSI_T_MINUS:
408 exp->calculator = psi_calc_sub;
409 break;
410 case PSI_T_ASTERISK:
411 exp->calculator = psi_calc_mul;
412 break;
413 case PSI_T_SLASH:
414 exp->calculator = psi_calc_div;
415 break;
416 EMPTY_SWITCH_DEFAULT_CASE();
417 }
418 if (!validate_num_exp(data, exp->operand, dargs, func, enm)) {
419 return 0;
420 }
421 }
422 switch (exp->t) {
423 case PSI_T_NAME:
424 if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
425 if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
426 data->error(exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
427 exp->u.dvar->name);
428 return 0;
429 }
430 }
431 return 1;
432 case PSI_T_NSNAME:
433 if (!locate_num_exp_constant(exp, data->consts)) {
434 data->error(exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
435 exp->u.numb);
436 return 0;
437 }
438 return 1;
439 case PSI_T_NUMBER:
440 case PSI_T_ENUM:
441 return 1;
442 default:
443 return 0;
444 }
445 }
446
447 static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
448 size_t j;
449
450 if (!e->items || !e->items->count) {
451 data->error(e->token, PSI_WARNING, "Empty enum '%s'", e->name);
452 return 0;
453 }
454
455 for (j = 0; j < e->items->count; ++j) {
456 decl_enum_item *i = e->items->list[j];
457
458 if (!i->num) {
459 if (j) {
460 i->inc.t = PSI_T_NUMBER;
461 i->inc.u.numb = "1";
462 i->inc.operator = PSI_T_PLUS;
463 i->inc.operand = i->prev->num ?: &i->prev->inc;
464 i->num = &i->inc;
465 } else {
466 i->inc.t = PSI_T_NUMBER;
467 i->inc.u.numb = "0";
468 i->num = &i->inc;
469 }
470 }
471 if (!validate_num_exp(data, i->num, NULL, NULL, e)) {
472 return 0;
473 }
474 }
475
476 return 1;
477 }
478
479 static inline int validate_set_value_handler(set_value *set) {
480 switch (set->func->type) {
481 case PSI_T_TO_BOOL:
482 set->func->handler = psi_to_bool;
483 break;
484 case PSI_T_TO_INT:
485 set->func->handler = psi_to_int;
486 break;
487 case PSI_T_TO_FLOAT:
488 set->func->handler = psi_to_double;
489 break;
490 case PSI_T_TO_STRING:
491 set->func->handler = psi_to_string;
492 break;
493 case PSI_T_TO_ARRAY:
494 set->func->handler = psi_to_array;
495 break;
496 case PSI_T_TO_OBJECT:
497 set->func->handler = psi_to_object;
498 break;
499 case PSI_T_VOID:
500 set->func->handler = psi_to_void;
501 break;
502 case PSI_T_ELLIPSIS:
503 if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) {
504 set->func->handler = psi_to_recursive;
505 set->inner = set->outer.set->inner;
506 set->count = set->outer.set->count;
507 break;
508 }
509 /* no break */
510 default:
511 return 0;
512 }
513 return 1;
514 }
515 static inline void decl_var_arg_v(decl_args *args, va_list argp) {
516 int argc;
517 decl_arg **argv;
518
519 memset(args, 0, sizeof(*args));
520
521 while ((argc = va_arg(argp, int))) {
522 argv = va_arg(argp, decl_arg **);
523 while (argc--) {
524 add_decl_arg(args, *argv++);
525 }
526 }
527 }
528 static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg *ref, decl_args *ref_list) {
529 size_t i;
530 decl_type *ref_type;
531 decl_var *set_var = set->vars->vars[0];
532
533 if (!validate_set_value_handler(set)) {
534 data->error(set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", set->func->name);
535 return 0;
536 }
537
538 for (i = 0; i < set->vars->count; ++i) {
539 decl_var *svar = set->vars->vars[i];
540 if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) {
541 data->error(svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name);
542 return 0;
543 }
544 }
545
546 if (!ref) {
547 ref = set_var->arg;
548 }
549 ref_type = real_decl_type(ref->type);
550
551 if (set->count) {
552 int is_to_array = (set->func->type == PSI_T_TO_ARRAY);
553 int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level);
554
555 if (!is_to_array && !is_pointer_to_struct) {
556 data->error(set->func->token, E_WARNING, "Inner `set` statement casts only work with "
557 "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name);
558 return 0;
559 }
560 }
561 if (set->num) {
562 if (!validate_num_exp(data, set->num, ref_list, ref, NULL)) {
563 return 0;
564 }
565 }
566
567 if (ref_type->type == PSI_T_STRUCT) {
568 /* to_array(struct, to_...) */
569 if (!set->outer.set || set->outer.set->inner != set->inner) {
570 for (i = 0; i < set->count; ++i) {
571 decl_var *sub_var = set->inner[i]->vars->vars[0];
572 decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var);
573
574 if (sub_ref) {
575 if (!validate_set_value_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) {
576 return 0;
577 }
578 }
579 }
580 }
581 } else if (set->count == 1) {
582 /* to_array(ptr, to_string(*ptr)) */
583 decl_var *sub_var = set->inner[0]->vars->vars[0];
584 decl_arg *sub_ref = locate_decl_var_arg(sub_var, ref_list, ref);
585
586 if (sub_ref) {
587 if (strcmp(sub_var->name, set_var->name)) {
588 data->error(sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
589 return 0;
590 }
591 if (!validate_set_value_ex(data, set->inner[0], sub_ref, ref_list)) {
592 return 0;
593 }
594 }
595 } else if (set->count > 1) {
596 data->error(set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once");
597 return 0;
598 }
599
600 return 1;
601 }
602 static inline int validate_set_value(PSI_Data *data, set_value *set, ...) {
603 va_list argp;
604 decl_args args = {0};
605 int check;
606
607 va_start(argp, set);
608 decl_var_arg_v(&args, argp);
609 va_end(argp);
610
611 check = validate_set_value_ex(data, set, NULL, &args);
612 if (args.args) {
613 free(args.args);
614 }
615 return check;
616 }
617 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
618 if (decls) {
619 size_t i;
620
621 for (i = 0; i < decls->count; ++i) {
622 if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) {
623 ret->decl = decls->list[i]->func;
624 return decls->list[i];
625 }
626 }
627 }
628
629 return NULL;
630 }
631 static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
632 return_stmt *ret;
633
634 /* we must have exactly one ret stmt delcaring the native func to call */
635 /* and which type cast to apply */
636 if (impl->stmts->ret.count != 1) {
637 if (impl->stmts->ret.count > 1) {
638 data->error(impl->stmts->ret.list[1]->token, PSI_WARNING,
639 "Too many `return` statements for implmentation %s;"
640 " found %zu, exactly one is needed",
641 impl->func->name, impl->stmts->ret.count);
642 } else {
643 data->error(impl->func->token, PSI_WARNING,
644 "Missing `return` statement for implementation %s",
645 impl->func->name);
646 }
647 return 0;
648 }
649
650 ret = impl->stmts->ret.list[0];
651
652 if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
653 data->error(ret->token, PSI_WARNING,
654 "Missing declaration '%s' for `return` statment for implementation %s",
655 ret->set->vars->vars[0]->name, impl->func->name);
656 return 0;
657 }
658
659 if (!validate_set_value(data, ret->set, 1, &ret->decl, impl->decl->args ? (int) impl->decl->args->count : 0, impl->decl->args ? impl->decl->args->args : NULL, 0)) {
660 return 0;
661 }
662
663 impl->decl->impl = impl;
664
665 return 1;
666 }
667
668 static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
669 size_t i, j;
670 /* we can have multiple let stmts */
671
672 /* check that we have a decl arg for every let stmt */
673 for (i = 0; i < impl->stmts->let.count; ++i) {
674 let_stmt *let = impl->stmts->let.list[i];
675 decl_var *let_var;
676 int check = 0;
677
678 if (let->val && let->val->kind == PSI_LET_TMP) {
679 let_var = let->val->data.var;
680 } else {
681 let_var = let->var;
682 }
683
684 if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) {
685 data->error(let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
686 " of implementation '%s'", let_var->name, impl->func->name);
687 return 0;
688 }
689
690 switch (let->val->kind) {
691 case PSI_LET_NULL:
692 break;
693 case PSI_LET_TMP:
694 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
695 /* e.g. let foo = *bar; */
696 let->var->pointer_level = let->val->data.var->pointer_level;
697 let->var->arg = init_decl_arg(
698 init_decl_type(
699 real_decl_type(let->val->data.var->arg->type)->type,
700 real_decl_type(let->val->data.var->arg->type)->name),
701 init_decl_var(
702 let->var->name,
703 let->var->pointer_level,
704 let->var->array_size));
705 break;
706 case PSI_LET_NUMEXP:
707 if (!validate_num_exp(data, let->val->data.num, impl->decl->args, impl->decl->func, NULL)) {
708 return 0;
709 }
710 break;
711 case PSI_LET_CALLOC:
712 if (!validate_num_exp(data, let->val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
713 return 0;
714 }
715 if (!validate_num_exp(data, let->val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
716 return 0;
717 }
718 break;
719 case PSI_LET_FUNC:
720 if (impl->func->args) {
721 for (j = 0; j < impl->func->args->count; ++j) {
722 impl_arg *iarg = impl->func->args->args[j];
723
724 if (!strcmp(let->val->data.func->var->name, iarg->var->name)) {
725 let->val->data.func->arg = iarg;
726 check = 1;
727 break;
728 }
729 }
730 }
731 if (!check) {
732 data->error(let->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement"
733 " for variable '%s' of implementation '%s'",
734 let->val->data.func->var->name, let->var->name, impl->func->name);
735 return 0;
736 }
737 break;
738 }
739 }
740
741 /* check that we have a let stmt for every decl arg */
742 if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) {
743 decl_arg *darg = impl->decl->args->args[i];
744 int check = 0;
745
746 for (j = 0; j < impl->stmts->let.count; ++j) {
747 let_stmt *let = impl->stmts->let.list[j];
748
749 if (!strcmp(let->var->name, darg->var->name)) {
750 darg->let = let;
751 check = 1;
752 break;
753 }
754 }
755 if (!check) {
756 data->error(impl->func->token, PSI_WARNING,
757 "Missing `let` statement for arg '%s %.*s%s'"
758 " of declaration '%s' for implementation '%s'",
759 darg->type->name, (int) darg->var->pointer_level, "*****",
760 darg->var->name, impl->decl->func->var->name, impl->func->name);
761 return 0;
762 }
763 }
764
765 return 1;
766 }
767 static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
768 size_t i, j, k;
769 /* we can have any count of set stmts; processing out vars */
770 /* check that set stmts reference known variables */
771 for (i = 0; i < impl->stmts->set.count; ++i) {
772 set_stmt *set = impl->stmts->set.list[i];
773 int check = 0;
774
775 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
776 impl_arg *iarg = impl->func->args->args[j];
777
778 if (!strcmp(set->var->name, iarg->var->name)) {
779 set->arg = iarg;
780 check = 1;
781 break;
782 }
783 }
784 if (!check) {
785 data->error(set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
786 " of implementation '%s'",
787 set->var->name, impl->func->name);
788 return 0;
789 }
790
791 for (j = 0; j < set->val->vars->count; ++j) {
792 decl_var *set_var = set->val->vars->vars[j];
793
794 check = 0;
795 if (impl->decl->args) {
796 for (k = 0; k < impl->decl->args->count; ++k) {
797 decl_arg *set_arg = impl->decl->args->args[k];
798
799 if (!strcmp(set_var->name, set_arg->var->name)) {
800 check = 1;
801 set_var->arg = set_arg;
802 if (!validate_set_value(data, set->val, 1, &set_arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
803 return 0;
804 }
805 break;
806 }
807 }
808 }
809 if (!check) {
810 for (k = 0; k < impl->stmts->let.count; ++k) {
811 let_stmt *let = impl->stmts->let.list[k];
812
813 /* check temp vars */
814 if (let->val && let->val->kind == PSI_LET_TMP) {
815 if (!strcmp(set_var->name, let->var->name)) {
816 check = 1;
817 set_var->arg = let->var->arg;
818 if (!validate_set_value(data, set->val, 1, &set_var->arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
819 return 0;
820 }
821 break;
822 }
823 }
824 }
825 }
826
827 if (!check) {
828 data->error(set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement"
829 " for variable '$%s' of implementation '%s'",
830 set_var->name, set->arg->var->name, impl->func->name);
831 return 0;
832 }
833 }
834 }
835 return 1;
836 }
837 static inline decl *locate_free_decl(decls *decls, free_call *f) {
838 if (decls) {
839 size_t i;
840
841 for (i = 0; i < decls->count; ++i) {
842 if (!strcmp(decls->list[i]->func->var->name, f->func)) {
843 f->decl = decls->list[i];
844 return decls->list[i];
845 }
846 }
847 }
848
849 return NULL;
850 }
851 static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
852 size_t i, j, k, l;
853 /* we can have any count of free stmts; freeing any out vars */
854 for (i = 0; i < impl->stmts->fre.count; ++i) {
855 free_stmt *fre = impl->stmts->fre.list[i];
856
857 for (j = 0; j < fre->calls->count; ++j) {
858 free_call *free_call = fre->calls->list[j];
859
860 /* first find the decl of the free func */
861 if (!locate_free_decl(data->decls, free_call)) {
862 data->error(free_call->token, PSI_WARNING,
863 "Missing declaration '%s' in `free` statement"
864 " of implementation '%s'",
865 free_call->func, impl->func->name);
866 return 0;
867 }
868
869
870
871 /* now check for known vars */
872 for (l = 0; l < free_call->vars->count; ++l) {
873 int check = 0;
874 decl_var *free_var = free_call->vars->vars[l];
875
876 if (!strcmp(free_var->name, impl->decl->func->var->name)) {
877 check = 1;
878 free_var->arg = impl->decl->func;
879 } else if (impl->decl->args) {
880 for (k = 0; k < impl->decl->args->count; ++k) {
881 decl_arg *free_arg = impl->decl->args->args[k];
882
883 if (!strcmp(free_var->name, free_arg->var->name)) {
884 check = 1;
885 free_var->arg = free_arg;
886 break;
887 }
888 }
889 }
890
891 if (!check) {
892 data->error(free_var->token, PSI_WARNING,
893 "Unknown variable '%s' of `free` statement"
894 " of implementation '%s'",
895 free_var->name, impl->func->name);
896 return 0;
897 }
898 }
899 }
900 }
901 return 1;
902 }
903 static inline int validate_impl_stmts(PSI_Data *data, impl *impl) {
904 if (!impl->stmts) {
905 data->error(impl->func->token, PSI_WARNING,
906 "Missing body for implementation %s!",
907 impl->func->name);
908 return 0;
909 }
910
911 if (!validate_impl_ret_stmt(data, impl)) {
912 return 0;
913 }
914
915 if (!validate_impl_let_stmts(data, impl)) {
916 return 0;
917 }
918 if (!validate_impl_set_stmts(data, impl)) {
919 return 0;
920 }
921 if (!validate_impl_free_stmts(data, impl)) {
922 return 0;
923 }
924
925 return 1;
926 }
927
928 static inline int validate_impl_args(PSI_Data *data, impl *impl) {
929 int def = 0;
930 size_t i;
931
932 for (i = 0; i < impl->func->args->count; ++i) {
933 impl_arg *iarg = impl->func->args->args[i];
934
935 if (iarg->def) {
936 def = 1;
937 } else if (def) {
938 data->error(impl->func->token, PSI_WARNING,
939 "Non-optional argument %zu '$%s' of implementation '%s'"
940 " follows optional argument",
941 i+1, iarg->var->name, impl->func->name);
942 return 0;
943 }
944 }
945
946 return 1;
947 }
948
949 static inline int validate_impl(PSI_Data *data, impl *impl) {
950 if (!validate_impl_args(data, impl)) {
951 return 0;
952 }
953 return validate_impl_stmts(data, impl);
954 }
955
956
957 int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
958 {
959 PSI_Data *D;
960 void *dlopened = NULL;
961 size_t i, count = C->count++, check_round, check_count;
962 decl_typedefs *check_defs = P->defs;
963 decl_structs *check_structs = P->structs;
964 decl_enums *check_enums = P->enums;
965
966 C->data = realloc(C->data, C->count * sizeof(*C->data));
967 D = PSI_DataExchange(&C->data[count], PSI_DATA(P));
968 /*
969 if (D->defs) {
970 for (i = 0; i < D->defs->count; ++i) {
971 if (validate_decl_typedef(PSI_DATA(C), D->defs->list[i])) {
972 C->defs = add_decl_typedef(C->defs, D->defs->list[i]);
973 } else {
974 check_defs = add_decl_typedef(check_defs, D->defs->list[i]);
975 }
976 }
977 }
978 if (D->structs) {
979 for (i = 0; i < D->structs->count; ++i) {
980 if (validate_decl_struct(PSI_DATA(C), D->structs->list[i])) {
981 C->structs = add_decl_struct(C->structs, D->structs->list[i]);
982 } else {
983 check_structs = add_decl_struct(check_structs, D->structs->list[i]);
984 }
985 }
986 }
987 if (D->enums) {
988 for (i = 0; i < D->enums->count; ++i) {
989 if (validate_decl_enum(PSI_DATA(C), D->enums->list[i])) {
990 C->enums = add_decl_enum(C->enums, D->enums->list[i]);
991 } else {
992 check_enums = add_decl_enum(check_enums, D->enums->list[i]);
993 }
994 }
995 }
996 */
997 #define REVALIDATE(what) do { \
998 if (check_round && check_ ##what) { \
999 free(check_ ##what->list); \
1000 free(check_ ##what); \
1001 } \
1002 check_ ##what = recheck_ ##what; \
1003 } while (0)
1004 #define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
1005 #define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
1006
1007 for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
1008 decl_typedefs *recheck_defs = NULL;
1009 decl_structs *recheck_structs = NULL;
1010 decl_enums *recheck_enums = NULL;
1011
1012 check_count = CHECK_TOTAL;
1013 fprintf(stderr, "### Validation round %zu with %zu checks\n", check_round, check_count);
1014
1015 for (i = 0; i < CHECK_COUNT(defs); ++i) {
1016 if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
1017 C->defs = add_decl_typedef(C->defs, check_defs->list[i]);
1018 } else {
1019 recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]);
1020 }
1021 }
1022 for (i = 0; i < CHECK_COUNT(structs); ++i) {
1023 if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) {
1024 C->structs = add_decl_struct(C->structs, check_structs->list[i]);
1025 } else {
1026 recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
1027 }
1028 }
1029 for (i = 0; i < CHECK_COUNT(enums); ++i) {
1030 if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
1031 C->enums = add_decl_enum(C->enums, check_enums->list[i]);
1032 } else {
1033 recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]);
1034 }
1035 }
1036
1037 REVALIDATE(defs);
1038 REVALIDATE(structs);
1039 REVALIDATE(enums);
1040 }
1041
1042
1043 if (D->consts) {
1044 for (i = 0; i < D->consts->count; ++i) {
1045 if (validate_constant(PSI_DATA(C), D->consts->list[i])) {
1046 C->consts = add_constant(C->consts, D->consts->list[i]);
1047 }
1048 }
1049 }
1050
1051 if (!validate_lib(D, &dlopened)) {
1052 return 0;
1053 }
1054
1055 add_decl_lib(&C->psi.libs, dlopened);
1056
1057 if (D->decls) {
1058 for (i = 0; i < D->decls->count; ++i) {
1059 if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) {
1060 C->decls = add_decl(C->decls, D->decls->list[i]);
1061 }
1062 }
1063 }
1064 if (D->impls) {
1065 for (i = 0; i < D->impls->count; ++i) {
1066 if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
1067 C->impls = add_impl(C->impls, D->impls->list[i]);
1068 }
1069 }
1070 }
1071
1072 return 1;
1073 }
1074
1075 int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source)
1076 {
1077 size_t i;
1078 int errors = 0;
1079
1080 if (source->defs) for (i = 0; i < source->defs->count; ++i) {
1081 decl_arg *def = source->defs->list[i];
1082
1083 if (validate_decl_typedef(source, def)) {
1084 if (dest) {
1085 dest->defs = add_decl_typedef(dest->defs, def);
1086 }
1087 } else {
1088 ++errors;
1089 }
1090 }
1091
1092 if (source->consts) for (i = 0; i < source->consts->count; ++i) {
1093 constant *constant = source->consts->list[i];
1094
1095 if (validate_constant(source, constant)) {
1096 if (dest) {
1097 dest->consts = add_constant(dest->consts, constant);
1098 }
1099 } else {
1100 ++errors;
1101 }
1102 }
1103
1104 if (source->structs) for (i = 0; i < source->structs->count; ++i) {
1105 decl_struct *dstruct = source->structs->list[i];
1106
1107 if (validate_decl_struct(source, dstruct)) {
1108 if (dest) {
1109 dest->structs = add_decl_struct(dest->structs, dstruct);
1110 }
1111 } else {
1112 ++errors;
1113 }
1114 }
1115
1116 if (source->enums) for (i = 0; i < source->enums->count; ++i) {
1117 decl_enum *denum = source->enums->list[i];
1118
1119 if (validate_decl_enum(source, denum)) {
1120 if (dest) {
1121 dest->enums = add_decl_enum(dest->enums, denum);
1122 }
1123 } else {
1124 ++errors;
1125 }
1126 }
1127
1128 if (source->decls) for (i = 0; i < source->decls->count; ++i) {
1129 decl *decl = source->decls->list[i];
1130
1131 if (validate_decl(source, NULL, decl)) {
1132 if (dest) {
1133 dest->decls = add_decl(dest->decls, decl);
1134 }
1135 } else {
1136 ++errors;
1137 }
1138 }
1139
1140 if (source->impls) for (i = 0; i < source->impls->count; ++i) {
1141 impl *impl = source->impls->list[i];
1142
1143 if (validate_impl(source, impl)) {
1144 if (dest) {
1145 dest->impls = add_impl(dest->impls, impl);
1146 }
1147 } else {
1148 ++errors;
1149 }
1150 }
1151
1152 return errors;
1153 }