7 #include "php_psi_stdinc.h"
11 # define NAMLEN(dirent) strlen ((dirent)->d_name)
13 # define dirent direct
14 # define NAMLEN(dirent) ((dirent)->d_namlen)
15 # ifdef HAVE_SYS_NDIR_H
16 # include <sys/ndir.h>
18 # ifdef HAVE_SYS_DIR_H
26 #include <sys/param.h>
31 #include "php_scandir.h"
37 #include "php_psi_stdtypes.h"
38 #include "php_psi_types.h"
39 #include "php_psi_consts.h"
40 #include "php_psi_macros.h"
41 #include "php_psi_redirs.h"
42 #include "php_psi_decls.h"
43 #include "php_psi_va_decls.h"
44 #include "php_psi_structs.h"
46 static int validate_lib(PSI_Data
*data
, void **dlopened
) {
48 const char *ptr
= data
->psi
.file
.ln
;
52 /* FIXME: assume stdlib */
54 } else if (!strchr(ptr
, '/')) {
55 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.%s", ptr
, PHP_PSI_SHLIB_SUFFIX
);
56 if (MAXPATHLEN
== len
) {
57 data
->error(NULL
, PSI_WARNING
, "Library name too long: '%s'", ptr
);
62 if (!(*dlopened
= dlopen(ptr
, RTLD_LAZY
|RTLD_LOCAL
))) {
63 data
->error(NULL
, PSI_WARNING
, "Could not open library '%s': %s.",
64 data
->psi
.file
.ln
, dlerror());
70 static inline int locate_decl_type_alias(decl_typedefs
*defs
, decl_type
*type
) {
72 struct psi_predef_type
*stdtyp
;
77 for (i
= 0; i
< defs
->count
; ++i
) {
78 decl_typedef
*def
= defs
->list
[i
];
80 if (def
->type
->type
!= type
->type
&& !strcmp(def
->alias
, type
->name
)) {
81 type
->real
= def
->type
;
85 for (stdtyp
= &psi_std_types
[0]; stdtyp
->type_tag
; ++stdtyp
) {
86 if (!strcmp(type
->name
, stdtyp
->alias
?: stdtyp
->type_name
)) {
87 type
->type
= stdtyp
->type_tag
;
94 static inline int locate_decl_type_struct(decl_structs
*structs
, decl_type
*type
) {
100 for (i
= 0; i
< structs
->count
; ++i
) {
101 if (!strcmp(structs
->list
[i
]->name
, type
->name
)) {
102 type
->strct
= structs
->list
[i
];
109 static inline int validate_decl_type(PSI_Data
*data
, decl_type
*type
) {
110 switch (type
->type
) {
116 if (!data
->defs
|| !locate_decl_type_alias(data
->defs
, type
)) {
120 return validate_decl_type(data
, type
->real
);
124 if (!data
->structs
|| !locate_decl_type_struct(data
->structs
, type
)) {
131 static inline int validate_decl_typedef(PSI_Data
*data
, decl_typedef
*def
) {
132 if (!validate_decl_type(data
, def
->type
)) {
133 data
->error(def
->token
, PSI_WARNING
,
134 "Type '%s' cannot be aliased to %s'%s'",
135 def
->type
->name
, def
->type
->type
== PSI_T_STRUCT
?"struct ":"",def
->alias
);
138 /* FIXME: check def->alias */
142 static inline int validate_constant(PSI_Data
*data
, constant
*c
) {
147 static inline int validate_decl_arg(PSI_Data
*data
, decl_arg
*arg
) {
148 if (!validate_decl_type(data
, arg
->type
)) {
149 data
->error(arg
->type
->token
, PSI_WARNING
,
150 "Cannot use '%s'(%d) as type for decl var '%s'",
151 arg
->type
->name
, arg
->type
->type
, arg
->var
->name
);
157 static int psi_sort_struct_arg_cmp(const void *_a
, const void *_b
) {
158 decl_arg
*a
= *(decl_arg
**)_a
, *b
= *(decl_arg
**)_b
;
160 if (a
->layout
->pos
== b
->layout
->pos
) {
161 if (a
->layout
->len
== b
->layout
->len
) {
163 } else if (a
->layout
->len
> b
->layout
->len
) {
168 } else if (a
->layout
->pos
> b
->layout
->pos
) {
174 static void psi_sort_struct_arg_swp(void *a
, void *b
) {
175 decl_arg
**_a
= a
, **_b
= b
, *_c
;
181 static inline void psi_sort_struct_args(decl_struct
*s
) {
182 zend_insert_sort(s
->args
->args
, s
->args
->count
, sizeof(*s
->args
->args
),
183 psi_sort_struct_arg_cmp
, psi_sort_struct_arg_swp
);
186 static inline int validate_decl_struct(PSI_Data
*data
, decl_struct
*s
) {
189 for (i
= 0; i
< s
->args
->count
; ++i
) {
190 if (!validate_decl_arg(data
, s
->args
->args
[i
])) {
195 for (i
= 0; i
< s
->args
->count
; ++i
) {
196 decl_arg
*darg
= s
->args
->args
[i
];
198 if (!validate_decl_arg(data
, darg
)) {
202 ZEND_ASSERT(!darg
->var
->arg
|| darg
->var
->arg
== darg
);
203 darg
->var
->arg
= darg
;
208 if (darg
->var
->array_size
) {
209 size
= psi_t_size(real_decl_type(darg
->type
)->type
) * darg
->var
->array_size
;
210 } else if (darg
->var
->pointer_level
) {
211 size
= psi_t_size(PSI_T_POINTER
);
213 decl_type
*real
= real_decl_type(darg
->type
);
215 if (real
->type
== PSI_T_STRUCT
) {
216 size
= real
->strct
->size
;
218 size
= psi_t_size(real
->type
);
221 if (darg
->layout
->len
!= size
) {
222 data
->error(darg
->token
, PSI_WARNING
,
223 "Computed length %zu of %s.%s does not match"
224 " pre-defined length %zu of type '%s'",
225 darg
->layout
->len
, s
->name
, darg
->var
->name
, size
,
232 if (darg
->var
->pointer_level
&& (!darg
->var
->array_size
|| darg
->var
->pointer_level
== 1)) {
235 t
= real_decl_type(darg
->type
)->type
;
239 decl_arg
*last
= s
->args
->args
[i
-1];
240 darg
->layout
= init_decl_struct_layout(
241 psi_t_align(t
, last
->layout
->pos
+ last
->layout
->len
),
242 psi_t_size(t
) * darg
->var
->array_size
);
244 darg
->layout
= init_decl_struct_layout(0, psi_t_size(t
));
247 if (s
->size
< darg
->layout
->pos
+ darg
->layout
->len
) {
248 s
->size
= darg
->layout
->pos
+ darg
->layout
->len
;
252 psi_sort_struct_args(s
);
257 static const char * const abi_ccs
[] = {
259 "extern", /* > - all the same */
265 static inline int validate_decl_abi(PSI_Data
*data
, decl_abi
*abi
) {
268 for (i
= 0; i
< sizeof(abi_ccs
)/sizeof(char*); ++i
) {
269 if (strcasecmp(abi
->convention
, abi_ccs
[i
])) {
275 static inline int validate_decl_func(PSI_Data
*data
, void *dl
, decl
*decl
, decl_arg
*func
)
277 struct psi_func_redir
*redir
;
279 if (!strcmp(func
->var
->name
, "dlsym")) {
280 data
->error(func
->token
, PSI_WARNING
, "Cannot dlsym dlsym (sic!)");
284 if (!validate_decl_arg(data
, func
)) {
287 for (redir
= &psi_func_redirs
[0]; redir
->name
; ++redir
) {
288 if (!strcmp(func
->var
->name
, redir
->name
)) {
289 decl
->call
.sym
= redir
->func
;
292 if (!decl
->call
.sym
) {
294 # define RTLD_NEXT ((void *) -1l)
296 decl
->call
.sym
= dlsym(dl
?: RTLD_NEXT
, func
->var
->name
);
297 if (!decl
->call
.sym
) {
298 data
->error(func
->token
, PSI_WARNING
,
299 "Failed to locate symbol '%s': %s",
300 func
->var
->name
, dlerror());
306 static inline int validate_decl(PSI_Data
*data
, void *dl
, decl
*decl
) {
307 if (!validate_decl_abi(data
, decl
->abi
)) {
308 data
->error(decl
->abi
->token
, PSI_WARNING
,
309 "Invalid calling convention: '%s'", decl
->abi
->token
->text
);
312 if (!validate_decl_func(data
, dl
, decl
, decl
->func
)) {
318 for (i
= 0; i
< decl
->args
->count
; ++i
) {
319 if (!validate_decl_arg(data
, decl
->args
->args
[i
])) {
326 static inline decl_arg
*locate_decl_var_arg(decl_var
*var
, decl_args
*args
, decl_arg
*func
) {
329 for (i
= 0; i
< args
->count
; ++i
) {
330 decl_arg
*arg
= args
->args
[i
];
332 if (!strcmp(var
->name
, arg
->var
->name
)) {
333 ZEND_ASSERT(!var
->arg
|| var
->arg
== arg
);
334 return var
->arg
= arg
;
337 if (func
&& !strcmp(var
->name
, func
->var
->name
)) {
338 return var
->arg
= func
;
343 static inline decl_arg
*locate_struct_member(decl_struct
*s
, decl_var
*var
) {
345 return locate_decl_var_arg(var
, s
->args
, NULL
);
350 static inline constant
*locate_num_exp_constant(num_exp
*exp
, constants
*consts
) {
353 for (i
= 0; i
< consts
->count
; ++i
) {
354 constant
*cnst
= consts
->list
[i
];
356 if (!strcmp(cnst
->name
, exp
->u
.numb
)) {
358 return exp
->u
.cnst
= cnst
;
364 static inline int validate_num_exp(PSI_Data
*data
, decl_args
*dargs
, decl_arg
*func
, num_exp
*exp
) {
366 switch (exp
->operator) {
368 exp
->calculator
= psi_calc_add
;
371 exp
->calculator
= psi_calc_sub
;
374 exp
->calculator
= psi_calc_mul
;
377 exp
->calculator
= psi_calc_div
;
379 EMPTY_SWITCH_DEFAULT_CASE();
381 if (!validate_num_exp(data
, dargs
, func
, exp
->operand
)) {
387 if (!locate_decl_var_arg(exp
->u
.dvar
, dargs
, func
)) {
388 data
->error(exp
->token
, PSI_WARNING
, "Unknown variable '%s' in numeric expression",
394 if (!locate_num_exp_constant(exp
, data
->consts
)) {
395 data
->error(exp
->token
, PSI_WARNING
, "Unknown constant '%s' in numeric expression",
406 static inline int validate_set_value_handler(set_value
*set
) {
407 switch (set
->func
->type
) {
409 set
->func
->handler
= psi_to_bool
;
412 set
->func
->handler
= psi_to_int
;
415 set
->func
->handler
= psi_to_double
;
417 case PSI_T_TO_STRING
:
418 set
->func
->handler
= psi_to_string
;
421 set
->func
->handler
= psi_to_array
;
423 case PSI_T_TO_OBJECT
:
424 set
->func
->handler
= psi_to_object
;
427 set
->func
->handler
= psi_to_void
;
430 if (set
->outer
.set
&& set
->outer
.set
->func
->type
== PSI_T_TO_ARRAY
) {
431 set
->func
->handler
= psi_to_recursive
;
432 set
->inner
= set
->outer
.set
->inner
;
433 set
->count
= set
->outer
.set
->count
;
442 static inline void decl_var_arg_v(decl_args
*args
, va_list argp
) {
446 memset(args
, 0, sizeof(*args
));
448 while ((argc
= va_arg(argp
, int))) {
449 argv
= va_arg(argp
, decl_arg
**);
451 add_decl_arg(args
, *argv
++);
455 static inline int validate_set_value_ex(PSI_Data
*data
, set_value
*set
, decl_arg
*ref
, decl_args
*ref_list
) {
458 decl_var
*set_var
= set
->vars
->vars
[0];
460 if (!validate_set_value_handler(set
)) {
461 data
->error(set
->func
->token
, PSI_WARNING
, "Invalid cast '%s' in `set` statement", set
->func
->name
);
465 for (i
= 0; i
< set
->vars
->count
; ++i
) {
466 decl_var
*svar
= set
->vars
->vars
[i
];
467 if (!svar
->arg
&& !locate_decl_var_arg(svar
, ref_list
, NULL
)) {
468 data
->error(svar
->token
, PSI_WARNING
, "Unknown variable '%s' in `set` statement", svar
->name
);
476 ref_type
= real_decl_type(ref
->type
);
479 int is_to_array
= (set
->func
->type
== PSI_T_TO_ARRAY
);
480 int is_pointer_to_struct
= (ref_type
->type
== PSI_T_STRUCT
&& ref
->var
->pointer_level
);
482 if (!is_to_array
&& !is_pointer_to_struct
) {
483 data
->error(set
->func
->token
, E_WARNING
, "Inner `set` statement casts only work with "
484 "to_array() casts on structs or pointers: %s(%s...", set
->func
->name
, set
->vars
->vars
[0]->name
);
489 if (!validate_num_exp(data
, ref_list
, ref
, set
->num
)) {
494 if (ref_type
->type
== PSI_T_STRUCT
) {
495 /* to_array(struct, to_...) */
496 if (!set
->outer
.set
|| set
->outer
.set
->inner
!= set
->inner
) {
497 for (i
= 0; i
< set
->count
; ++i
) {
498 decl_var
*sub_var
= set
->inner
[i
]->vars
->vars
[0];
499 decl_arg
*sub_ref
= locate_struct_member(ref_type
->strct
, sub_var
);
502 if (!validate_set_value_ex(data
, set
->inner
[i
], sub_ref
, ref_type
->strct
->args
)) {
508 } else if (set
->count
== 1) {
509 /* to_array(ptr, to_string(*ptr)) */
510 decl_var
*sub_var
= set
->inner
[0]->vars
->vars
[0];
511 decl_arg
*sub_ref
= locate_decl_var_arg(sub_var
, ref_list
, ref
);
514 if (strcmp(sub_var
->name
, set_var
->name
)) {
515 data
->error(sub_var
->token
, E_WARNING
, "Inner `set` statement casts on pointers must reference the same variable");
518 if (!validate_set_value_ex(data
, set
->inner
[0], sub_ref
, ref_list
)) {
522 } else if (set
->count
> 1) {
523 data
->error(set
->func
->token
, E_WARNING
, "Inner `set` statement casts on pointers may only occur once");
529 static inline int validate_set_value(PSI_Data
*data
, set_value
*set
, ...) {
531 decl_args args
= {0};
535 decl_var_arg_v(&args
, argp
);
538 check
= validate_set_value_ex(data
, set
, NULL
, &args
);
544 static inline decl
*locate_impl_decl(decls
*decls
, return_stmt
*ret
) {
548 for (i
= 0; i
< decls
->count
; ++i
) {
549 if (!strcmp(decls
->list
[i
]->func
->var
->name
, ret
->set
->vars
->vars
[0]->name
)) {
550 ret
->decl
= decls
->list
[i
]->func
;
551 return decls
->list
[i
];
558 static inline int validate_impl_ret_stmt(PSI_Data
*data
, impl
*impl
) {
561 /* we must have exactly one ret stmt delcaring the native func to call */
562 /* and which type cast to apply */
563 if (impl
->stmts
->ret
.count
!= 1) {
564 if (impl
->stmts
->ret
.count
> 1) {
565 data
->error(impl
->stmts
->ret
.list
[1]->token
, PSI_WARNING
,
566 "Too many `return` statements for implmentation %s;"
567 " found %zu, exactly one is needed",
568 impl
->func
->name
, impl
->stmts
->ret
.count
);
570 data
->error(impl
->func
->token
, PSI_WARNING
,
571 "Missing `return` statement for implementation %s",
577 ret
= impl
->stmts
->ret
.list
[0];
579 if (!(impl
->decl
= locate_impl_decl(data
->decls
, ret
))) {
580 data
->error(ret
->token
, PSI_WARNING
,
581 "Missing declaration '%s' for `return` statment for implementation %s",
582 ret
->set
->vars
->vars
[0]->name
, impl
->func
->name
);
586 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)) {
590 impl
->decl
->impl
= impl
;
595 static inline int validate_impl_let_stmts(PSI_Data
*data
, impl
*impl
) {
597 /* we can have multiple let stmts */
599 /* check that we have a decl arg for every let stmt */
600 for (i
= 0; i
< impl
->stmts
->let
.count
; ++i
) {
601 let_stmt
*let
= impl
->stmts
->let
.list
[i
];
605 if (let
->val
&& let
->val
->kind
== PSI_LET_TMP
) {
606 let_var
= let
->val
->data
.var
;
611 if (!locate_decl_var_arg(let_var
, impl
->decl
->args
, impl
->decl
->func
)) {
612 data
->error(let_var
->token
, PSI_WARNING
, "Unknown variable '%s' in `let` statement"
613 " of implementation '%s'", let_var
->name
, impl
->func
->name
);
617 switch (let
->val
->kind
) {
621 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
622 /* e.g. let foo = *bar; */
623 let
->var
->pointer_level
= let
->val
->data
.var
->pointer_level
;
624 let
->var
->arg
= init_decl_arg(
626 real_decl_type(let
->val
->data
.var
->arg
->type
)->type
,
627 real_decl_type(let
->val
->data
.var
->arg
->type
)->name
),
630 let
->var
->pointer_level
,
631 let
->var
->array_size
));
634 if (!validate_num_exp(data
, impl
->decl
->args
, impl
->decl
->func
, let
->val
->data
.num
)) {
639 if (!validate_num_exp(data
, impl
->decl
->args
, impl
->decl
->func
, let
->val
->data
.alloc
->nmemb
)) {
642 if (!validate_num_exp(data
, impl
->decl
->args
, impl
->decl
->func
, let
->val
->data
.alloc
->size
)) {
647 if (impl
->func
->args
) {
648 for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
649 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
651 if (!strcmp(let
->val
->data
.func
->var
->name
, iarg
->var
->name
)) {
652 let
->val
->data
.func
->arg
= iarg
;
659 data
->error(let
->var
->token
, PSI_WARNING
, "Unknown value '$%s' of `let` statement"
660 " for variable '%s' of implementation '%s'",
661 let
->val
->data
.func
->var
->name
, let
->var
->name
, impl
->func
->name
);
668 /* check that we have a let stmt for every decl arg */
669 if (impl
->decl
->args
) for (i
= 0; i
< impl
->decl
->args
->count
; ++i
) {
670 decl_arg
*darg
= impl
->decl
->args
->args
[i
];
673 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
674 let_stmt
*let
= impl
->stmts
->let
.list
[j
];
676 if (!strcmp(let
->var
->name
, darg
->var
->name
)) {
683 data
->error(impl
->func
->token
, PSI_WARNING
,
684 "Missing `let` statement for arg '%s %.*s%s'"
685 " of declaration '%s' for implementation '%s'",
686 darg
->type
->name
, (int) darg
->var
->pointer_level
, "*****",
687 darg
->var
->name
, impl
->decl
->func
->var
->name
, impl
->func
->name
);
694 static inline int validate_impl_set_stmts(PSI_Data
*data
, impl
*impl
) {
696 /* we can have any count of set stmts; processing out vars */
697 /* check that set stmts reference known variables */
698 for (i
= 0; i
< impl
->stmts
->set
.count
; ++i
) {
699 set_stmt
*set
= impl
->stmts
->set
.list
[i
];
702 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
703 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
705 if (!strcmp(set
->var
->name
, iarg
->var
->name
)) {
712 data
->error(set
->var
->token
, PSI_WARNING
, "Unknown variable '$%s' of `set` statement"
713 " of implementation '%s'",
714 set
->var
->name
, impl
->func
->name
);
718 for (j
= 0; j
< set
->val
->vars
->count
; ++j
) {
719 decl_var
*set_var
= set
->val
->vars
->vars
[j
];
722 if (impl
->decl
->args
) {
723 for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
724 decl_arg
*set_arg
= impl
->decl
->args
->args
[k
];
726 if (!strcmp(set_var
->name
, set_arg
->var
->name
)) {
728 set_var
->arg
= set_arg
;
729 if (!validate_set_value(data
, set
->val
, 1, &set_arg
, 1, &impl
->decl
->func
, impl
->decl
->args
->count
, impl
->decl
->args
->args
, 0)) {
737 for (k
= 0; k
< impl
->stmts
->let
.count
; ++k
) {
738 let_stmt
*let
= impl
->stmts
->let
.list
[k
];
740 /* check temp vars */
741 if (let
->val
&& let
->val
->kind
== PSI_LET_TMP
) {
742 if (!strcmp(set_var
->name
, let
->var
->name
)) {
744 set_var
->arg
= let
->var
->arg
;
745 if (!validate_set_value(data
, set
->val
, 1, &set_var
->arg
, 1, &impl
->decl
->func
, impl
->decl
->args
->count
, impl
->decl
->args
->args
, 0)) {
755 data
->error(set_var
->token
, PSI_WARNING
, "Unknown value '%s' of `set` statement"
756 " for variable '$%s' of implementation '%s'",
757 set_var
->name
, set
->arg
->var
->name
, impl
->func
->name
);
764 static inline decl
*locate_free_decl(decls
*decls
, free_call
*f
) {
768 for (i
= 0; i
< decls
->count
; ++i
) {
769 if (!strcmp(decls
->list
[i
]->func
->var
->name
, f
->func
)) {
770 f
->decl
= decls
->list
[i
];
771 return decls
->list
[i
];
778 static inline int validate_impl_free_stmts(PSI_Data
*data
, impl
*impl
) {
780 /* we can have any count of free stmts; freeing any out vars */
781 for (i
= 0; i
< impl
->stmts
->fre
.count
; ++i
) {
782 free_stmt
*fre
= impl
->stmts
->fre
.list
[i
];
784 for (j
= 0; j
< fre
->calls
->count
; ++j
) {
785 free_call
*free_call
= fre
->calls
->list
[j
];
787 /* first find the decl of the free func */
788 if (!locate_free_decl(data
->decls
, free_call
)) {
789 data
->error(free_call
->token
, PSI_WARNING
,
790 "Missing declaration '%s' in `free` statement"
791 " of implementation '%s'",
792 free_call
->func
, impl
->func
->name
);
798 /* now check for known vars */
799 for (l
= 0; l
< free_call
->vars
->count
; ++l
) {
801 decl_var
*free_var
= free_call
->vars
->vars
[l
];
803 if (!strcmp(free_var
->name
, impl
->decl
->func
->var
->name
)) {
805 free_var
->arg
= impl
->decl
->func
;
806 } else if (impl
->decl
->args
) {
807 for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
808 decl_arg
*free_arg
= impl
->decl
->args
->args
[k
];
810 if (!strcmp(free_var
->name
, free_arg
->var
->name
)) {
812 free_var
->arg
= free_arg
;
819 data
->error(free_var
->token
, PSI_WARNING
,
820 "Unknown variable '%s' of `free` statement"
821 " of implementation '%s'",
822 free_var
->name
, impl
->func
->name
);
830 static inline int validate_impl_stmts(PSI_Data
*data
, impl
*impl
) {
832 data
->error(impl
->func
->token
, PSI_WARNING
,
833 "Missing body for implementation %s!",
838 if (!validate_impl_ret_stmt(data
, impl
)) {
842 if (!validate_impl_let_stmts(data
, impl
)) {
845 if (!validate_impl_set_stmts(data
, impl
)) {
848 if (!validate_impl_free_stmts(data
, impl
)) {
855 static inline int validate_impl_args(PSI_Data
*data
, impl
*impl
) {
859 for (i
= 0; i
< impl
->func
->args
->count
; ++i
) {
860 impl_arg
*iarg
= impl
->func
->args
->args
[i
];
865 data
->error(impl
->func
->token
, PSI_WARNING
,
866 "Non-optional argument %zu '$%s' of implementation '%s'"
867 " follows optional argument",
868 i
+1, iarg
->var
->name
, impl
->func
->name
);
875 static inline int validate_impl(PSI_Data
*data
, impl
*impl
) {
876 if (!validate_impl_args(data
, impl
)) {
879 return validate_impl_stmts(data
, impl
);
882 PSI_Context
*PSI_ContextInit(PSI_Context
*C
, PSI_ContextOps
*ops
, PSI_ContextErrorFunc error
)
886 struct psi_predef_type
*predef_type
;
887 struct psi_predef_const
*predef_const
;
888 struct psi_predef_struct
*predef_struct
;
889 struct psi_predef_decl
*predef_decl
;
892 C
= malloc(sizeof(*C
));
894 memset(C
, 0, sizeof(*C
));
903 ZEND_ASSERT(ops
->call
!= NULL
);
904 ZEND_ASSERT(ops
->compile
!= NULL
);
906 /* build up predefs in a temporary PSI_Data for validation */
907 memset(&T
, 0, sizeof(T
));
910 for (predef_type
= &psi_predef_types
[0]; predef_type
->type_tag
; ++predef_type
) {
911 decl_type
*type
= init_decl_type(predef_type
->type_tag
, predef_type
->type_name
);
912 decl_typedef
*def
= init_decl_typedef(predef_type
->alias
, type
);
914 T
.defs
= add_decl_typedef(T
.defs
, def
);
916 for (predef_const
= &psi_predef_consts
[0]; predef_const
->type_tag
; ++predef_const
) {
917 impl_def_val
*val
= init_impl_def_val(predef_const
->val_type_tag
, predef_const
->val_text
);
918 const_type
*type
= init_const_type(predef_const
->type_tag
, predef_const
->type_name
);
919 constant
*constant
= init_constant(type
, predef_const
->var_name
, val
);
921 T
.consts
= add_constant(T
.consts
, constant
);
923 for (predef_struct
= &psi_predef_structs
[0]; predef_struct
->type_tag
; ++predef_struct
) {
924 struct psi_predef_struct
*member
;
925 decl_args
*dargs
= init_decl_args(NULL
);
926 decl_struct
*dstruct
= init_decl_struct(predef_struct
->var_name
, dargs
);
928 dstruct
->size
= predef_struct
->size
;
929 for (member
= &predef_struct
[1]; member
->type_tag
; ++member
) {
934 type
= init_decl_type(member
->type_tag
, member
->type_name
);
935 dvar
= init_decl_var(member
->var_name
, member
->pointer_level
, member
->array_size
);
936 darg
= init_decl_arg(type
, dvar
);
937 darg
->layout
= init_decl_struct_layout(member
->offset
, member
->size
);
938 dargs
= add_decl_arg(dargs
, darg
);
941 T
.structs
= add_decl_struct(T
.structs
, dstruct
);
942 predef_struct
= member
;
944 for (predef_decl
= &psi_predef_decls
[0]; predef_decl
->type_tag
; ++predef_decl
) {
945 struct psi_predef_decl
*farg
;
946 decl_type
*ftype
= init_decl_type(predef_decl
->type_tag
, predef_decl
->type_name
);
947 decl_var
*fname
= init_decl_var(predef_decl
->var_name
, predef_decl
->pointer_level
, predef_decl
->array_size
);
948 decl_arg
*func
= init_decl_arg(ftype
, fname
);
949 decl_args
*args
= init_decl_args(NULL
);
950 decl
*decl
= init_decl(init_decl_abi("default"), func
, args
);
952 for (farg
= &predef_decl
[1]; farg
->type_tag
; ++farg
) {
953 decl_type
*arg_type
= init_decl_type(farg
->type_tag
, farg
->type_name
);
954 decl_var
*arg_var
= init_decl_var(farg
->var_name
, farg
->pointer_level
, farg
->array_size
);
955 decl_arg
*darg
= init_decl_arg(arg_type
, arg_var
);
956 args
= add_decl_arg(args
, darg
);
959 T
.decls
= add_decl(T
.decls
, decl
);
963 for (predef_decl
= &psi_predef_vararg_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
);
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
);
979 T
.decls
= add_decl(T
.decls
, decl
);
983 for (i
= 0; i
< T
.defs
->count
; ++i
) {
984 decl_typedef
*def
= T
.defs
->list
[i
];
986 if (validate_decl_typedef(&T
, def
)) {
987 C
->defs
= add_decl_typedef(C
->defs
, def
);
991 for (i
= 0; i
< T
.consts
->count
; ++i
) {
992 constant
*constant
= T
.consts
->list
[i
];
994 if (validate_constant(&T
, constant
)) {
995 C
->consts
= add_constant(C
->consts
, constant
);
999 for (i
= 0; i
< T
.structs
->count
; ++i
) {
1000 decl_struct
*dstruct
= T
.structs
->list
[i
];
1002 if (validate_decl_struct(&T
, dstruct
)) {
1003 C
->structs
= add_decl_struct(C
->structs
, dstruct
);
1007 for (i
= 0; i
< T
.decls
->count
; ++i
) {
1008 decl
*decl
= T
.decls
->list
[i
];
1010 if (validate_decl(&T
, NULL
, decl
)) {
1011 C
->decls
= add_decl(C
->decls
, decl
);
1016 C
->data
= malloc(sizeof(*C
->data
));
1017 PSI_DataExchange(C
->data
, &T
);
1022 int PSI_ContextValidate(PSI_Context
*C
, PSI_Parser
*P
)
1025 void *dlopened
= NULL
;
1026 size_t count
= C
->count
++;
1028 C
->data
= realloc(C
->data
, C
->count
* sizeof(*C
->data
));
1029 D
= PSI_DataExchange(&C
->data
[count
], PSI_DATA(P
));
1034 for (i
= 0; i
< D
->defs
->count
; ++i
) {
1035 if (validate_decl_typedef(PSI_DATA(C
), D
->defs
->list
[i
])) {
1036 C
->defs
= add_decl_typedef(C
->defs
, D
->defs
->list
[i
]);
1043 for (i
= 0; i
< D
->structs
->count
; ++i
) {
1044 if (validate_decl_struct(PSI_DATA(C
), D
->structs
->list
[i
])) {
1045 C
->structs
= add_decl_struct(C
->structs
, D
->structs
->list
[i
]);
1052 for (i
= 0; i
< D
->consts
->count
; ++i
) {
1053 if (validate_constant(PSI_DATA(C
), D
->consts
->list
[i
])) {
1054 C
->consts
= add_constant(C
->consts
, D
->consts
->list
[i
]);
1059 if (!validate_lib(D
, &dlopened
)) {
1063 add_decl_lib(&C
->psi
.libs
, dlopened
);
1068 for (i
= 0; i
< D
->decls
->count
; ++i
) {
1069 if (validate_decl(PSI_DATA(C
), dlopened
, D
->decls
->list
[i
])) {
1070 C
->decls
= add_decl(C
->decls
, D
->decls
->list
[i
]);
1077 for (i
= 0; i
< D
->impls
->count
; ++i
) {
1078 if (validate_impl(PSI_DATA(C
), D
->impls
->list
[i
])) {
1079 C
->impls
= add_impl(C
->impls
, D
->impls
->list
[i
]);
1087 static int psi_select_dirent(const struct dirent
*entry
)
1089 #ifndef FNM_CASEFOLD
1090 #define FNM_CASEFOLD 0
1092 return 0 == fnmatch("*.psi", entry
->d_name
, FNM_CASEFOLD
);
1095 void PSI_ContextBuild(PSI_Context
*C
, const char *paths
)
1097 int i
, n
, flags
= psi_check_env("PSI_DEBUG") ? PSI_PARSER_DEBUG
: 0;
1098 char *sep
= NULL
, *cpy
= strdup(paths
), *ptr
= cpy
;
1099 struct dirent
**entries
= NULL
;
1103 sep
= strchr(ptr
, ':');
1109 n
= php_scandir(ptr
, &entries
, psi_select_dirent
, alphasort
);
1112 for (i
= 0; i
< n
; ++i
) {
1113 char psi
[MAXPATHLEN
];
1116 if (MAXPATHLEN
<= slprintf(psi
, MAXPATHLEN
, "%s/%s", ptr
, entries
[i
]->d_name
)) {
1117 C
->error(NULL
, PSI_WARNING
, "Path to PSI file too long: %s/%s",
1118 ptr
, entries
[i
]->d_name
);
1120 if (!PSI_ParserInit(&P
, psi
, C
->error
, flags
)) {
1121 C
->error(NULL
, PSI_WARNING
, "Failed to init PSI parser (%s): %s",
1122 psi
, strerror(errno
));
1126 while (0 < PSI_ParserScan(&P
)) {
1127 PSI_ParserParse(&P
, PSI_TokenAlloc(&P
));
1128 if (P
.num
== PSI_T_EOF
) {
1133 PSI_ParserParse(&P
, NULL
);
1134 PSI_ContextValidate(C
, &P
);
1140 for (i
= 0; i
< n
; ++i
) {
1150 if (PSI_ContextCompile(C
) && SUCCESS
!= zend_register_functions(NULL
, C
->closures
, NULL
, MODULE_PERSISTENT
)) {
1151 C
->error(NULL
, PSI_WARNING
, "Failed to register functions!");
1158 zend_function_entry
*PSI_ContextCompile(PSI_Context
*C
)
1165 zc
.flags
= CONST_PERSISTENT
|CONST_CS
;
1166 zc
.module_number
= EG(current_module
)->module_number
;
1168 for (i
= 0; i
< C
->consts
->count
; ++i
) {
1169 constant
*c
= C
->consts
->list
[i
];
1171 zc
.name
= zend_string_init(c
->name
+ (c
->name
[0] == '\\'), strlen(c
->name
) - (c
->name
[0] == '\\'), 1);
1172 ZVAL_NEW_STR(&zc
.value
, zend_string_init(c
->val
->text
, strlen(c
->val
->text
), 1));
1174 switch (c
->type
->type
) {
1176 convert_to_boolean(&zc
.value
);
1179 convert_to_long(&zc
.value
);
1182 convert_to_double(&zc
.value
);
1185 zend_register_constant(&zc
);
1189 return C
->closures
= C
->ops
->compile(C
);
1193 void PSI_ContextCall(PSI_Context
*C
, decl_callinfo
*decl_call
, impl_vararg
*va
)
1195 C
->ops
->call(C
, decl_call
, va
);
1198 static inline void dump_decl_type(int fd
, decl_type
*t
) {
1208 dprintf(fd
, "%s%s", pre
, t
->name
);
1210 static inline void dump_decl_var(int fd
, decl_var
*v
) {
1211 dprintf(fd
, "%.*s%s", v
->pointer_level
-!!v
->array_size
, "**********", v
->name
);
1212 if (v
->array_size
) {
1213 dprintf(fd
, "[%u]", v
->array_size
);
1216 static inline void dump_decl_arg(int fd
, decl_arg
*a
) {
1217 dump_decl_type(fd
, a
->type
);
1219 dump_decl_var(fd
, a
->var
);
1221 static inline void dump_level(int fd
, unsigned level
) {
1222 dprintf(fd
, "%.*s", level
, "\t\t\t\t\t\t\t\t\t");
1224 static inline void dump_num_exp(int fd
, num_exp
*exp
) {
1228 dprintf(fd
, "%s", exp
->u
.numb
);
1231 dprintf(fd
, "%s", exp
->u
.cnst
->name
);
1234 dump_decl_var(fd
, exp
->u
.dvar
);
1236 EMPTY_SWITCH_DEFAULT_CASE();
1241 switch (exp
->operator) {
1242 case PSI_T_PLUS
: op
= '+'; break;
1243 case PSI_T_MINUS
: op
= '-'; break;
1244 case PSI_T_ASTERISK
:op
= '*'; break;
1245 case PSI_T_SLASH
: op
= '/'; break;
1246 EMPTY_SWITCH_DEFAULT_CASE();
1248 dprintf(fd
, " %c ", op
);
1254 static inline void dump_impl_set_value(int fd
, set_value
*set
, unsigned level
, int last
) {
1258 /* only if not directly after `set ...` */
1259 dump_level(fd
, level
);
1262 if (set
->func
->type
== PSI_T_ELLIPSIS
) {
1263 dprintf(fd
, "%s(", set
->outer
.set
->func
->name
);
1265 dprintf(fd
, "%s(", set
->func
->name
);
1268 for (i
= 0; i
< set
->vars
->count
; ++i
) {
1269 decl_var
*svar
= set
->vars
->vars
[i
];
1273 dump_decl_var(fd
, svar
);
1276 if (set
->func
->type
== PSI_T_ELLIPSIS
) {
1277 dprintf(fd
, ", ...");
1281 dump_num_exp(fd
, set
->num
);
1283 if (set
->inner
&& set
->func
->type
!= PSI_T_ELLIPSIS
) {
1285 for (i
= 0; i
< set
->count
; ++i
) {
1286 dump_impl_set_value(fd
, set
->inner
[i
], level
+1, i
== (set
->count
- 1));
1288 /* only if inner stmts, i.e. with new lines, were dumped */
1289 dump_level(fd
, level
);
1292 dprintf(fd
, ")%s\n", last
? "" : ",");
1294 dprintf(fd
, ");\n");
1297 void PSI_ContextDump(PSI_Context
*C
, int fd
)
1302 if (C
->ops
== PSI_Libjit()) {
1303 dprintf(fd
, "// psi.engine=jit\n");
1307 if (C
->ops
== PSI_Libffi()) {
1308 dprintf(fd
, "// psi.engine=ffi\n");
1314 for (i
= 0; i
< C
->defs
->count
; ++i
) {
1315 decl_typedef
*tdef
= C
->defs
->list
[i
];
1317 dprintf(fd
, "typedef ");
1318 dump_decl_type(fd
, tdef
->type
);
1319 dprintf(fd
, " %s%s;\n", tdef
->type
->type
== PSI_T_POINTER
? "*":"",
1326 for (i
= 0; i
< C
->structs
->count
; ++i
) {
1327 decl_struct
*strct
= C
->structs
->list
[i
];
1329 dprintf(fd
, "struct %s::(%zu)", strct
->name
, strct
->size
);
1330 if (strct
->args
&& strct
->args
->count
) {
1331 dprintf(fd
, " {\n");
1332 for (j
= 0; j
< strct
->args
->count
; ++j
) {
1333 decl_arg
*sarg
= strct
->args
->args
[j
];
1336 dump_decl_arg(fd
, sarg
);
1337 dprintf(fd
, "::(%zu, %zu);\n", sarg
->layout
->pos
, sarg
->layout
->len
);
1349 for (i
= 0; i
< C
->consts
->count
; ++i
) {
1350 constant
*cnst
= C
->consts
->list
[i
];
1352 dprintf(fd
, "const %s %s = ", cnst
->type
->name
, cnst
->name
);
1353 if (cnst
->val
->type
== PSI_T_QUOTED_STRING
) {
1354 dprintf(fd
, "\"%s\";\n", cnst
->val
->text
);
1356 dprintf(fd
, "%s;\n", cnst
->val
->text
);
1362 for (i
= 0; i
< C
->decls
->count
; ++i
) {
1363 decl
*decl
= C
->decls
->list
[i
];
1365 dprintf(fd
, "%s ", decl
->abi
->convention
);
1366 dump_decl_arg(fd
, decl
->func
);
1369 for (j
= 0; j
< decl
->args
->count
; ++j
) {
1373 dump_decl_arg(fd
, decl
->args
->args
[j
]);
1375 if (decl
->args
->varargs
) {
1376 dprintf(fd
, ", ...");
1379 dprintf(fd
, ");\n");
1384 for (i
= 0; i
< C
->impls
->count
; ++i
) {
1385 impl
*impl
= C
->impls
->list
[i
];
1387 dprintf(fd
, "function %s(", impl
->func
->name
);
1388 if (impl
->func
->args
) {
1389 for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
1390 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
1392 dprintf(fd
, "%s%s %s$%s",
1395 iarg
->var
->reference
? "&" : "",
1398 dprintf(fd
, " = %s", iarg
->def
->text
);
1401 if (impl
->func
->args
->vararg
.name
) {
1402 impl_arg
*vararg
= impl
->func
->args
->vararg
.name
;
1404 dprintf(fd
, ", %s %s...$%s",
1406 vararg
->var
->reference
? "&" : "",
1410 dprintf(fd
, ") : %s%s {\n",
1411 impl
->func
->return_reference
? "&":"",
1412 impl
->func
->return_type
->name
);
1414 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
1415 let_stmt
*let
= impl
->stmts
->let
.list
[j
];
1417 dprintf(fd
, "\tlet %s", let
->var
->name
);
1419 dprintf(fd
, " = %s", let
->val
->flags
.one
.is_reference
? "&" : "");
1420 switch (let
->val
->kind
) {
1422 dprintf(fd
, "NULL");
1425 dump_decl_var(fd
, let
->val
->data
.var
);
1427 case PSI_LET_CALLOC
:
1428 dprintf(fd
, "calloc(");
1429 dump_num_exp(fd
, let
->val
->data
.alloc
->nmemb
);
1431 dump_num_exp(fd
, let
->val
->data
.alloc
->size
);
1435 dprintf(fd
, "%s($%s)", let
->val
->data
.func
->name
,
1436 let
->val
->data
.func
->var
->name
);
1438 case PSI_LET_NUMEXP
:
1439 dump_num_exp(fd
, let
->val
->data
.num
);
1442 EMPTY_SWITCH_DEFAULT_CASE();
1447 for (j
= 0; j
< impl
->stmts
->ret
.count
; ++j
) {
1448 return_stmt
*ret
= impl
->stmts
->ret
.list
[j
];
1450 dprintf(fd
, "\treturn ");
1451 dump_impl_set_value(fd
, ret
->set
, 1, 0);
1453 for (j
= 0; j
< impl
->stmts
->set
.count
; ++j
) {
1454 set_stmt
*set
= impl
->stmts
->set
.list
[j
];
1456 dprintf(fd
, "\tset $%s = ", set
->var
->name
);
1457 dump_impl_set_value(fd
, set
->val
, 1, 0);
1459 for (j
= 0; j
< impl
->stmts
->fre
.count
; ++j
) {
1460 free_stmt
*fre
= impl
->stmts
->fre
.list
[j
];
1462 dprintf(fd
, "\tfree ");
1463 for (k
= 0; k
< fre
->calls
->count
; ++k
) {
1464 free_call
*call
= fre
->calls
->list
[k
];
1469 dprintf(fd
, "%s(", call
->func
);
1470 for (l
= 0; l
< call
->vars
->count
; ++l
) {
1471 decl_var
*fvar
= call
->vars
->vars
[l
];
1473 dump_decl_var(fd
, fvar
);
1475 dprintf(fd
, ");\n");
1485 void PSI_ContextDtor(PSI_Context
*C
)
1488 zend_function_entry
*zfe
;
1494 free_decl_libs(&C
->psi
.libs
);
1497 for (i
= 0; i
< C
->count
; ++i
) {
1498 PSI_DataDtor(&C
->data
[i
]);
1504 for (zfe
= C
->closures
; zfe
->fname
; ++zfe
) {
1505 free((void *) zfe
->arg_info
);
1511 if (C
->consts
->list
) {
1512 free(C
->consts
->list
);
1517 if (C
->defs
->list
) {
1518 free(C
->defs
->list
);
1523 if (C
->structs
->list
) {
1524 free(C
->structs
->list
);
1529 if (C
->decls
->list
) {
1530 free(C
->decls
->list
);
1535 if (C
->impls
->list
) {
1536 free(C
->impls
->list
);
1541 memset(C
, 0, sizeof(*C
));
1544 void PSI_ContextFree(PSI_Context
**C
)
1547 PSI_ContextDtor(*C
);