validation and marshaling of structs/unions
[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 #include "context.h"
21
22 static int validate_lib(struct psi_data *data, void **dlopened) {
23 char lib[MAXPATHLEN];
24 const char *ptr = data->psi.file.ln;
25 size_t len;
26
27 if (!ptr) {
28 /* FIXME: assume stdlib */
29 return 1;
30 } else if (!strchr(ptr, '/')) {
31 len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX);
32 if (MAXPATHLEN == len) {
33 data->error(data, NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
34 }
35 lib[len] = 0;
36 ptr = lib;
37 }
38 if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
39 data->error(data, NULL, PSI_WARNING, "Could not open library '%s': %s.",
40 data->psi.file.ln, dlerror());
41 return 0;
42 }
43 return 1;
44 }
45
46 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
47 size_t i;
48 struct psi_std_type *stdtyp;
49
50 if (type->real.def) {
51 return 1;
52 }
53 if (defs) for (i = 0; i < defs->count; ++i) {
54 decl_arg *def = defs->list[i];
55
56 if (def->type->type != type->type && !strcmp(def->var->name, type->name)) {
57 type->real.def = def;
58 return 1;
59 }
60 }
61 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
62 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
63 type->type = stdtyp->type_tag;
64 return 1;
65 }
66 }
67
68 return 0;
69 }
70
71 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
72 size_t i;
73
74 if (type->real.strct) {
75 return 1;
76 }
77 if (structs) for (i = 0; i < structs->count; ++i) {
78 if (!strcmp(structs->list[i]->name, type->name)) {
79 type->real.strct = structs->list[i];
80 return 1;
81 }
82 }
83 return 0;
84 }
85
86 static inline int locate_decl_type_union(decl_unions *unions, decl_type *type) {
87 size_t i;
88
89 if (type->real.unn) {
90 return 1;
91 }
92 if (unions) for (i = 0; i < unions->count; ++i) {
93 if (!strcmp(unions->list[i]->name, type->name)) {
94 type->real.unn = unions->list[i];
95 return 1;
96 }
97 }
98 return 0;
99 }
100
101 static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
102 size_t i;
103
104 if (type->real.enm) {
105 return 1;
106 }
107 if (enums) for (i = 0; i < enums->count; ++i) {
108 if (!strcmp(enums->list[i]->name, type->name)) {
109 type->real.enm = enums->list[i];
110 return 1;
111 }
112 }
113 return 0;
114 }
115
116 static inline int locate_decl_type_decl(decls *decls, decl_type *type) {
117 size_t i;
118
119 if (type->real.func) {
120 return 1;
121 }
122 if (decls) for (i = 0; i < decls->count; ++i) {
123 if (!strcmp(decls->list[i]->func->var->name, type->name)) {
124 type->real.func = decls->list[i];
125 return 1;
126 }
127 }
128
129 return 0;
130 }
131
132 static inline int validate_decl_nodl(struct psi_data *data, decl *decl);
133 static inline int validate_decl_struct(struct psi_data *data, decl_struct *s);
134 static inline int validate_decl_union(struct psi_data *data, decl_union *u);
135 static inline int validate_decl_enum(struct psi_data *data, decl_enum *e);
136
137 static inline int validate_decl_type(struct psi_data *data, decl_type *type, decl_arg *def) {
138 if (weak_decl_type(type)) {
139 if (!locate_decl_type_alias(data->defs, type)) {
140 return 0;
141 }
142 if (type->real.def) {
143 return validate_decl_type(data, type->real.def->type, type->real.def);
144 }
145 return 1;
146 }
147
148 switch (type->type) {
149 case PSI_T_STRUCT:
150 if (!locate_decl_type_struct(data->structs, type)) {
151 return 0;
152 }
153 break;
154 case PSI_T_UNION:
155 if (!locate_decl_type_union(data->unions, type)) {
156 return 0;
157 }
158 break;
159 case PSI_T_ENUM:
160 if (!locate_decl_type_enum(data->enums, type)) {
161 return 0;
162 }
163 break;
164 case PSI_T_FUNCTION:
165 if (!locate_decl_type_decl(data->decls, type)) {
166 return 0;
167 }
168 if (!validate_decl_nodl(data, type->real.func)) {
169 return 0;
170 }
171 break;
172 }
173 return 1;
174 }
175 static inline int validate_decl_typedef(struct psi_data *data, decl_arg *def) {
176 if (!validate_decl_type(data, def->type, def)) {
177 const char *pre;
178
179 switch (def->type->type) {
180 case PSI_T_STRUCT: pre = "struct "; break;
181 case PSI_T_UNION: pre = "union "; break;
182 case PSI_T_ENUM: pre = "enum "; break;
183 default: pre = ""; break;
184 }
185 data->error(data, def->token, PSI_WARNING,
186 "Type '%s' cannot be aliased to %s'%s'",
187 def->var->name, pre, def->type->name);
188 return 0;
189 }
190 if (def->type->type == PSI_T_VOID) {
191 if (def->var->pointer_level) {
192 def->type->type = PSI_T_POINTER;
193 } else {
194 data->error(data, def->token, PSI_WARNING,
195 "Type '%s' cannot be aliased to 'void'",
196 def->type->name);
197 return 0;
198 }
199 }
200 return 1;
201 }
202
203 static inline int validate_constant(struct psi_data *data, constant *c) {
204 /* FIXME */
205 return 1;
206 }
207
208 static inline int validate_decl_arg(struct psi_data *data, decl_arg *arg) {
209 if (!validate_decl_type(data, arg->type, NULL)) {
210 data->error(data, arg->type->token, PSI_WARNING,
211 "Cannot use '%s' as type for '%s'",
212 arg->type->name, arg->var->name);
213 return 0;
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(struct 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(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(struct 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(struct 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(struct 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(struct 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(struct 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_arg(decl_args *args, const char *name) {
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(name, arg->var->name)) {
614 return arg;
615 }
616 }
617
618 return NULL;
619 }
620 static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
621 decl_arg *arg = locate_decl_arg(args, var->name);
622
623 if (arg) {
624 ZEND_ASSERT(!var->arg || var->arg == arg);
625 return var->arg = arg;
626 }
627
628 if (func && !strcmp(var->name, func->var->name)) {
629 return var->arg = func;
630 }
631
632 return NULL;
633 }
634 static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) {
635 if (s->args) {
636 return locate_decl_var_arg(var, s->args, NULL);
637 }
638
639 return NULL;
640 }
641 static inline decl_arg *locate_union_member(decl_union *u, decl_var *var) {
642 if (u->args) {
643 return locate_decl_var_arg(var, u->args, NULL);
644 }
645
646 return NULL;
647 }
648 static inline constant *locate_num_exp_constant(num_exp *exp, constants *consts) {
649 size_t i;
650
651 for (i = 0; i < consts->count; ++i) {
652 constant *cnst = consts->list[i];
653
654 if (!strcmp(cnst->name, exp->u.numb)) {
655 free(exp->u.numb);
656 return exp->u.cnst = cnst;
657 }
658 }
659
660 return NULL;
661 }
662 static inline decl_enum_item *locate_num_exp_enum_item_ex(num_exp *exp, decl_enum *e) {
663 size_t k;
664
665 if (e) for (k = 0; k < e->items->count; ++k) {
666 decl_enum_item *i = e->items->list[k];
667
668 if (!strcmp(i->name, exp->u.dvar->name)) {
669 free_decl_var(exp->u.dvar);
670 exp->t = PSI_T_ENUM;
671 exp->u.enm = i;
672 return i;
673 }
674 }
675 return NULL;
676 }
677 static inline decl_enum_item *locate_num_exp_enum_item(num_exp *exp, decl_enums *enums) {
678 size_t j;
679
680 if (enums) for (j = 0; j < enums->count; ++j) {
681 decl_enum *e = enums->list[j];
682 decl_enum_item *i = locate_num_exp_enum_item_ex(exp, e);
683
684 if (i) {
685 return i;
686 }
687 }
688 return NULL;
689 }
690 static inline int validate_num_exp(struct psi_data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
691 if (exp->operand) {
692 switch (exp->operator) {
693 case PSI_T_PLUS:
694 exp->calculator = psi_calc_add;
695 break;
696 case PSI_T_MINUS:
697 exp->calculator = psi_calc_sub;
698 break;
699 case PSI_T_ASTERISK:
700 exp->calculator = psi_calc_mul;
701 break;
702 case PSI_T_SLASH:
703 exp->calculator = psi_calc_div;
704 break;
705 EMPTY_SWITCH_DEFAULT_CASE();
706 }
707 if (!validate_num_exp(data, exp->operand, dargs, func, enm)) {
708 return 0;
709 }
710 }
711 switch (exp->t) {
712 case PSI_T_NAME:
713 if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
714 if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
715 data->error(data, exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
716 exp->u.dvar->name);
717 return 0;
718 }
719 }
720 return 1;
721 case PSI_T_NSNAME:
722 if (!locate_num_exp_constant(exp, data->consts)) {
723 data->error(data, exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
724 exp->u.numb);
725 return 0;
726 }
727 return 1;
728 case PSI_T_NUMBER:
729 case PSI_T_ENUM:
730 return 1;
731 default:
732 return 0;
733 }
734 }
735
736 static inline int validate_decl_enum(struct psi_data *data, decl_enum *e) {
737 size_t j;
738
739 if (!e->items || !e->items->count) {
740 data->error(data, e->token, PSI_WARNING, "Empty enum '%s'", e->name);
741 return 0;
742 }
743
744 for (j = 0; j < e->items->count; ++j) {
745 decl_enum_item *i = e->items->list[j];
746
747 if (!i->num) {
748 if (j) {
749 i->inc.t = PSI_T_NUMBER;
750 i->inc.u.numb = "1";
751 i->inc.operator = PSI_T_PLUS;
752 i->inc.operand = i->prev->num ?: &i->prev->inc;
753 i->num = &i->inc;
754 } else {
755 i->inc.t = PSI_T_NUMBER;
756 i->inc.u.numb = "0";
757 i->num = &i->inc;
758 }
759 }
760 if (!validate_num_exp(data, i->num, NULL, NULL, e)) {
761 return 0;
762 }
763 }
764
765 return 1;
766 }
767
768 static inline int validate_set_value_handler(set_value *set) {
769 switch (set->func->type) {
770 case PSI_T_TO_BOOL: set->func->handler = psi_to_bool; break;
771 case PSI_T_TO_INT: set->func->handler = psi_to_int; break;
772 case PSI_T_TO_FLOAT: set->func->handler = psi_to_double; break;
773 case PSI_T_TO_STRING: set->func->handler = psi_to_string; break;
774 case PSI_T_TO_ARRAY: set->func->handler = psi_to_array; break;
775 case PSI_T_TO_OBJECT: set->func->handler = psi_to_object; break;
776 case PSI_T_VOID: set->func->handler = psi_to_void; break;
777 case PSI_T_ZVAL: set->func->handler = psi_to_zval; break;
778 case PSI_T_ELLIPSIS:
779 if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) {
780 set->func->handler = psi_to_recursive;
781 set->inner = set->outer.set->inner;
782 break;
783 }
784 /* no break */
785 default:
786 return 0;
787 }
788 return 1;
789 }
790 static inline void decl_var_arg_v(decl_args *args, va_list argp) {
791 int argc;
792 decl_arg **argv;
793
794 memset(args, 0, sizeof(*args));
795
796 while ((argc = va_arg(argp, int))) {
797 argv = va_arg(argp, decl_arg **);
798 while (argc--) {
799 add_decl_arg(args, *argv++);
800 }
801 }
802 }
803 static inline int validate_set_value_ex(struct psi_data *data, set_value *set, decl_arg *ref, decl_args *ref_list) {
804 size_t i;
805 decl_type *ref_type;
806 decl_var *set_var = set->vars->vars[0];
807
808 if (!validate_set_value_handler(set)) {
809 data->error(data, set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", set->func->name);
810 return 0;
811 }
812
813 for (i = 0; i < set->vars->count; ++i) {
814 decl_var *svar = set->vars->vars[i];
815 if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) {
816 data->error(data, svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name);
817 return 0;
818 }
819 }
820
821 if (!ref) {
822 ref = set_var->arg;
823 }
824 ref_type = real_decl_type(ref->type);
825
826 if (set->inner && set->inner->count) {
827 int is_to_array = (set->func->type == PSI_T_TO_ARRAY);
828 int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level);
829
830 if (!is_to_array && !is_pointer_to_struct) {
831 data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts only work with "
832 "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name);
833 return 0;
834 }
835 }
836 if (set->num) {
837 if (!validate_num_exp(data, set->num, ref_list, ref, NULL)) {
838 return 0;
839 }
840 }
841
842 if (set->inner && (ref_type->type == PSI_T_STRUCT || ref_type->type == PSI_T_UNION)) {
843 /* to_array(struct, to_...) */
844 if (!set->outer.set || set->outer.set->inner->vals != set->inner->vals) {
845 for (i = 0; i < set->inner->count; ++i) {
846 decl_var *sub_var = set->inner->vals[i]->vars->vars[0];
847 decl_arg *sub_ref;
848
849 switch (ref_type->type) {
850 case PSI_T_STRUCT:
851 sub_ref = locate_struct_member(ref_type->real.strct, sub_var);
852 break;
853 case PSI_T_UNION:
854 sub_ref = locate_union_member(ref_type->real.unn, sub_var);
855 break;
856 }
857
858 if (sub_ref) {
859 if (!validate_set_value_ex(data, set->inner->vals[i], sub_ref, ref_type->real.strct->args)) {
860 return 0;
861 }
862 }
863 }
864 }
865 } else if (set->inner && set->inner->count == 1) {
866 /* to_array(ptr, to_string(*ptr)) */
867 decl_var *sub_var = set->inner->vals[0]->vars->vars[0];
868 decl_arg *sub_ref = locate_decl_var_arg(sub_var, ref_list, ref);
869
870 if (sub_ref) {
871 if (strcmp(sub_var->name, set_var->name)) {
872 data->error(data, sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
873 return 0;
874 }
875 if (!validate_set_value_ex(data, set->inner->vals[0], sub_ref, ref_list)) {
876 return 0;
877 }
878 }
879 } else if (set->inner && set->inner->count > 1) {
880 data->error(data, set->func->token, E_WARNING,
881 "Inner `set` statement casts on pointers may only occur once, "
882 "unless the outer type is a scruct or union, got '%s%.*s'",
883 ref_type->name, PSI_PRINT_POINTER_LEVEL(ref->var->pointer_level));
884 return 0;
885 }
886
887 return 1;
888 }
889 static inline int validate_set_value(struct psi_data *data, set_value *set, ...) {
890 va_list argp;
891 decl_args args = {0};
892 int check;
893
894 va_start(argp, set);
895 decl_var_arg_v(&args, argp);
896 va_end(argp);
897
898 check = validate_set_value_ex(data, set, NULL, &args);
899 if (args.args) {
900 free(args.args);
901 }
902 return check;
903 }
904 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
905 if (decls) {
906 size_t i;
907
908 for (i = 0; i < decls->count; ++i) {
909 if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) {
910 ret->decl = decls->list[i]->func;
911 return decls->list[i];
912 }
913 }
914 }
915
916 return NULL;
917 }
918 static inline int validate_impl_ret_stmt(struct psi_data *data, impl *impl) {
919 return_stmt *ret;
920
921 /* we must have exactly one ret stmt delcaring the native func to call */
922 /* and which type cast to apply */
923 if (impl->stmts->ret.count != 1) {
924 if (impl->stmts->ret.count > 1) {
925 data->error(data, impl->stmts->ret.list[1]->token, PSI_WARNING,
926 "Too many `return` statements for implmentation %s;"
927 " found %zu, exactly one is needed",
928 impl->func->name, impl->stmts->ret.count);
929 } else {
930 data->error(data, impl->func->token, PSI_WARNING,
931 "Missing `return` statement for implementation %s",
932 impl->func->name);
933 }
934 return 0;
935 }
936
937 ret = impl->stmts->ret.list[0];
938
939 if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
940 data->error(data, ret->token, PSI_WARNING,
941 "Missing declaration '%s' for `return` statment for implementation %s",
942 ret->set->vars->vars[0]->name, impl->func->name);
943 return 0;
944 }
945
946 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)) {
947 return 0;
948 }
949
950 //impl->decl->impl = impl;
951
952 return 1;
953 }
954
955 static inline impl_arg *locate_impl_var_arg(impl_var *var, impl_args *args) {
956 size_t i;
957
958 for (i = 0; i < args->count; ++i) {
959 impl_arg *iarg = args->args[i];
960
961 if (!strcmp(var->name, iarg->var->name)) {
962 return var->arg = iarg;
963 }
964 }
965
966 return NULL;
967 }
968
969 static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var *let_var, impl *impl);
970
971 static inline const char *locate_let_val_varname(let_val *val) {
972 if (val) {
973 switch (val->kind) {
974 case PSI_LET_CALLBACK:
975 return &val->data.callback->func->var->name[1];
976 case PSI_LET_FUNC:
977 return &val->data.func->var->name[1];
978 default:
979 break;
980 }
981 }
982 return NULL;
983 }
984
985 static inline int validate_let_func(struct psi_data *data, let_func *func, decl_var *let_var, impl *impl) {
986 if (func->outer) {
987
988 }
989 if (impl->func->args) {
990 locate_impl_var_arg(func->var, impl->func->args);
991 }
992 if (!func->var->arg && !func->ref) {
993 data->error(data, func->var->token, PSI_WARNING,
994 "Unknown variable '%s%s' of `let` statement"
995 " for cast '%s' of implementation '%s'",
996 *func->var->name == '$' ? "" : "$",
997 func->var->name, func->name, impl->func->name);
998 return 0;
999 }
1000 switch (func->type) {
1001 case PSI_T_BOOLVAL: func->handler = psi_let_boolval; break;
1002 case PSI_T_INTVAL: func->handler = psi_let_intval; break;
1003 case PSI_T_FLOATVAL: func->handler = psi_let_floatval; break;
1004 case PSI_T_STRVAL: func->handler = psi_let_strval; break;
1005 case PSI_T_STRLEN: func->handler = psi_let_strlen; break;
1006 case PSI_T_PATHVAL: func->handler = psi_let_pathval; break;
1007 case PSI_T_ARRVAL: func->handler = psi_let_arrval; break;
1008 case PSI_T_OBJVAL: func->handler = psi_let_objval; break;
1009 case PSI_T_ZVAL: func->handler = psi_let_zval; break;
1010 case PSI_T_VOID: func->handler = psi_let_void; break;
1011 EMPTY_SWITCH_DEFAULT_CASE();
1012 }
1013
1014 if (func->inner) {
1015 size_t i;
1016 decl_type *var_typ = real_decl_type(let_var->arg->type);
1017 decl_args *sub_args;
1018
1019 switch (var_typ->type) {
1020 case PSI_T_STRUCT:
1021 sub_args = var_typ->real.strct->args;
1022 break;
1023 case PSI_T_UNION:
1024 sub_args = var_typ->real.unn->args;
1025 break;
1026 default:
1027 data->error(data, let_var->token, PSI_WARNING,
1028 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
1029 real_decl_type(let_var->arg->type)->name, let_var->name);
1030 return 0;
1031 }
1032
1033 for (i = 0; i < func->inner->count; ++i) {
1034 let_val *inner = func->inner->vals[i];
1035 let_val *outer = func->outer;
1036 const char *name = locate_let_val_varname(inner);
1037 decl_arg *sub_arg;
1038
1039 if (name) {
1040 sub_arg = locate_decl_arg(sub_args, name);
1041 }
1042 if (!name || !sub_arg) {
1043 data->error(data, let_var->token, PSI_WARNING,
1044 "Unknown variable '%s' of '%s'",
1045 name,
1046 var_typ->real.strct->name);
1047 return 0;
1048 }
1049 if (!validate_let_val(data, inner, sub_arg->var, impl)) {
1050 return 0;
1051 }
1052 }
1053 }
1054 return 1;
1055 }
1056
1057 static inline int validate_let_callback(struct psi_data *data, decl_var *cb_var, let_callback *cb, impl *impl) {
1058 size_t i;
1059 decl *cb_func;
1060 decl_type *cb_type = real_decl_type(cb_var->arg->type);
1061
1062 if (!validate_let_func(data, cb->func, cb_var, impl)) {
1063 return 0;
1064 }
1065
1066 if (cb_type->type != PSI_T_FUNCTION) {
1067 data->error(data, cb_var->token, PSI_WARNING, "Not a function: %s", cb_var->name);
1068 return 0;
1069 }
1070 cb_func = cb_type->real.func;
1071 for (i = 0; i < cb->args->count; ++i) {
1072 if (!validate_set_value(data, cb->args->vals[i], cb_func->args->count, cb_func->args->args, 0)) {
1073 return 0;
1074 }
1075 }
1076
1077 if (!validate_decl_nodl(data, cb_func)) {
1078 return 0;
1079 }
1080
1081 cb->decl = cb_func;
1082
1083 return 1;
1084 }
1085
1086 static inline int validate_let_val(struct psi_data *data, let_val *val, decl_var *let_var, impl *impl) {
1087
1088 switch (val->kind) {
1089 case PSI_LET_NULL:
1090 break;
1091 case PSI_LET_TMP:
1092 if (!let_var) {
1093 data->error(data, NULL, PSI_WARNING,
1094 "Ivalid let statement value of implementation '%s'",
1095 impl->func->name);
1096 return 0;
1097 }
1098 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
1099 /* e.g. let foo = *bar; */
1100 let_var->pointer_level = val->data.var->pointer_level;
1101 let_var->arg = init_decl_arg(
1102 init_decl_type(
1103 real_decl_type(val->data.var->arg->type)->type,
1104 real_decl_type(val->data.var->arg->type)->name),
1105 init_decl_var(
1106 let_var->name,
1107 let_var->pointer_level,
1108 let_var->array_size));
1109 break;
1110 case PSI_LET_NUMEXP:
1111 if (!validate_num_exp(data, val->data.num, impl->decl->args, impl->decl->func, NULL)) {
1112 return 0;
1113 }
1114 break;
1115 case PSI_LET_CALLOC:
1116 if (!validate_num_exp(data, val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
1117 return 0;
1118 }
1119 if (!validate_num_exp(data, val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
1120 return 0;
1121 }
1122 break;
1123 case PSI_LET_CALLBACK:
1124 if (!let_var) {
1125 data->error(data, NULL, PSI_WARNING,
1126 "Ivalid let statement value of implementation '%s'",
1127 impl->func->name);
1128 return 0;
1129 }
1130 if (val->data.callback->func->inner) {
1131 size_t i;
1132 decl_type *var_typ = real_decl_type(let_var->arg->type);
1133 decl_args *sub_args;
1134
1135 switch (var_typ->type) {
1136 case PSI_T_STRUCT:
1137 sub_args = var_typ->real.strct->args;
1138 break;
1139 case PSI_T_UNION:
1140 sub_args = var_typ->real.unn->args;
1141 break;
1142 default:
1143 data->error(data, let_var->token, PSI_WARNING,
1144 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
1145 real_decl_type(let_var->arg->type)->name, let_var->name);
1146 return 0;
1147 }
1148 for (i = 0; i < val->data.callback->func->inner->count; ++i) {
1149 let_val *inner = val->data.callback->func->inner->vals[i];
1150 switch (inner->kind) {
1151 case PSI_LET_FUNC:
1152 inner->data.func->outer = val;
1153 inner->data.func->ref = locate_decl_arg(sub_args,
1154 &inner->data.func->var->name[1]);
1155 break;
1156
1157 break;
1158 case PSI_LET_CALLBACK:
1159 inner->data.callback->func->outer = val;
1160 inner->data.callback->func->ref = locate_decl_arg(sub_args,
1161 &inner->data.callback->func->var->name[1]);
1162 break;
1163 }
1164 }
1165 }
1166 if (!validate_let_callback(data, let_var, val->data.callback, impl)) {
1167 return 0;
1168 }
1169 break;
1170 case PSI_LET_FUNC:
1171 if (val->data.func->inner) {
1172 size_t i;
1173 decl_type *var_typ = real_decl_type(let_var->arg->type);
1174 decl_args *sub_args;
1175
1176 switch (var_typ->type) {
1177 case PSI_T_STRUCT:
1178 sub_args = var_typ->real.strct->args;
1179 break;
1180 case PSI_T_UNION:
1181 sub_args = var_typ->real.unn->args;
1182 break;
1183 default:
1184 data->error(data, let_var->token, PSI_WARNING,
1185 "Inner let statement's values must refer to a structure type, got '%s' for '%s'",
1186 real_decl_type(let_var->arg->type)->name, let_var->name);
1187 return 0;
1188 }
1189 for (i = 0; i < val->data.func->inner->count; ++i) {
1190 let_val *inner = val->data.func->inner->vals[i];
1191 switch (inner->kind) {
1192 case PSI_LET_FUNC:
1193 inner->data.func->outer = val;
1194 inner->data.func->ref = locate_decl_arg(sub_args,
1195 &inner->data.func->var->name[1]);
1196 break;
1197 case PSI_LET_CALLBACK:
1198 inner->data.callback->func->outer = val;
1199 inner->data.callback->func->ref = locate_decl_arg(sub_args,
1200 &inner->data.callback->func->var->name[1]);
1201 break;
1202 }
1203 }
1204 }
1205
1206 val->data.func->var;
1207
1208 if (!validate_let_func(data, val->data.func, let_var, impl)) {
1209 return 0;
1210 }
1211 break;
1212 }
1213
1214 return 1;
1215 }
1216
1217 static inline int validate_impl_let_stmts(struct psi_data *data, impl *impl) {
1218 size_t i, j;
1219 /* we can have multiple let stmts */
1220
1221 /* check that we have a decl arg and impl arg for every let stmt */
1222 for (i = 0; i < impl->stmts->let.count; ++i) {
1223 let_stmt *let = impl->stmts->let.list[i];
1224 decl_var *let_var;
1225 impl_var *let_ivar = NULL;
1226
1227 if (let->val && let->val->kind == PSI_LET_TMP) {
1228 let_var = let->val->data.var;
1229 } else {
1230 let_var = let->var;
1231 }
1232
1233 if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) {
1234 data->error(data, let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
1235 " of implementation '%s'", let_var->name, impl->func->name);
1236 return 0;
1237 }
1238 switch (let->val->kind) {
1239 case PSI_LET_CALLBACK:
1240 let_ivar = let->val->data.callback->func->var;
1241 break;
1242 case PSI_LET_FUNC:
1243 let_ivar = let->val->data.func->var;
1244 break;
1245 default:
1246 break;
1247 }
1248 if (let_ivar && !locate_impl_var_arg(let_ivar, impl->func->args)) {
1249 data->error(data, let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
1250 " of implementation '%s'", let_ivar->name, impl->func->name);
1251 return 0;
1252 }
1253
1254 if (!validate_let_val(data, let->val, let->var, impl)) {
1255 return 0;
1256 }
1257 }
1258 /* check that we have a let stmt for every decl arg */
1259 if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) {
1260 decl_arg *darg = impl->decl->args->args[i];
1261 int check = 0;
1262
1263 for (j = 0; j < impl->stmts->let.count; ++j) {
1264 let_stmt *let = impl->stmts->let.list[j];
1265
1266 if (!strcmp(let->var->name, darg->var->name)) {
1267 check = 1;
1268 break;
1269 }
1270 }
1271 if (!check) {
1272 data->error(data, impl->func->token, PSI_WARNING,
1273 "Missing `let` statement for arg '%s %.*s%s'"
1274 " of declaration '%s' for implementation '%s'",
1275 darg->type->name, (int) darg->var->pointer_level, "*****",
1276 darg->var->name, impl->decl->func->var->name, impl->func->name);
1277 return 0;
1278 }
1279 }
1280
1281 return 1;
1282 }
1283 static inline int validate_impl_set_stmts(struct psi_data *data, impl *impl) {
1284 size_t i, j, k;
1285 /* we can have any count of set stmts; processing out vars */
1286 /* check that set stmts reference known variables */
1287 for (i = 0; i < impl->stmts->set.count; ++i) {
1288 set_stmt *set = impl->stmts->set.list[i];
1289 int check = 0;
1290
1291 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
1292 impl_arg *iarg = impl->func->args->args[j];
1293
1294 if (!strcmp(set->var->name, iarg->var->name)) {
1295 set->arg = iarg;
1296 check = 1;
1297 break;
1298 }
1299 }
1300 if (!check) {
1301 data->error(data, set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
1302 " of implementation '%s'",
1303 set->var->name, impl->func->name);
1304 return 0;
1305 }
1306
1307 for (j = 0; j < set->val->vars->count; ++j) {
1308 decl_var *set_var = set->val->vars->vars[j];
1309
1310 check = 0;
1311 if (impl->decl->args) {
1312 for (k = 0; k < impl->decl->args->count; ++k) {
1313 decl_arg *set_arg = impl->decl->args->args[k];
1314
1315 if (!strcmp(set_var->name, set_arg->var->name)) {
1316 check = 1;
1317 set_var->arg = set_arg;
1318 if (!validate_set_value(data, set->val, 1, &set_arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
1319 return 0;
1320 }
1321 break;
1322 }
1323 }
1324 }
1325 if (!check) {
1326 for (k = 0; k < impl->stmts->let.count; ++k) {
1327 let_stmt *let = impl->stmts->let.list[k];
1328
1329 /* check temp vars */
1330 if (let->val && let->val->kind == PSI_LET_TMP) {
1331 if (!strcmp(set_var->name, let->var->name)) {
1332 check = 1;
1333 set_var->arg = let->var->arg;
1334 if (!validate_set_value(data, set->val, 1, &set_var->arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
1335 return 0;
1336 }
1337 break;
1338 }
1339 }
1340 }
1341 }
1342
1343 if (!check) {
1344 data->error(data, set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement"
1345 " for variable '$%s' of implementation '%s'",
1346 set_var->name, set->arg->var->name, impl->func->name);
1347 return 0;
1348 }
1349 }
1350 }
1351 return 1;
1352 }
1353 static inline decl *locate_free_decl(decls *decls, free_call *f) {
1354 if (decls) {
1355 size_t i;
1356
1357 for (i = 0; i < decls->count; ++i) {
1358 if (!strcmp(decls->list[i]->func->var->name, f->func)) {
1359 f->decl = decls->list[i];
1360 return decls->list[i];
1361 }
1362 }
1363 }
1364
1365 return NULL;
1366 }
1367 static inline int validate_impl_free_stmts(struct psi_data *data, impl *impl) {
1368 size_t i, j, k, l;
1369 /* we can have any count of free stmts; freeing any out vars */
1370 for (i = 0; i < impl->stmts->fre.count; ++i) {
1371 free_stmt *fre = impl->stmts->fre.list[i];
1372
1373 for (j = 0; j < fre->calls->count; ++j) {
1374 free_call *free_call = fre->calls->list[j];
1375
1376 /* first find the decl of the free func */
1377 if (!locate_free_decl(data->decls, free_call)) {
1378 data->error(data, free_call->token, PSI_WARNING,
1379 "Missing declaration '%s' in `free` statement"
1380 " of implementation '%s'",
1381 free_call->func, impl->func->name);
1382 return 0;
1383 }
1384
1385
1386
1387 /* now check for known vars */
1388 for (l = 0; l < free_call->vars->count; ++l) {
1389 int check = 0;
1390 decl_var *free_var = free_call->vars->vars[l];
1391
1392 if (!strcmp(free_var->name, impl->decl->func->var->name)) {
1393 check = 1;
1394 free_var->arg = impl->decl->func;
1395 } else if (impl->decl->args) {
1396 for (k = 0; k < impl->decl->args->count; ++k) {
1397 decl_arg *free_arg = impl->decl->args->args[k];
1398
1399 if (!strcmp(free_var->name, free_arg->var->name)) {
1400 check = 1;
1401 free_var->arg = free_arg;
1402 break;
1403 }
1404 }
1405 }
1406
1407 if (!check) {
1408 data->error(data, free_var->token, PSI_WARNING,
1409 "Unknown variable '%s' of `free` statement"
1410 " of implementation '%s'",
1411 free_var->name, impl->func->name);
1412 return 0;
1413 }
1414 }
1415 }
1416 }
1417 return 1;
1418 }
1419 static inline int validate_impl_stmts(struct psi_data *data, impl *impl) {
1420 if (!impl->stmts) {
1421 data->error(data, impl->func->token, PSI_WARNING,
1422 "Missing body for implementation %s!",
1423 impl->func->name);
1424 return 0;
1425 }
1426
1427 if (!validate_impl_ret_stmt(data, impl)) {
1428 return 0;
1429 }
1430
1431 if (!validate_impl_let_stmts(data, impl)) {
1432 return 0;
1433 }
1434 if (!validate_impl_set_stmts(data, impl)) {
1435 return 0;
1436 }
1437 if (!validate_impl_free_stmts(data, impl)) {
1438 return 0;
1439 }
1440
1441 return 1;
1442 }
1443
1444 static inline int validate_impl_args(struct psi_data *data, impl *impl) {
1445 int def = 0;
1446 size_t i;
1447
1448 for (i = 0; i < impl->func->args->count; ++i) {
1449 impl_arg *iarg = impl->func->args->args[i];
1450
1451 if (iarg->def) {
1452 def = 1;
1453 } else if (def) {
1454 data->error(data, impl->func->token, PSI_WARNING,
1455 "Non-optional argument %zu '$%s' of implementation '%s'"
1456 " follows optional argument",
1457 i+1, iarg->var->name, impl->func->name);
1458 return 0;
1459 }
1460 }
1461
1462 return 1;
1463 }
1464
1465 static inline int validate_impl(struct psi_data *data, impl *impl) {
1466 if (!validate_impl_args(data, impl)) {
1467 return 0;
1468 }
1469 return validate_impl_stmts(data, impl);
1470 }
1471
1472
1473 int psi_context_validate(struct psi_context *C, struct psi_parser *P)
1474 {
1475 struct psi_data *D;
1476 void *dlopened = NULL;
1477 size_t i, count = C->count++, check_round, check_count;
1478 decl_typedefs *check_defs = P->defs;
1479 decl_structs *check_structs = P->structs;
1480 decl_unions *check_unions = P->unions;
1481 decl_enums *check_enums = P->enums;
1482 unsigned flags = C->flags;
1483
1484 C->data = realloc(C->data, C->count * sizeof(*C->data));
1485 D = psi_data_exchange(&C->data[count], PSI_DATA(P));
1486
1487 #define REVALIDATE(what) do { \
1488 if (check_round && check_ ##what) { \
1489 free(check_ ##what->list); \
1490 free(check_ ##what); \
1491 } \
1492 check_ ##what = recheck_ ##what; \
1493 } while (0)
1494 #define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
1495 #define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
1496
1497 if (!(flags & PSI_PARSER_SILENT)) {
1498 /* no warnings on first round */
1499 C->flags |= PSI_PARSER_SILENT;
1500 }
1501 for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
1502 decl_typedefs *recheck_defs = NULL;
1503 decl_structs *recheck_structs = NULL;
1504 decl_unions *recheck_unions = NULL;
1505 decl_enums *recheck_enums = NULL;
1506
1507 check_count = CHECK_TOTAL;
1508
1509 for (i = 0; i < CHECK_COUNT(defs); ++i) {
1510 if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
1511 C->defs = add_decl_typedef(C->defs, check_defs->list[i]);
1512 } else {
1513 recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]);
1514 }
1515 }
1516 for (i = 0; i < CHECK_COUNT(structs); ++i) {
1517 if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) {
1518 C->structs = add_decl_struct(C->structs, check_structs->list[i]);
1519 } else {
1520 recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
1521 }
1522 }
1523 for (i = 0; i < CHECK_COUNT(unions); ++i) {
1524 if (validate_decl_union(PSI_DATA(C), check_unions->list[i])) {
1525 C->unions = add_decl_union(C->unions, check_unions->list[i]);
1526 } else {
1527 recheck_unions = add_decl_union(recheck_unions, check_unions->list[i]);
1528 }
1529 }
1530 for (i = 0; i < CHECK_COUNT(enums); ++i) {
1531 if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
1532 C->enums = add_decl_enum(C->enums, check_enums->list[i]);
1533 } else {
1534 recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]);
1535 }
1536 }
1537
1538 REVALIDATE(defs);
1539 REVALIDATE(structs);
1540 REVALIDATE(unions);
1541 REVALIDATE(enums);
1542
1543 if (check_round == 0 && !(flags & PSI_PARSER_SILENT)) {
1544 C->flags ^= PSI_PARSER_SILENT;
1545 }
1546 }
1547
1548 C->flags = flags;
1549
1550 if (D->consts) {
1551 for (i = 0; i < D->consts->count; ++i) {
1552 if (validate_constant(PSI_DATA(C), D->consts->list[i])) {
1553 C->consts = add_constant(C->consts, D->consts->list[i]);
1554 }
1555 }
1556 }
1557
1558 if (!validate_lib(D, &dlopened)) {
1559 return 0;
1560 }
1561
1562 add_decl_lib(&C->psi.libs, dlopened);
1563
1564 if (D->decls) {
1565 for (i = 0; i < D->decls->count; ++i) {
1566 if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) {
1567 C->decls = add_decl(C->decls, D->decls->list[i]);
1568 }
1569 }
1570 }
1571 if (D->impls) {
1572 for (i = 0; i < D->impls->count; ++i) {
1573 if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
1574 C->impls = add_impl(C->impls, D->impls->list[i]);
1575 }
1576 }
1577 }
1578
1579 return 1;
1580 }
1581
1582 int psi_context_validate_data(struct psi_data *dest, struct psi_data *source)
1583 {
1584 size_t i;
1585 int errors = 0;
1586
1587 if (source->defs) for (i = 0; i < source->defs->count; ++i) {
1588 decl_arg *def = source->defs->list[i];
1589
1590 if (validate_decl_typedef(source, def)) {
1591 if (dest) {
1592 dest->defs = add_decl_typedef(dest->defs, def);
1593 }
1594 } else {
1595 ++errors;
1596 }
1597 }
1598
1599 if (source->consts) for (i = 0; i < source->consts->count; ++i) {
1600 constant *constant = source->consts->list[i];
1601
1602 if (validate_constant(source, constant)) {
1603 if (dest) {
1604 dest->consts = add_constant(dest->consts, constant);
1605 }
1606 } else {
1607 ++errors;
1608 }
1609 }
1610
1611 if (source->structs) for (i = 0; i < source->structs->count; ++i) {
1612 decl_struct *dstruct = source->structs->list[i];
1613
1614 if (validate_decl_struct(source, dstruct)) {
1615 if (dest) {
1616 dest->structs = add_decl_struct(dest->structs, dstruct);
1617 }
1618 } else {
1619 ++errors;
1620 }
1621 }
1622
1623 if (source->unions) for (i = 0; i < source->unions->count; ++i) {
1624 decl_union *dunion = source->unions->list[i];
1625
1626 if (validate_decl_union(source, dunion)) {
1627 if (dest) {
1628 dest->unions = add_decl_union(dest->unions, dunion);
1629 }
1630 } else {
1631 ++errors;
1632 }
1633 }
1634
1635 if (source->enums) for (i = 0; i < source->enums->count; ++i) {
1636 decl_enum *denum = source->enums->list[i];
1637
1638 if (validate_decl_enum(source, denum)) {
1639 if (dest) {
1640 dest->enums = add_decl_enum(dest->enums, denum);
1641 }
1642 } else {
1643 ++errors;
1644 }
1645 }
1646
1647 if (source->decls) for (i = 0; i < source->decls->count; ++i) {
1648 decl *decl = source->decls->list[i];
1649
1650 if (validate_decl(source, NULL, decl)) {
1651 if (dest) {
1652 dest->decls = add_decl(dest->decls, decl);
1653 }
1654 } else {
1655 ++errors;
1656 }
1657 }
1658
1659 if (source->impls) for (i = 0; i < source->impls->count; ++i) {
1660 impl *impl = source->impls->list[i];
1661
1662 if (validate_impl(source, impl)) {
1663 if (dest) {
1664 dest->impls = add_impl(dest->impls, impl);
1665 }
1666 } else {
1667 ++errors;
1668 }
1669 }
1670
1671 return errors;
1672 }