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