made the real decl_type a union
[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 "parser.h"
17 #include "calc.h"
18 #include "marshal.h"
19 #include "engine.h"
20
21 static int validate_lib(PSI_Data *data, void **dlopened) {
22 char lib[MAXPATHLEN];
23 const char *ptr = data->psi.file.ln;
24 size_t len;
25
26 if (!ptr) {
27 /* FIXME: assume stdlib */
28 return 1;
29 } else if (!strchr(ptr, '/')) {
30 len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX);
31 if (MAXPATHLEN == len) {
32 data->error(data, NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
33 }
34 lib[len] = 0;
35 ptr = lib;
36 }
37 if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
38 data->error(data, NULL, PSI_WARNING, "Could not open library '%s': %s.",
39 data->psi.file.ln, dlerror());
40 return 0;
41 }
42 return 1;
43 }
44
45 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
46 size_t i;
47 struct psi_std_type *stdtyp;
48
49 if (type->real.def) {
50 return 1;
51 }
52 if (defs) for (i = 0; i < defs->count; ++i) {
53 decl_arg *def = defs->list[i];
54
55 if (def->type->type != type->type && !strcmp(def->var->name, type->name)) {
56 type->real.def = def;
57 return 1;
58 }
59 }
60 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
61 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
62 type->type = stdtyp->type_tag;
63 return 1;
64 }
65 }
66
67 return 0;
68 }
69
70 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
71 size_t i;
72
73 if (type->real.strct) {
74 return 1;
75 }
76 if (structs) for (i = 0; i < structs->count; ++i) {
77 if (!strcmp(structs->list[i]->name, type->name)) {
78 type->real.strct = structs->list[i];
79 return 1;
80 }
81 }
82 return 0;
83 }
84
85 static inline int locate_decl_type_union(decl_unions *unions, decl_type *type) {
86 size_t i;
87
88 if (type->real.unn) {
89 return 1;
90 }
91 if (unions) for (i = 0; i < unions->count; ++i) {
92 if (!strcmp(unions->list[i]->name, type->name)) {
93 type->real.unn = unions->list[i];
94 return 1;
95 }
96 }
97 return 0;
98 }
99
100 static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
101 size_t i;
102
103 if (type->real.enm) {
104 return 1;
105 }
106 if (enums) for (i = 0; i < enums->count; ++i) {
107 if (!strcmp(enums->list[i]->name, type->name)) {
108 type->real.enm = enums->list[i];
109 return 1;
110 }
111 }
112 return 0;
113 }
114
115 static inline int locate_decl_type_decl(decls *decls, decl_type *type) {
116 size_t i;
117
118 if (type->real.func) {
119 return 1;
120 }
121 if (decls) for (i = 0; i < decls->count; ++i) {
122 if (!strcmp(decls->list[i]->func->var->name, type->name)) {
123 type->real.func = decls->list[i];
124 return 1;
125 }
126 }
127
128 return 0;
129 }
130
131 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s);
132 static inline int validate_decl_union(PSI_Data *data, decl_union *u);
133 static inline int validate_decl_enum(PSI_Data *data, decl_enum *e);
134
135 static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
136 if (weak_decl_type(type)) {
137 if (!locate_decl_type_alias(data->defs, type)) {
138 return 0;
139 }
140 if (type->real.def) {
141 return validate_decl_type(data, type->real.def->type);
142 }
143 return 1;
144 }
145
146 switch (type->type) {
147 case PSI_T_STRUCT:
148 if (!locate_decl_type_struct(data->structs, type)) {
149 return 0;
150 }
151 break;
152 case PSI_T_UNION:
153 if (!locate_decl_type_union(data->unions, type)) {
154 return 0;
155 }
156 break;
157 case PSI_T_ENUM:
158 if (!locate_decl_type_enum(data->enums, type)) {
159 return 0;
160 }
161 break;
162 case PSI_T_FUNCTION:
163 if (!locate_decl_type_decl(data->decls, type)) {
164 return 0;
165 }
166 break;
167 }
168 return 1;
169 }
170 static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
171 if (!validate_decl_type(data, def->type)) {
172 const char *pre;
173
174 switch (def->type->type) {
175 case PSI_T_STRUCT: pre = "struct "; break;
176 case PSI_T_UNION: pre = "union "; break;
177 case PSI_T_ENUM: pre = "enum "; break;
178 default: pre = ""; break;
179 }
180 data->error(data, def->token, PSI_WARNING,
181 "Type '%s' cannot be aliased to %s'%s'",
182 def->var->name, pre, def->type->name);
183 return 0;
184 }
185 if (def->type->type == PSI_T_VOID) {
186 if (def->var->pointer_level) {
187 def->type->type = PSI_T_POINTER;
188 } else {
189 data->error(data, def->token, PSI_WARNING,
190 "Type '%s' cannot be aliased to 'void'",
191 def->type->name);
192 return 0;
193 }
194 }
195 return 1;
196 }
197
198 static inline int validate_constant(PSI_Data *data, constant *c) {
199 /* FIXME */
200 return 1;
201 }
202
203 static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
204 if (!validate_decl_type(data, arg->type)) {
205 data->error(data, arg->type->token, PSI_WARNING,
206 "Cannot use '%s' as type for '%s'",
207 arg->type->name, arg->var->name);
208 return 0;
209 } else {
210 decl_type *real = real_decl_type(arg->type);
211
212 if (real->type == PSI_T_FUNCTION) {
213 }
214 }
215 return 1;
216 }
217
218 static int psi_sort_struct_arg_cmp(const void *_a, const void *_b) {
219 decl_arg *a = *(decl_arg **)_a, *b = *(decl_arg **)_b;
220
221 if (a->layout->pos == b->layout->pos) {
222 if (a->layout->len == b->layout->len) {
223 return 0;
224 } else if (a->layout->len > b->layout->len) {
225 return -1;
226 } else {
227 return 1;
228 }
229 } else if (a->layout->pos > b->layout->pos) {
230 return 1;
231 } else {
232 return -1;
233 }
234 }
235 static void psi_sort_struct_arg_swp(void *a, void *b) {
236 decl_arg **_a = a, **_b = b, *_c;
237
238 _c = *_b;
239 *_b = *_a;
240 *_a = _c;
241 }
242 static inline void psi_sort_struct_args(void **args, size_t count) {
243 zend_insert_sort(args, count, sizeof(*args),
244 psi_sort_struct_arg_cmp, psi_sort_struct_arg_swp);
245 }
246
247 static inline int validate_decl_struct_darg(PSI_Data *data, decl_arg *darg, void *current) {
248 decl_type *real = real_decl_type(darg->type);
249
250 /* pre-validate any structs/unions/enums */
251 switch (real->type) {
252 case PSI_T_STRUCT:
253 if (current && current == real->real.strct) {
254 return 1;
255 }
256 if (!locate_decl_type_struct(data->structs, real)) {
257 return 0;
258 }
259 if (!validate_decl_struct(data, real->real.strct)) {
260 return 0;
261 }
262 break;
263 case PSI_T_UNION:
264 if (current && current == real->real.unn) {
265 return 1;
266 }
267 if (!locate_decl_type_union(data->unions, real)) {
268 return 0;
269 }
270 if (!validate_decl_union(data, real->real.unn)) {
271 return 0;
272 }
273 break;
274 case PSI_T_ENUM:
275 if (current && current == real->real.enm) {
276 return 1;
277 }
278 if (!locate_decl_type_enum(data->enums, real)) {
279 return 0;
280 }
281 if (!validate_decl_enum(data, real->real.enm)) {
282 return 0;
283 }
284 break;
285 }
286
287 return 1;
288 }
289
290 static inline size_t sizeof_decl_arg(decl_arg *darg) {
291 size_t size;
292 decl_type *real = real_decl_type(darg->type);
293
294 if (darg->var->array_size) {
295 if (darg->var->pointer_level > 2) {
296 size = psi_t_size(PSI_T_POINTER) * darg->var->array_size;
297 } else {
298 size = psi_t_size(real->type) * darg->var->array_size;
299 }
300 } else if (darg->var->pointer_level) {
301 size = psi_t_size(PSI_T_POINTER);
302 } else {
303 switch (real->type) {
304 case PSI_T_UNION:
305 size = real->real.unn->size;
306 break;
307 case PSI_T_STRUCT:
308 size = real->real.strct->size;
309 break;
310 case PSI_T_ENUM:
311 default:
312 size = psi_t_size(real->type);
313 break;
314 }
315 }
316
317 ZEND_ASSERT(size);
318
319 return size;
320 }
321
322 static inline size_t alignof_decl_type(decl_type *t);
323 static inline size_t alignof_decl_arg(decl_arg *darg);
324 static inline size_t alignof_decl_union(decl_union *u);
325 static inline size_t alignof_decl_struct(decl_struct *s);
326
327 static inline size_t alignof_decl_args(decl_args *args) {
328 size_t i, maxalign = 0;
329
330 for (i = 0; i < args->count; ++i) {
331 decl_arg *darg = args->args[i];
332 size_t align = alignof_decl_arg(darg);
333
334 if (align > maxalign) {
335 maxalign = align;
336 }
337 }
338
339 return maxalign;
340 }
341
342 static inline size_t alignof_decl_struct(decl_struct *s) {
343 if (!s->align) {
344 s->align = alignof_decl_args(s->args);
345 }
346 return s->align;
347 }
348
349 static inline size_t alignof_decl_union(decl_union *u) {
350 if (!u->align) {
351 u->align = alignof_decl_args(u->args);
352 }
353 return u->align;
354 }
355
356 static inline size_t alignof_decl_type(decl_type *t) {
357 decl_type *real = real_decl_type(t);
358 size_t align;
359
360 switch (real->type) {
361 case PSI_T_STRUCT:
362 align = alignof_decl_struct(real->real.strct);
363 break;
364 case PSI_T_UNION:
365 align = alignof_decl_union(real->real.unn);
366 break;
367 case PSI_T_ENUM:
368 default:
369 align = psi_t_alignment(real->type);
370 }
371
372 return align;
373 }
374
375 static inline size_t alignof_decl_arg(decl_arg *darg) {
376 size_t align;
377
378 if (darg->var->pointer_level && (!darg->var->array_size || darg->var->pointer_level > 2)) {
379 align = psi_t_alignment(PSI_T_POINTER);
380 } else {
381 align = alignof_decl_type(darg->type);
382 }
383
384 return align;
385 }
386
387 static inline size_t align_decl_arg(decl_arg *darg, size_t *pos, size_t *len) {
388 size_t align = alignof_decl_arg(darg);
389
390 ZEND_ASSERT(align);
391
392 *len = sizeof_decl_arg(darg);
393 *pos = psi_align(align, *pos);
394
395 return align;
396 }
397
398 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
399 size_t i, pos, len, size, align;
400
401 if (!s->size && !s->args->count) {
402 data->error(data, s->token, PSI_WARNING,
403 "Cannot compute size of empty struct '%s'",
404 s->name);
405 return 0;
406 }
407
408 for (i = 0; i < s->args->count; ++i) {
409 decl_arg *darg = s->args->args[i];
410
411 if (!validate_decl_arg(data, darg)) {
412 return 0;
413 }
414
415 ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
416 darg->var->arg = darg;
417
418 if (!validate_decl_struct_darg(data, darg, s)) {
419 return 0;
420 } else if (darg->layout) {
421 pos = darg->layout->pos;
422
423 align = align_decl_arg(darg, &pos, &len);
424
425 if (darg->layout->len != len) {
426 data->error(data, darg->token, PSI_WARNING,
427 "Computed size %zu of %s.%s does not match"
428 " pre-defined size %zu of type '%s'",
429 len, s->name, darg->var->name, darg->layout->len,
430 darg->type->name);
431 }
432 if (darg->layout->pos != pos) {
433 data->error(data, darg->token, PSI_WARNING,
434 "Computed offset %zu of %s.%s does not match"
435 " pre-defined offset %zu",
436 pos, s->name, darg->var->name, darg->layout->pos);
437 }
438 } else {
439 if (i) {
440 pos = s->args->args[i-1]->layout->pos +
441 s->args->args[i-1]->layout->len;
442 } else {
443 pos = 0;
444 }
445
446 align = align_decl_arg(darg, &pos, &len);
447 darg->layout = init_decl_struct_layout(pos, len);
448 }
449
450 if (align > s->align) {
451 s->align = align;
452 }
453 }
454
455 psi_sort_struct_args((void **) s->args->args, s->args->count);
456
457 if (s->args->count) {
458 decl_arg *darg = s->args->args[s->args->count-1];
459
460 size = darg->layout->pos + darg->layout->len;
461 if (s->size < size) {
462 s->size = psi_align(size, s->align);
463 }
464 }
465
466 return 1;
467 }
468
469 static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
470 size_t i, pos, len, size = 0, align;
471
472 if (!u->size && !u->args->count) {
473 data->error(data, u->token, PSI_WARNING,
474 "Cannot compute size of empty union %s",
475 u->name);
476 return 0;
477 }
478
479 for (i = 0; i < u->args->count; ++i) {
480 decl_arg *darg = u->args->args[i];
481
482 if (!validate_decl_arg(data, darg)) {
483 return 0;
484 }
485
486 ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
487 darg->var->arg = darg;
488
489 if (!validate_decl_struct_darg(data, darg, u)) {
490 return 0;
491 } else if (darg->layout) {
492 pos = darg->layout->pos;
493
494 align = align_decl_arg(darg, &pos, &len);
495
496 if (darg->layout->pos != 0) {
497 data->error(data, darg->token, PSI_WARNING,
498 "Offset of %s.%s should be 0",
499 u->name, darg->var->name);
500 darg->layout->pos = 0;
501 }
502 if (darg->layout->len != len) {
503 data->error(data, darg->token, PSI_WARNING,
504 "Computed size %zu of %s.%s does not match"
505 " pre-defined size %zu of type '%s'",
506 len, u->name, darg->var->name, darg->layout->len,
507 darg->type->name);
508 }
509 } else {
510 pos = 0;
511
512 align = align_decl_arg(darg, &pos, &len);
513 darg->layout = init_decl_struct_layout(pos, len);
514
515 }
516 if (len > size) {
517 size = len;
518 }
519 if (align > u->align) {
520 u->align = align;
521 }
522 }
523
524 psi_sort_struct_args((void **) u->args->args, u->args->count);
525
526 if (u->size < size) {
527 u->size = psi_align(size, u->align);
528 }
529
530 return 1;
531 }
532
533 static const char * const abi_ccs[] = {
534 "default", /* \ */
535 "extern", /* > - all the same */
536 "cdecl", /* / */
537 "mscdecl",
538 "stdcall",
539 "fastcall",
540 };
541 static inline int validate_decl_abi(PSI_Data *data, decl_abi *abi) {
542 size_t i;
543
544 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) {
545 if (strcasecmp(abi->convention, abi_ccs[i])) {
546 return 1;
547 }
548 }
549 return 0;
550 }
551 static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func)
552 {
553 struct psi_func_redir *redir;
554
555 if (!strcmp(func->var->name, "dlsym")) {
556 data->error(data, func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)");
557 return 0;
558 }
559
560 for (redir = &psi_func_redirs[0]; redir->name; ++redir) {
561 if (!strcmp(func->var->name, redir->name)) {
562 decl->call.sym = redir->func;
563 }
564 }
565 if (!decl->call.sym) {
566 #ifndef RTLD_NEXT
567 # define RTLD_NEXT ((void *) -1l)
568 #endif
569 decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name);
570 if (!decl->call.sym) {
571 data->error(data, func->token, PSI_WARNING,
572 "Failed to locate symbol '%s': %s",
573 func->var->name, dlerror() ?: "not found");
574 }
575 }
576 return 1;
577 }
578 static inline int validate_decl_nodl(PSI_Data *data, decl *decl) {
579 if (!validate_decl_abi(data, decl->abi)) {
580 data->error(data, decl->abi->token, PSI_WARNING,
581 "Invalid calling convention: '%s'", decl->abi->token->text);
582 return 0;
583 }
584 if (!validate_decl_arg(data, decl->func)) {
585 return 0;
586 }
587 if (decl->args) {
588 size_t i;
589
590 for (i = 0; i < decl->args->count; ++i) {
591 if (!validate_decl_arg(data, decl->args->args[i])) {
592 return 0;
593 }
594 }
595 }
596 return 1;
597 }
598 static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
599 if (!validate_decl_nodl(data, decl)) {
600 return 0;
601 }
602 if (!validate_decl_func(data, dl, decl, decl->func)) {
603 return 0;
604 }
605 return 1;
606 }
607 static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
608 size_t i;
609
610 if (args) for (i = 0; i < args->count; ++i) {
611 decl_arg *arg = args->args[i];
612
613 if (!strcmp(var->name, arg->var->name)) {
614 ZEND_ASSERT(!var->arg || var->arg == arg);
615 return var->arg = arg;
616 }
617 }
618 if (func && !strcmp(var->name, func->var->name)) {
619 return var->arg = func;
620 }
621
622 return NULL;
623 }
624 static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) {
625 if (s->args) {
626 return locate_decl_var_arg(var, s->args, NULL);
627 }
628
629 return NULL;
630 }
631 static inline constant *locate_num_exp_constant(num_exp *exp, constants *consts) {
632 size_t i;
633
634 for (i = 0; i < consts->count; ++i) {
635 constant *cnst = consts->list[i];
636
637 if (!strcmp(cnst->name, exp->u.numb)) {
638 free(exp->u.numb);
639 return exp->u.cnst = cnst;
640 }
641 }
642
643 return NULL;
644 }
645 static inline decl_enum_item *locate_num_exp_enum_item_ex(num_exp *exp, decl_enum *e) {
646 size_t k;
647
648 if (e) for (k = 0; k < e->items->count; ++k) {
649 decl_enum_item *i = e->items->list[k];
650
651 if (!strcmp(i->name, exp->u.dvar->name)) {
652 free_decl_var(exp->u.dvar);
653 exp->t = PSI_T_ENUM;
654 exp->u.enm = i;
655 return i;
656 }
657 }
658 return NULL;
659 }
660 static inline decl_enum_item *locate_num_exp_enum_item(num_exp *exp, decl_enums *enums) {
661 size_t j;
662
663 if (enums) for (j = 0; j < enums->count; ++j) {
664 decl_enum *e = enums->list[j];
665 decl_enum_item *i = locate_num_exp_enum_item_ex(exp, e);
666
667 if (i) {
668 return i;
669 }
670 }
671 return NULL;
672 }
673 static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
674 if (exp->operand) {
675 switch (exp->operator) {
676 case PSI_T_PLUS:
677 exp->calculator = psi_calc_add;
678 break;
679 case PSI_T_MINUS:
680 exp->calculator = psi_calc_sub;
681 break;
682 case PSI_T_ASTERISK:
683 exp->calculator = psi_calc_mul;
684 break;
685 case PSI_T_SLASH:
686 exp->calculator = psi_calc_div;
687 break;
688 EMPTY_SWITCH_DEFAULT_CASE();
689 }
690 if (!validate_num_exp(data, exp->operand, dargs, func, enm)) {
691 return 0;
692 }
693 }
694 switch (exp->t) {
695 case PSI_T_NAME:
696 if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
697 if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
698 data->error(data, exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
699 exp->u.dvar->name);
700 return 0;
701 }
702 }
703 return 1;
704 case PSI_T_NSNAME:
705 if (!locate_num_exp_constant(exp, data->consts)) {
706 data->error(data, exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
707 exp->u.numb);
708 return 0;
709 }
710 return 1;
711 case PSI_T_NUMBER:
712 case PSI_T_ENUM:
713 return 1;
714 default:
715 return 0;
716 }
717 }
718
719 static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
720 size_t j;
721
722 if (!e->items || !e->items->count) {
723 data->error(data, e->token, PSI_WARNING, "Empty enum '%s'", e->name);
724 return 0;
725 }
726
727 for (j = 0; j < e->items->count; ++j) {
728 decl_enum_item *i = e->items->list[j];
729
730 if (!i->num) {
731 if (j) {
732 i->inc.t = PSI_T_NUMBER;
733 i->inc.u.numb = "1";
734 i->inc.operator = PSI_T_PLUS;
735 i->inc.operand = i->prev->num ?: &i->prev->inc;
736 i->num = &i->inc;
737 } else {
738 i->inc.t = PSI_T_NUMBER;
739 i->inc.u.numb = "0";
740 i->num = &i->inc;
741 }
742 }
743 if (!validate_num_exp(data, i->num, NULL, NULL, e)) {
744 return 0;
745 }
746 }
747
748 return 1;
749 }
750
751 static inline int validate_set_value_handler(set_value *set) {
752 switch (set->func->type) {
753 case PSI_T_TO_BOOL: set->func->handler = psi_to_bool; break;
754 case PSI_T_TO_INT: set->func->handler = psi_to_int; break;
755 case PSI_T_TO_FLOAT: set->func->handler = psi_to_double; break;
756 case PSI_T_TO_STRING: set->func->handler = psi_to_string; break;
757 case PSI_T_TO_ARRAY: set->func->handler = psi_to_array; break;
758 case PSI_T_TO_OBJECT: set->func->handler = psi_to_object; break;
759 case PSI_T_VOID: set->func->handler = psi_to_void; break;
760 case PSI_T_ZVAL: set->func->handler = psi_to_zval; break;
761 case PSI_T_ELLIPSIS:
762 if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) {
763 set->func->handler = psi_to_recursive;
764 set->inner = set->outer.set->inner;
765 break;
766 }
767 /* no break */
768 default:
769 return 0;
770 }
771 return 1;
772 }
773 static inline void decl_var_arg_v(decl_args *args, va_list argp) {
774 int argc;
775 decl_arg **argv;
776
777 memset(args, 0, sizeof(*args));
778
779 while ((argc = va_arg(argp, int))) {
780 argv = va_arg(argp, decl_arg **);
781 while (argc--) {
782 add_decl_arg(args, *argv++);
783 }
784 }
785 }
786 static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg *ref, decl_args *ref_list) {
787 size_t i;
788 decl_type *ref_type;
789 decl_var *set_var = set->vars->vars[0];
790
791 if (!validate_set_value_handler(set)) {
792 data->error(data, set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", set->func->name);
793 return 0;
794 }
795
796 for (i = 0; i < set->vars->count; ++i) {
797 decl_var *svar = set->vars->vars[i];
798 if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) {
799 data->error(data, svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name);
800 return 0;
801 }
802 }
803
804 if (!ref) {
805 ref = set_var->arg;
806 }
807 ref_type = real_decl_type(ref->type);
808
809 if (set->inner && set->inner->count) {
810 int is_to_array = (set->func->type == PSI_T_TO_ARRAY);
811 int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level);
812
813 if (!is_to_array && !is_pointer_to_struct) {
814 data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts only work with "
815 "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name);
816 return 0;
817 }
818 }
819 if (set->num) {
820 if (!validate_num_exp(data, set->num, ref_list, ref, NULL)) {
821 return 0;
822 }
823 }
824
825 if (set->inner && ref_type->type == PSI_T_STRUCT) {
826 /* to_array(struct, to_...) */
827 if (!set->outer.set || set->outer.set->inner->vals != set->inner->vals) {
828 for (i = 0; i < set->inner->count; ++i) {
829 decl_var *sub_var = set->inner->vals[i]->vars->vars[0];
830 decl_arg *sub_ref = locate_struct_member(ref_type->real.strct, sub_var);
831
832 if (sub_ref) {
833 if (!validate_set_value_ex(data, set->inner->vals[i], sub_ref, ref_type->real.strct->args)) {
834 return 0;
835 }
836 }
837 }
838 }
839 } else if (set->inner && set->inner->count == 1) {
840 /* to_array(ptr, to_string(*ptr)) */
841 decl_var *sub_var = set->inner->vals[0]->vars->vars[0];
842 decl_arg *sub_ref = locate_decl_var_arg(sub_var, ref_list, ref);
843
844 if (sub_ref) {
845 if (strcmp(sub_var->name, set_var->name)) {
846 data->error(data, sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
847 return 0;
848 }
849 if (!validate_set_value_ex(data, set->inner->vals[0], sub_ref, ref_list)) {
850 return 0;
851 }
852 }
853 } else if (set->inner && set->inner->count > 1) {
854 data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once");
855 return 0;
856 }
857
858 return 1;
859 }
860 static inline int validate_set_value(PSI_Data *data, set_value *set, ...) {
861 va_list argp;
862 decl_args args = {0};
863 int check;
864
865 va_start(argp, set);
866 decl_var_arg_v(&args, argp);
867 va_end(argp);
868
869 check = validate_set_value_ex(data, set, NULL, &args);
870 if (args.args) {
871 free(args.args);
872 }
873 return check;
874 }
875 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
876 if (decls) {
877 size_t i;
878
879 for (i = 0; i < decls->count; ++i) {
880 if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) {
881 ret->decl = decls->list[i]->func;
882 return decls->list[i];
883 }
884 }
885 }
886
887 return NULL;
888 }
889 static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
890 return_stmt *ret;
891
892 /* we must have exactly one ret stmt delcaring the native func to call */
893 /* and which type cast to apply */
894 if (impl->stmts->ret.count != 1) {
895 if (impl->stmts->ret.count > 1) {
896 data->error(data, impl->stmts->ret.list[1]->token, PSI_WARNING,
897 "Too many `return` statements for implmentation %s;"
898 " found %zu, exactly one is needed",
899 impl->func->name, impl->stmts->ret.count);
900 } else {
901 data->error(data, impl->func->token, PSI_WARNING,
902 "Missing `return` statement for implementation %s",
903 impl->func->name);
904 }
905 return 0;
906 }
907
908 ret = impl->stmts->ret.list[0];
909
910 if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
911 data->error(data, ret->token, PSI_WARNING,
912 "Missing declaration '%s' for `return` statment for implementation %s",
913 ret->set->vars->vars[0]->name, impl->func->name);
914 return 0;
915 }
916
917 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)) {
918 return 0;
919 }
920
921 //impl->decl->impl = impl;
922
923 return 1;
924 }
925
926 static inline impl_arg *locate_impl_var_arg(impl_var *var, impl_args *args) {
927 size_t i;
928
929 for (i = 0; i < args->count; ++i) {
930 impl_arg *iarg = args->args[i];
931
932 if (!strcmp(var->name, iarg->var->name)) {
933 return var->arg = iarg;
934 }
935 }
936
937 return NULL;
938 }
939
940 static inline int validate_let_func(PSI_Data *data, let_func *func, impl *impl) {
941 if (impl->func->args) {
942 if (!locate_impl_var_arg(func->var, impl->func->args)) {
943 data->error(data, func->var->token, PSI_WARNING,
944 "Unknown variable '$%s' of `let` statement"
945 " for cast '%s' of implementation '%s'",
946 func->var->name, func->name, impl->func->name);
947 return 0;
948 }
949 }
950 switch (func->type) {
951 case PSI_T_BOOLVAL: func->handler = psi_let_boolval; break;
952 case PSI_T_INTVAL: func->handler = psi_let_intval; break;
953 case PSI_T_FLOATVAL: func->handler = psi_let_floatval; break;
954 case PSI_T_STRVAL: func->handler = psi_let_strval; break;
955 case PSI_T_STRLEN: func->handler = psi_let_strlen; break;
956 case PSI_T_PATHVAL: func->handler = psi_let_pathval; break;
957 case PSI_T_ARRVAL: func->handler = psi_let_arrval; break;
958 case PSI_T_OBJVAL: func->handler = psi_let_objval; break;
959 case PSI_T_ZVAL: func->handler = psi_let_zval; break;
960 EMPTY_SWITCH_DEFAULT_CASE();
961 }
962 return 1;
963 }
964
965 static inline int validate_let_callback(PSI_Data *data, decl_var *cb_var, let_callback *cb, impl *impl) {
966 size_t i;
967 decl *cb_func;
968 decl_type *cb_type = real_decl_type(cb_var->arg->type);
969
970 if (!validate_let_func(data, cb->func, impl)) {
971 return 0;
972 }
973
974 if (cb_type->type != PSI_T_FUNCTION) {
975 data->error(data, cb_var->token, PSI_WARNING, "Not a function: %s", cb_var->name);
976 return 0;
977 }
978 cb_func = cb_type->real.func;
979 for (i = 0; i < cb->args->count; ++i) {
980 if (!validate_set_value(data, cb->args->vals[i], cb_func->args->count, cb_func->args->args, 0)) {
981 return 0;
982 }
983 }
984
985 if (!validate_decl_nodl(data, cb_func)) {
986 return 0;
987 }
988
989 cb->decl = cb_func;
990
991 return 1;
992 }
993
994 static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
995 size_t i, j;
996 /* we can have multiple let stmts */
997
998 /* check that we have a decl arg for every let stmt */
999 for (i = 0; i < impl->stmts->let.count; ++i) {
1000 let_stmt *let = impl->stmts->let.list[i];
1001 decl_var *let_var;
1002
1003 if (let->val && let->val->kind == PSI_LET_TMP) {
1004 let_var = let->val->data.var;
1005 } else {
1006 let_var = let->var;
1007 }
1008
1009 if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) {
1010 data->error(data, let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
1011 " of implementation '%s'", let_var->name, impl->func->name);
1012 return 0;
1013 }
1014
1015 switch (let->val->kind) {
1016 case PSI_LET_NULL:
1017 break;
1018 case PSI_LET_TMP:
1019 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
1020 /* e.g. let foo = *bar; */
1021 let->var->pointer_level = let->val->data.var->pointer_level;
1022 let->var->arg = init_decl_arg(
1023 init_decl_type(
1024 real_decl_type(let->val->data.var->arg->type)->type,
1025 real_decl_type(let->val->data.var->arg->type)->name),
1026 init_decl_var(
1027 let->var->name,
1028 let->var->pointer_level,
1029 let->var->array_size));
1030 break;
1031 case PSI_LET_NUMEXP:
1032 if (!validate_num_exp(data, let->val->data.num, impl->decl->args, impl->decl->func, NULL)) {
1033 return 0;
1034 }
1035 break;
1036 case PSI_LET_CALLOC:
1037 if (!validate_num_exp(data, let->val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
1038 return 0;
1039 }
1040 if (!validate_num_exp(data, let->val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
1041 return 0;
1042 }
1043 break;
1044 case PSI_LET_CALLBACK:
1045 if (!validate_let_callback(data, let->var, let->val->data.callback, impl)) {
1046 return 0;
1047 }
1048 break;
1049 case PSI_LET_FUNC:
1050 if (!validate_let_func(data, let->val->data.func, impl)) {
1051 return 0;
1052 }
1053 break;
1054 }
1055 }
1056
1057 /* check that we have a let stmt for every decl arg */
1058 if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) {
1059 decl_arg *darg = impl->decl->args->args[i];
1060 int check = 0;
1061
1062 for (j = 0; j < impl->stmts->let.count; ++j) {
1063 let_stmt *let = impl->stmts->let.list[j];
1064
1065 if (!strcmp(let->var->name, darg->var->name)) {
1066 check = 1;
1067 break;
1068 }
1069 }
1070 if (!check) {
1071 data->error(data, impl->func->token, PSI_WARNING,
1072 "Missing `let` statement for arg '%s %.*s%s'"
1073 " of declaration '%s' for implementation '%s'",
1074 darg->type->name, (int) darg->var->pointer_level, "*****",
1075 darg->var->name, impl->decl->func->var->name, impl->func->name);
1076 return 0;
1077 }
1078 }
1079
1080 return 1;
1081 }
1082 static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
1083 size_t i, j, k;
1084 /* we can have any count of set stmts; processing out vars */
1085 /* check that set stmts reference known variables */
1086 for (i = 0; i < impl->stmts->set.count; ++i) {
1087 set_stmt *set = impl->stmts->set.list[i];
1088 int check = 0;
1089
1090 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
1091 impl_arg *iarg = impl->func->args->args[j];
1092
1093 if (!strcmp(set->var->name, iarg->var->name)) {
1094 set->arg = iarg;
1095 check = 1;
1096 break;
1097 }
1098 }
1099 if (!check) {
1100 data->error(data, set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
1101 " of implementation '%s'",
1102 set->var->name, impl->func->name);
1103 return 0;
1104 }
1105
1106 for (j = 0; j < set->val->vars->count; ++j) {
1107 decl_var *set_var = set->val->vars->vars[j];
1108
1109 check = 0;
1110 if (impl->decl->args) {
1111 for (k = 0; k < impl->decl->args->count; ++k) {
1112 decl_arg *set_arg = impl->decl->args->args[k];
1113
1114 if (!strcmp(set_var->name, set_arg->var->name)) {
1115 check = 1;
1116 set_var->arg = set_arg;
1117 if (!validate_set_value(data, set->val, 1, &set_arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
1118 return 0;
1119 }
1120 break;
1121 }
1122 }
1123 }
1124 if (!check) {
1125 for (k = 0; k < impl->stmts->let.count; ++k) {
1126 let_stmt *let = impl->stmts->let.list[k];
1127
1128 /* check temp vars */
1129 if (let->val && let->val->kind == PSI_LET_TMP) {
1130 if (!strcmp(set_var->name, let->var->name)) {
1131 check = 1;
1132 set_var->arg = let->var->arg;
1133 if (!validate_set_value(data, set->val, 1, &set_var->arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
1134 return 0;
1135 }
1136 break;
1137 }
1138 }
1139 }
1140 }
1141
1142 if (!check) {
1143 data->error(data, set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement"
1144 " for variable '$%s' of implementation '%s'",
1145 set_var->name, set->arg->var->name, impl->func->name);
1146 return 0;
1147 }
1148 }
1149 }
1150 return 1;
1151 }
1152 static inline decl *locate_free_decl(decls *decls, free_call *f) {
1153 if (decls) {
1154 size_t i;
1155
1156 for (i = 0; i < decls->count; ++i) {
1157 if (!strcmp(decls->list[i]->func->var->name, f->func)) {
1158 f->decl = decls->list[i];
1159 return decls->list[i];
1160 }
1161 }
1162 }
1163
1164 return NULL;
1165 }
1166 static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
1167 size_t i, j, k, l;
1168 /* we can have any count of free stmts; freeing any out vars */
1169 for (i = 0; i < impl->stmts->fre.count; ++i) {
1170 free_stmt *fre = impl->stmts->fre.list[i];
1171
1172 for (j = 0; j < fre->calls->count; ++j) {
1173 free_call *free_call = fre->calls->list[j];
1174
1175 /* first find the decl of the free func */
1176 if (!locate_free_decl(data->decls, free_call)) {
1177 data->error(data, free_call->token, PSI_WARNING,
1178 "Missing declaration '%s' in `free` statement"
1179 " of implementation '%s'",
1180 free_call->func, impl->func->name);
1181 return 0;
1182 }
1183
1184
1185
1186 /* now check for known vars */
1187 for (l = 0; l < free_call->vars->count; ++l) {
1188 int check = 0;
1189 decl_var *free_var = free_call->vars->vars[l];
1190
1191 if (!strcmp(free_var->name, impl->decl->func->var->name)) {
1192 check = 1;
1193 free_var->arg = impl->decl->func;
1194 } else if (impl->decl->args) {
1195 for (k = 0; k < impl->decl->args->count; ++k) {
1196 decl_arg *free_arg = impl->decl->args->args[k];
1197
1198 if (!strcmp(free_var->name, free_arg->var->name)) {
1199 check = 1;
1200 free_var->arg = free_arg;
1201 break;
1202 }
1203 }
1204 }
1205
1206 if (!check) {
1207 data->error(data, free_var->token, PSI_WARNING,
1208 "Unknown variable '%s' of `free` statement"
1209 " of implementation '%s'",
1210 free_var->name, impl->func->name);
1211 return 0;
1212 }
1213 }
1214 }
1215 }
1216 return 1;
1217 }
1218 static inline int validate_impl_stmts(PSI_Data *data, impl *impl) {
1219 if (!impl->stmts) {
1220 data->error(data, impl->func->token, PSI_WARNING,
1221 "Missing body for implementation %s!",
1222 impl->func->name);
1223 return 0;
1224 }
1225
1226 if (!validate_impl_ret_stmt(data, impl)) {
1227 return 0;
1228 }
1229
1230 if (!validate_impl_let_stmts(data, impl)) {
1231 return 0;
1232 }
1233 if (!validate_impl_set_stmts(data, impl)) {
1234 return 0;
1235 }
1236 if (!validate_impl_free_stmts(data, impl)) {
1237 return 0;
1238 }
1239
1240 return 1;
1241 }
1242
1243 static inline int validate_impl_args(PSI_Data *data, impl *impl) {
1244 int def = 0;
1245 size_t i;
1246
1247 for (i = 0; i < impl->func->args->count; ++i) {
1248 impl_arg *iarg = impl->func->args->args[i];
1249
1250 if (iarg->def) {
1251 def = 1;
1252 } else if (def) {
1253 data->error(data, impl->func->token, PSI_WARNING,
1254 "Non-optional argument %zu '$%s' of implementation '%s'"
1255 " follows optional argument",
1256 i+1, iarg->var->name, impl->func->name);
1257 return 0;
1258 }
1259 }
1260
1261 return 1;
1262 }
1263
1264 static inline int validate_impl(PSI_Data *data, impl *impl) {
1265 if (!validate_impl_args(data, impl)) {
1266 return 0;
1267 }
1268 return validate_impl_stmts(data, impl);
1269 }
1270
1271
1272 int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
1273 {
1274 PSI_Data *D;
1275 void *dlopened = NULL;
1276 size_t i, count = C->count++, check_round, check_count;
1277 decl_typedefs *check_defs = P->defs;
1278 decl_structs *check_structs = P->structs;
1279 decl_unions *check_unions = P->unions;
1280 decl_enums *check_enums = P->enums;
1281 unsigned silent = C->flags & PSI_PARSER_SILENT;
1282
1283 C->data = realloc(C->data, C->count * sizeof(*C->data));
1284 D = PSI_DataExchange(&C->data[count], PSI_DATA(P));
1285
1286 #define REVALIDATE(what) do { \
1287 if (check_round && check_ ##what) { \
1288 free(check_ ##what->list); \
1289 free(check_ ##what); \
1290 } \
1291 check_ ##what = recheck_ ##what; \
1292 } while (0)
1293 #define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
1294 #define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
1295
1296 if (!silent) {
1297 /* no warnings on first round */
1298 C->flags |= PSI_PARSER_SILENT;
1299 }
1300 for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
1301 decl_typedefs *recheck_defs = NULL;
1302 decl_structs *recheck_structs = NULL;
1303 decl_unions *recheck_unions = NULL;
1304 decl_enums *recheck_enums = NULL;
1305
1306 check_count = CHECK_TOTAL;
1307
1308 for (i = 0; i < CHECK_COUNT(defs); ++i) {
1309 if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
1310 C->defs = add_decl_typedef(C->defs, check_defs->list[i]);
1311 } else {
1312 recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]);
1313 }
1314 }
1315 for (i = 0; i < CHECK_COUNT(structs); ++i) {
1316 if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) {
1317 C->structs = add_decl_struct(C->structs, check_structs->list[i]);
1318 } else {
1319 recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
1320 }
1321 }
1322 for (i = 0; i < CHECK_COUNT(unions); ++i) {
1323 if (validate_decl_union(PSI_DATA(C), check_unions->list[i])) {
1324 C->unions = add_decl_union(C->unions, check_unions->list[i]);
1325 } else {
1326 recheck_unions = add_decl_union(recheck_unions, check_unions->list[i]);
1327 }
1328 }
1329 for (i = 0; i < CHECK_COUNT(enums); ++i) {
1330 if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
1331 C->enums = add_decl_enum(C->enums, check_enums->list[i]);
1332 } else {
1333 recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]);
1334 }
1335 }
1336
1337 REVALIDATE(defs);
1338 REVALIDATE(structs);
1339 REVALIDATE(unions);
1340 REVALIDATE(enums);
1341
1342 if (check_round == 0 && !silent) {
1343 C->flags &= ~PSI_PARSER_SILENT;
1344 }
1345 }
1346
1347
1348 if (D->consts) {
1349 for (i = 0; i < D->consts->count; ++i) {
1350 if (validate_constant(PSI_DATA(C), D->consts->list[i])) {
1351 C->consts = add_constant(C->consts, D->consts->list[i]);
1352 }
1353 }
1354 }
1355
1356 if (!validate_lib(D, &dlopened)) {
1357 return 0;
1358 }
1359
1360 add_decl_lib(&C->psi.libs, dlopened);
1361
1362 if (D->decls) {
1363 for (i = 0; i < D->decls->count; ++i) {
1364 if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) {
1365 C->decls = add_decl(C->decls, D->decls->list[i]);
1366 }
1367 }
1368 }
1369 if (D->impls) {
1370 for (i = 0; i < D->impls->count; ++i) {
1371 if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
1372 C->impls = add_impl(C->impls, D->impls->list[i]);
1373 }
1374 }
1375 }
1376
1377 return 1;
1378 }
1379
1380 int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source)
1381 {
1382 size_t i;
1383 int errors = 0;
1384
1385 if (source->defs) for (i = 0; i < source->defs->count; ++i) {
1386 decl_arg *def = source->defs->list[i];
1387
1388 if (validate_decl_typedef(source, def)) {
1389 if (dest) {
1390 dest->defs = add_decl_typedef(dest->defs, def);
1391 }
1392 } else {
1393 ++errors;
1394 }
1395 }
1396
1397 if (source->consts) for (i = 0; i < source->consts->count; ++i) {
1398 constant *constant = source->consts->list[i];
1399
1400 if (validate_constant(source, constant)) {
1401 if (dest) {
1402 dest->consts = add_constant(dest->consts, constant);
1403 }
1404 } else {
1405 ++errors;
1406 }
1407 }
1408
1409 if (source->structs) for (i = 0; i < source->structs->count; ++i) {
1410 decl_struct *dstruct = source->structs->list[i];
1411
1412 if (validate_decl_struct(source, dstruct)) {
1413 if (dest) {
1414 dest->structs = add_decl_struct(dest->structs, dstruct);
1415 }
1416 } else {
1417 ++errors;
1418 }
1419 }
1420
1421 if (source->unions) for (i = 0; i < source->unions->count; ++i) {
1422 decl_union *dunion = source->unions->list[i];
1423
1424 if (validate_decl_union(source, dunion)) {
1425 if (dest) {
1426 dest->unions = add_decl_union(dest->unions, dunion);
1427 }
1428 } else {
1429 ++errors;
1430 }
1431 }
1432
1433 if (source->enums) for (i = 0; i < source->enums->count; ++i) {
1434 decl_enum *denum = source->enums->list[i];
1435
1436 if (validate_decl_enum(source, denum)) {
1437 if (dest) {
1438 dest->enums = add_decl_enum(dest->enums, denum);
1439 }
1440 } else {
1441 ++errors;
1442 }
1443 }
1444
1445 if (source->decls) for (i = 0; i < source->decls->count; ++i) {
1446 decl *decl = source->decls->list[i];
1447
1448 if (validate_decl(source, NULL, decl)) {
1449 if (dest) {
1450 dest->decls = add_decl(dest->decls, decl);
1451 }
1452 } else {
1453 ++errors;
1454 }
1455 }
1456
1457 if (source->impls) for (i = 0; i < source->impls->count; ++i) {
1458 impl *impl = source->impls->list[i];
1459
1460 if (validate_impl(source, impl)) {
1461 if (dest) {
1462 dest->impls = add_impl(dest->impls, impl);
1463 }
1464 } else {
1465 ++errors;
1466 }
1467 }
1468
1469 return errors;
1470 }