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