8 #ifdef HAVE_SYS_TYPES_H
9 # include <sys/types.h>
11 #ifdef HAVE_SYS_STAT_H
12 # include <sys/stat.h>
23 # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
31 #ifdef HAVE_INTTYPES_H
32 # include <inttypes.h>
47 #ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
50 #ifdef HAVE_ARPA_NAMESER_H
51 # include <arpa/nameser.h>
59 #ifdef HAVE_SYS_SELECT_H
60 # include <sys/select.h>
62 #ifdef HAVE_SYS_SOCKET_H
63 # include <sys/socket.h>
65 #ifdef HAVE_SYS_TIME_H
66 # include <sys/time.h>
68 #ifdef HAVE_SYS_TIMES_H
69 # include <sys/times.h>
74 #ifdef HAVE_SYS_UTSNAME_H
75 # include <sys/utsname.h>
86 # define NAMLEN(dirent) strlen ((dirent)->d_name)
88 # define dirent direct
89 # define NAMLEN(dirent) ((dirent)->d_namlen)
90 # ifdef HAVE_SYS_NDIR_H
91 # include <sys/ndir.h>
93 # ifdef HAVE_SYS_DIR_H
101 #include <sys/param.h>
106 #include "php_scandir.h"
114 static struct psi_std_type
{
116 const char *type_name
;
117 } psi_std_types
[] = {
118 {PSI_T_FLOAT
, "float"},
119 {PSI_T_DOUBLE
, "double"},
120 {PSI_T_INT8
, "int8_t"},
121 {PSI_T_INT16
, "int16_t"},
122 {PSI_T_INT32
, "int32_t"},
123 {PSI_T_INT64
, "int64_t"},
124 {PSI_T_UINT8
, "uint8_t"},
125 {PSI_T_UINT16
, "uint16_t"},
126 {PSI_T_UINT32
, "uint32_t"},
127 {PSI_T_UINT64
, "uint64_t"},
131 static struct psi_predef_type
{
133 const char *type_name
;
135 } psi_predef_types
[] = {
140 static struct psi_predef_const
{
142 const char *type_name
;
143 const char *var_name
;
144 const char *val_text
;
145 token_t val_type_tag
;
146 } psi_predef_consts
[] = {
153 static struct psi_func_redir
{
156 } psi_func_redirs
[] = {
161 static struct psi_predef_decl
{
163 const char *type_name
;
164 const char *var_name
;
165 size_t pointer_level
;
167 } psi_predef_decls
[] = {
172 static struct psi_predef_struct
{
174 const char *type_name
;
175 const char *var_name
;
178 size_t pointer_level
;
180 } psi_predef_structs
[] = {
185 static int validate_lib(PSI_Data
*data
, void **dlopened
) {
186 char lib
[MAXPATHLEN
];
187 const char *ptr
= data
->psi
.file
.ln
;
191 /* FIXME: assume stdlib */
193 } else if (!strchr(ptr
, '/')) {
194 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.%s", ptr
, PHP_PSI_SHLIB_SUFFIX
);
195 if (MAXPATHLEN
== len
) {
196 data
->error(PSI_WARNING
, "Library name too long: '%s'", ptr
);
201 if (!(*dlopened
= dlopen(ptr
, RTLD_LAZY
|RTLD_LOCAL
))) {
202 data
->error(PSI_WARNING
, "Could not open library '%s': %s.",
203 data
->psi
.file
.ln
, dlerror());
209 static inline int locate_decl_type_alias(decl_typedefs
*defs
, decl_type
*type
) {
211 struct psi_std_type
*stdtyp
;
216 for (i
= 0; i
< defs
->count
; ++i
) {
217 decl_typedef
*def
= defs
->list
[i
];
219 if (def
->type
->type
!= type
->type
&& !strcmp(def
->alias
, type
->name
)) {
220 type
->real
= def
->type
;
224 for (stdtyp
= &psi_std_types
[0]; stdtyp
->type_tag
; ++stdtyp
) {
225 if (!strcmp(type
->name
, stdtyp
->type_name
)) {
226 type
->type
= stdtyp
->type_tag
;
233 static inline int locate_decl_type_struct(decl_structs
*structs
, decl_type
*type
) {
239 for (i
= 0; i
< structs
->count
; ++i
) {
240 if (!strcmp(structs
->list
[i
]->name
, type
->name
)) {
241 type
->strct
= structs
->list
[i
];
248 static inline int validate_decl_type(PSI_Data
*data
, decl_type
*type
) {
249 switch (type
->type
) {
251 if (!data
->defs
|| !locate_decl_type_alias(data
->defs
, type
)) {
255 return validate_decl_type(data
, type
->real
);
259 if (!data
->structs
|| !locate_decl_type_struct(data
->structs
, type
)) {
266 static inline int validate_decl_typedef(PSI_Data
*data
, decl_typedef
*def
) {
267 if (!validate_decl_type(data
, def
->type
)) {
268 data
->error(PSI_WARNING
, "Type '%s' cannot be aliased to %s'%s'",
269 def
->type
->name
, def
->type
->type
== PSI_T_STRUCT
?"struct ":"",def
->alias
);
272 /* FIXME: check def->alias */
276 static inline int validate_constant(PSI_Data
*data
, constant
*c
) {
281 static inline int validate_decl_arg(PSI_Data
*data
, decl_arg
*arg
) {
282 if (!validate_decl_type(data
, arg
->type
)) {
283 data
->error(PSI_WARNING
, "Cannot use '%s'(%d) as type for '%s'",
284 arg
->type
->name
, arg
->type
->type
, arg
->var
->name
);
290 static inline int validate_decl_struct(PSI_Data
*data
, decl_struct
*s
) {
293 for (i
= 0; i
< s
->args
->count
; ++i
) {
294 if (!validate_decl_arg(data
, s
->args
->args
[i
])) {
299 for (i
= 0; i
< s
->args
->count
; ++i
) {
300 decl_arg
*darg
= s
->args
->args
[i
];
302 if (!validate_decl_arg(data
, darg
)) {
306 ZEND_ASSERT(!darg
->var
->arg
|| darg
->var
->arg
== darg
);
307 darg
->var
->arg
= darg
;
312 if (darg
->var
->pointer_level
&& (!darg
->var
->array_size
|| darg
->var
->pointer_level
== 1)) {
315 t
= real_decl_type(darg
->type
)->type
;
319 decl_arg
*last
= s
->args
->args
[i
-1];
320 darg
->layout
= init_decl_struct_layout(
321 psi_t_align(t
, last
->layout
->pos
+ last
->layout
->len
),
322 psi_t_size(t
) * darg
->var
->array_size
);
324 darg
->layout
= init_decl_struct_layout(0, psi_t_size(t
));
327 if (s
->size
< darg
->layout
->pos
+ darg
->layout
->len
) {
328 s
->size
= darg
->layout
->pos
+ darg
->layout
->len
;
334 static const char * const abi_ccs
[] = {
336 "extern", /* > - all the same */
341 static inline int validate_decl_abi(PSI_Data
*data
, decl_abi
*abi
) {
344 for (i
= 0; i
< sizeof(abi_ccs
)/sizeof(char*); ++i
) {
345 if (strcasecmp(abi
->convention
, abi_ccs
[i
])) {
349 data
->error(PSI_WARNING
, "Invalid calling convention: '%s'", abi
->convention
);
352 static inline int validate_decl_func(PSI_Data
*data
, void *dl
, decl
*decl
, decl_arg
*func
)
354 struct psi_func_redir
*redir
;
356 if (!strcmp(func
->var
->name
, "dlsym")) {
357 data
->error(PSI_WARNING
, "Cannot dlsym dlsym (sic!)");
361 if (!validate_decl_arg(data
, func
)) {
364 for (redir
= &psi_func_redirs
[0]; redir
->name
; ++redir
) {
365 if (!strcmp(func
->var
->name
, redir
->name
)) {
366 decl
->call
.sym
= redir
->func
;
369 if (!decl
->call
.sym
) {
371 # define RTLD_NEXT ((void *) -1l)
373 decl
->call
.sym
= dlsym(dl
?: RTLD_NEXT
, func
->var
->name
);
374 if (!decl
->call
.sym
) {
375 data
->error(PSI_WARNING
, "Failed to locate symbol '%s': %s",
376 func
->var
->name
, dlerror());
382 static inline int validate_decl(PSI_Data
*data
, void *dl
, decl
*decl
) {
383 if (!validate_decl_abi(data
, decl
->abi
)) {
386 if (!validate_decl_func(data
, dl
, decl
, decl
->func
)) {
392 for (i
= 0; i
< decl
->args
->count
; ++i
) {
393 if (!validate_decl_arg(data
, decl
->args
->args
[i
])) {
400 static inline decl_arg
*locate_decl_var_arg(decl_var
*var
, decl_args
*args
) {
403 for (i
= 0; i
< args
->count
; ++i
) {
404 decl_arg
*arg
= args
->args
[i
];
406 if (!strcmp(var
->name
, arg
->var
->name
)) {
407 ZEND_ASSERT(!var
->arg
|| var
->arg
== arg
);
408 return var
->arg
= arg
;
414 static inline decl_arg
*locate_struct_member(decl_struct
*s
, decl_var
*var
) {
416 return locate_decl_var_arg(var
, s
->args
);
421 static inline constant
*locate_num_exp_constant(num_exp
*exp
, constants
*consts
) {
424 for (i
= 0; i
< consts
->count
; ++i
) {
425 constant
*cnst
= consts
->list
[i
];
427 if (!strcmp(cnst
->name
, exp
->u
.numb
)) {
429 return exp
->u
.cnst
= cnst
;
435 static inline int validate_num_exp(PSI_Data
*data
, decl_args
*dargs
, num_exp
*exp
) {
437 switch (exp
->operator) {
439 exp
->calculator
= psi_calc_add
;
442 exp
->calculator
= psi_calc_sub
;
445 exp
->calculator
= psi_calc_mul
;
448 exp
->calculator
= psi_calc_div
;
450 EMPTY_SWITCH_DEFAULT_CASE();
452 if (!validate_num_exp(data
, dargs
, exp
->operand
)) {
458 if (!locate_decl_var_arg(exp
->u
.dvar
, dargs
)) {
459 data
->error(PSI_WARNING
, "Unknown variable '%s' in numeric expression",
465 if (!locate_num_exp_constant(exp
, data
->consts
)) {
466 data
->error(PSI_WARNING
, "Unknown constant '%s' in numeric expression",
477 static inline int validate_set_value(PSI_Data
*data
, set_value
*set
, decl_arg
*ref
, decl_args
*ref_list
) {
479 decl_type
*ref_type
= real_decl_type(ref
->type
);
480 decl_var
*set_var
= set
->vars
->vars
[0];
482 switch (set
->func
->type
) {
484 set
->func
->handler
= psi_to_bool
;
487 set
->func
->handler
= psi_to_int
;
490 set
->func
->handler
= psi_to_double
;
492 case PSI_T_TO_STRING
:
493 set
->func
->handler
= psi_to_string
;
496 set
->func
->handler
= psi_to_array
;
498 case PSI_T_TO_OBJECT
:
499 set
->func
->handler
= psi_to_object
;
502 set
->func
->handler
= psi_to_void
;
504 EMPTY_SWITCH_DEFAULT_CASE();
507 for (i
= 1; i
< set
->vars
->count
; ++i
) {
508 if (!locate_decl_var_arg(set
->vars
->vars
[i
], ref_list
)) {
515 int is_to_array
= (set
->func
->type
== PSI_T_TO_ARRAY
);
516 int is_pointer_to_struct
= (ref_type
->type
== PSI_T_STRUCT
&& ref
->var
->pointer_level
);
518 if (!is_to_array
&& !is_pointer_to_struct
) {
519 data
->error(E_WARNING
, "Inner `set` statement casts only work with "
520 "to_array() casts on structs or pointers: %s(%s...", set
->func
->name
, set
->vars
->vars
[0]->name
);
525 if (!validate_num_exp(data
, ref_list
, set
->num
)) {
530 if (ref_type
->type
== PSI_T_STRUCT
) {
531 /* to_array(struct, to_...) */
532 for (i
= 0; i
< set
->count
; ++i
) {
533 decl_var
*sub_var
= set
->inner
[i
]->vars
->vars
[0];
534 decl_arg
*sub_ref
= locate_struct_member(ref_type
->strct
, sub_var
);
536 set
->inner
[i
]->outer
.set
= set
;
538 if (!validate_set_value(data
, set
->inner
[i
], sub_ref
, ref_type
->strct
->args
)) {
543 } else if (set
->count
== 1) {
544 /* to_array(ptr, to_string(*ptr)) */
545 decl_var
*sub_var
= set
->inner
[0]->vars
->vars
[0];
546 decl_arg
*sub_ref
= locate_decl_var_arg(sub_var
, ref_list
);
548 set
->inner
[0]->outer
.set
= set
;
550 if (strcmp(sub_var
->name
, set_var
->name
)) {
551 data
->error(E_WARNING
, "Inner `set` statement casts on pointers must reference the same variable");
554 if (!validate_set_value(data
, set
->inner
[0], sub_ref
, ref_list
)) {
558 } else if (set
->count
> 1) {
559 data
->error(E_WARNING
, "Inner `set` statement casts on pointers may only occur once");
565 static inline decl
*locate_impl_decl(decls
*decls
, return_stmt
*ret
) {
569 for (i
= 0; i
< decls
->count
; ++i
) {
570 if (!strcmp(decls
->list
[i
]->func
->var
->name
, ret
->set
->vars
->vars
[0]->name
)) {
571 ret
->decl
= decls
->list
[i
]->func
;
572 return decls
->list
[i
];
579 static inline int validate_impl_ret_stmt(PSI_Data
*data
, impl
*impl
) {
582 /* we must have exactly one ret stmt delcaring the native func to call */
583 /* and which type cast to apply */
584 if (impl
->stmts
->ret
.count
!= 1) {
585 if (impl
->stmts
->ret
.count
> 1) {
586 data
->error(PSI_WARNING
, "Too many `return` statements for implmentation %s;"
587 " found %zu, exactly one is needed",
588 impl
->func
->name
, impl
->stmts
->ret
.count
);
590 data
->error(PSI_WARNING
, "Missing `return` statement for implementation %s",
596 ret
= impl
->stmts
->ret
.list
[0];
598 if (!(impl
->decl
= locate_impl_decl(data
->decls
, ret
))) {
599 data
->error(PSI_WARNING
, "Missing declaration for implementation %s",
604 if (!validate_set_value(data
, ret
->set
, ret
->decl
, impl
->decl
->args
)) {
608 impl
->decl
->impl
= impl
;
613 static inline int validate_impl_let_stmts(PSI_Data
*data
, impl
*impl
) {
615 /* we can have multiple let stmts */
616 /* check that we have a let stmt for every decl arg */
617 if (impl
->decl
->args
) for (i
= 0; i
< impl
->decl
->args
->count
; ++i
) {
618 decl_arg
*darg
= impl
->decl
->args
->args
[i
];
621 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
622 let_stmt
*let
= impl
->stmts
->let
.list
[j
];
624 if (!strcmp(let
->var
->name
, darg
->var
->name
)) {
631 data
->error(PSI_WARNING
, "Missing `let` statement for arg '%s %.*s%s'"
632 " of declaration '%s' for implementation '%s'",
633 darg
->type
->name
, (int) darg
->var
->pointer_level
, "*****",
634 darg
->var
->name
, impl
->decl
->func
->var
->name
, impl
->func
->name
);
638 /* check that the let_value references a known variable or NULL */
639 for (i
= 0; i
< impl
->stmts
->let
.count
; ++i
) {
640 let_stmt
*let
= impl
->stmts
->let
.list
[i
];
643 if (let
->val
&& let
->val
->func
&& let
->val
->func
->alloc
) {
644 if (!validate_num_exp(data
, impl
->decl
->args
, let
->val
->func
->alloc
->nmemb
)) {
647 if (!validate_num_exp(data
, impl
->decl
->args
, let
->val
->func
->alloc
->size
)) {
651 if (let
->val
&& let
->val
->var
) {
652 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
653 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
655 if (!strcmp(let
->val
->var
->name
, iarg
->var
->name
)) {
662 data
->error(PSI_WARNING
, "Unknown value '$%s' of `let` statement"
663 " for variable '%s' of implementation '%s'",
664 let
->val
->var
->name
, let
->var
->name
, impl
->func
->name
);
671 static inline int validate_impl_set_stmts(PSI_Data
*data
, impl
*impl
) {
673 /* we can have any count of set stmts; processing out vars */
674 /* check that set stmts reference known variables */
675 for (i
= 0; i
< impl
->stmts
->set
.count
; ++i
) {
676 set_stmt
*set
= impl
->stmts
->set
.list
[i
];
679 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
680 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
682 if (!strcmp(set
->var
->name
, iarg
->var
->name
)) {
689 data
->error(PSI_WARNING
, "Unknown variable '$%s' of `set` statement"
690 " of implementation '%s'",
691 set
->var
->name
, impl
->func
->name
);
695 for (j
= 0; j
< set
->val
->vars
->count
; ++j
) {
696 decl_var
*set_var
= set
->val
->vars
->vars
[j
];
699 if (impl
->decl
->args
) for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
700 decl_arg
*set_arg
= impl
->decl
->args
->args
[k
];
702 if (!strcmp(set_var
->name
, set_arg
->var
->name
)) {
704 set_var
->arg
= set_arg
;
705 if (!validate_set_value(data
, set
->val
, set_arg
, impl
->decl
->args
)) {
713 data
->error(PSI_WARNING
, "Unknown value '%s' of `set` statement"
714 " for variable '$%s' of implementation '%s'",
715 set_var
->name
, set
->arg
->var
->name
, impl
->func
->name
);
722 static inline decl
*locate_free_decl(decls
*decls
, free_call
*f
) {
726 for (i
= 0; i
< decls
->count
; ++i
) {
727 if (!strcmp(decls
->list
[i
]->func
->var
->name
, f
->func
)) {
728 f
->decl
= decls
->list
[i
];
729 return decls
->list
[i
];
736 static inline int validate_impl_free_stmts(PSI_Data
*data
, impl
*impl
) {
738 /* we can have any count of free stmts; freeing any out vars */
739 for (i
= 0; i
< impl
->stmts
->fre
.count
; ++i
) {
740 free_stmt
*fre
= impl
->stmts
->fre
.list
[i
];
742 for (j
= 0; j
< fre
->calls
->count
; ++j
) {
743 free_call
*free_call
= fre
->calls
->list
[j
];
745 /* first find the decl of the free func */
746 if (!locate_free_decl(data
->decls
, free_call
)) {
747 data
->error(PSI_WARNING
, "Unknown function '%s' in `free` statement"
748 " of implementation '%s'", free_call
->func
, impl
->func
->name
);
751 if (!impl
->decl
->args
) {
752 data
->error(PSI_WARNING
, "Declaration '%s' of implementation '%s'"
753 " does not have any arguments to free",
754 impl
->decl
->func
->var
->name
, impl
->func
->name
);
757 /* now check for known vars */
758 for (l
= 0; l
< free_call
->vars
->count
; ++l
) {
760 decl_var
*free_var
= free_call
->vars
->vars
[l
];
762 for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
763 decl_arg
*free_arg
= impl
->decl
->args
->args
[k
];
765 if (!strcmp(free_var
->name
, free_arg
->var
->name
)) {
767 free_var
->arg
= free_arg
;
773 data
->error(PSI_WARNING
, "Unknown variable '%s' of `free` statement"
774 " of implementation '%s'",
775 free_var
->name
, impl
->func
->name
);
783 static inline int validate_impl_stmts(PSI_Data
*data
, impl
*impl
) {
785 data
->error(PSI_WARNING
, "Missing body for implementation %s!",
790 if (!validate_impl_ret_stmt(data
, impl
)) {
794 if (!validate_impl_let_stmts(data
, impl
)) {
797 if (!validate_impl_set_stmts(data
, impl
)) {
800 if (!validate_impl_free_stmts(data
, impl
)) {
807 PSI_Context
*PSI_ContextInit(PSI_Context
*C
, PSI_ContextOps
*ops
, PSI_ContextErrorFunc error
)
811 struct psi_predef_type
*predef_type
;
812 struct psi_predef_const
*predef_const
;
813 struct psi_predef_struct
*predef_struct
;
814 struct psi_predef_decl
*predef_decl
;
817 C
= malloc(sizeof(*C
));
819 memset(C
, 0, sizeof(*C
));
828 ZEND_ASSERT(ops
->call
!= NULL
);
829 ZEND_ASSERT(ops
->compile
!= NULL
);
831 /* build up predefs in a temporary PSI_Data for validation */
832 memset(&T
, 0, sizeof(T
));
835 for (predef_type
= &psi_predef_types
[0]; predef_type
->type_tag
; ++predef_type
) {
836 decl_type
*type
= init_decl_type(predef_type
->type_tag
, predef_type
->type_name
);
837 decl_typedef
*def
= init_decl_typedef(predef_type
->alias
, type
);
839 T
.defs
= add_decl_typedef(T
.defs
, def
);
841 for (predef_const
= &psi_predef_consts
[0]; predef_const
->type_tag
; ++predef_const
) {
842 impl_def_val
*val
= init_impl_def_val(predef_const
->val_type_tag
, predef_const
->val_text
);
843 const_type
*type
= init_const_type(predef_const
->type_tag
, predef_const
->type_name
);
844 constant
*constant
= init_constant(type
, predef_const
->var_name
, val
);
846 T
.consts
= add_constant(T
.consts
, constant
);
848 for (predef_struct
= &psi_predef_structs
[0]; predef_struct
->type_tag
; ++predef_struct
) {
849 struct psi_predef_struct
*member
;
850 decl_args
*dargs
= init_decl_args(NULL
);
851 decl_struct
*dstruct
= init_decl_struct(predef_struct
->var_name
, dargs
);
853 dstruct
->size
= predef_struct
->size
;
854 for (member
= &predef_struct
[1]; member
->type_tag
; ++member
) {
859 type
= init_decl_type(member
->type_tag
, member
->type_name
);
860 dvar
= init_decl_var(member
->var_name
, member
->pointer_level
, member
->array_size
);
861 darg
= init_decl_arg(type
, dvar
);
862 darg
->layout
= init_decl_struct_layout(member
->offset
, member
->size
);
863 dargs
= add_decl_arg(dargs
, darg
);
866 T
.structs
= add_decl_struct(T
.structs
, dstruct
);
867 predef_struct
= member
;
869 for (predef_decl
= &psi_predef_decls
[0]; predef_decl
->type_tag
; ++predef_decl
) {
870 struct psi_predef_decl
*farg
;
871 decl_type
*ftype
= init_decl_type(predef_decl
->type_tag
, predef_decl
->type_name
);
872 decl_var
*fname
= init_decl_var(predef_decl
->var_name
, predef_decl
->pointer_level
, predef_decl
->array_size
);
873 decl_arg
*func
= init_decl_arg(ftype
, fname
);
874 decl_args
*args
= init_decl_args(NULL
);
875 decl
*decl
= init_decl(init_decl_abi("default"), func
, args
);
878 for (farg
= &predef_decl
[1]; farg
->type_tag
; ++farg
) {
879 decl_type
*arg_type
= init_decl_type(farg
->type_tag
, farg
->type_name
);
880 decl_var
*arg_var
= init_decl_var(farg
->var_name
, farg
->pointer_level
, farg
->array_size
);
881 decl_arg
*darg
= init_decl_arg(arg_type
, arg_var
);
882 args
= add_decl_arg(args
, darg
);
885 T
.decls
= add_decl(T
.decls
, decl
);
889 for (i
= 0; i
< T
.defs
->count
; ++i
) {
890 decl_typedef
*def
= T
.defs
->list
[i
];
892 if (validate_decl_typedef(&T
, def
)) {
893 C
->defs
= add_decl_typedef(C
->defs
, def
);
897 for (i
= 0; i
< T
.consts
->count
; ++i
) {
898 constant
*constant
= T
.consts
->list
[i
];
900 if (validate_constant(&T
, constant
)) {
901 C
->consts
= add_constant(C
->consts
, constant
);
905 for (i
= 0; i
< T
.structs
->count
; ++i
) {
906 decl_struct
*dstruct
= T
.structs
->list
[i
];
908 if (validate_decl_struct(&T
, dstruct
)) {
909 C
->structs
= add_decl_struct(C
->structs
, dstruct
);
913 for (i
= 0; i
< T
.decls
->count
; ++i
) {
914 decl
*decl
= T
.decls
->list
[i
];
916 if (validate_decl(&T
, NULL
, decl
)) {
917 C
->decls
= add_decl(C
->decls
, decl
);
922 C
->data
= malloc(sizeof(*C
->data
));
923 PSI_DataExchange(C
->data
, &T
);
928 int PSI_ContextValidate(PSI_Context
*C
, PSI_Parser
*P
)
931 void *dlopened
= NULL
;
932 size_t count
= C
->count
++;
934 C
->data
= realloc(C
->data
, C
->count
* sizeof(*C
->data
));
935 D
= PSI_DataExchange(&C
->data
[count
], PSI_DATA(P
));
940 for (i
= 0; i
< D
->defs
->count
; ++i
) {
941 if (validate_decl_typedef(PSI_DATA(C
), D
->defs
->list
[i
])) {
942 C
->defs
= add_decl_typedef(C
->defs
, D
->defs
->list
[i
]);
949 for (i
= 0; i
< D
->structs
->count
; ++i
) {
950 if (validate_decl_struct(PSI_DATA(C
), D
->structs
->list
[i
])) {
951 C
->structs
= add_decl_struct(C
->structs
, D
->structs
->list
[i
]);
958 for (i
= 0; i
< D
->consts
->count
; ++i
) {
959 if (validate_constant(PSI_DATA(C
), D
->consts
->list
[i
])) {
960 C
->consts
= add_constant(C
->consts
, D
->consts
->list
[i
]);
965 if (!validate_lib(D
, &dlopened
)) {
969 add_decl_lib(&C
->psi
.libs
, dlopened
);
974 for (i
= 0; i
< D
->decls
->count
; ++i
) {
975 if (validate_decl(PSI_DATA(C
), dlopened
, D
->decls
->list
[i
])) {
976 C
->decls
= add_decl(C
->decls
, D
->decls
->list
[i
]);
983 for (i
= 0; i
< D
->impls
->count
; ++i
) {
984 if (validate_impl_stmts(PSI_DATA(C
), D
->impls
->list
[i
])) {
985 C
->impls
= add_impl(C
->impls
, D
->impls
->list
[i
]);
993 static int psi_select_dirent(const struct dirent
*entry
)
996 #define FNM_CASEFOLD 0
998 return 0 == fnmatch("*.psi", entry
->d_name
, FNM_CASEFOLD
);
1001 void PSI_ContextBuild(PSI_Context
*C
, const char *paths
)
1003 int i
, n
, flags
= psi_check_env("PSI_DEBUG") ? PSI_PARSER_DEBUG
: 0;
1004 char *sep
= NULL
, *cpy
= strdup(paths
), *ptr
= cpy
;
1005 struct dirent
**entries
= NULL
;
1009 sep
= strchr(ptr
, ':');
1015 n
= php_scandir(ptr
, &entries
, psi_select_dirent
, alphasort
);
1018 for (i
= 0; i
< n
; ++i
) {
1019 char psi
[MAXPATHLEN
];
1022 if (MAXPATHLEN
<= slprintf(psi
, MAXPATHLEN
, "%s/%s", ptr
, entries
[i
]->d_name
)) {
1023 C
->error(PSI_WARNING
, "Path to PSI file too long: %s/%s",
1024 ptr
, entries
[i
]->d_name
);
1026 if (!PSI_ParserInit(&P
, psi
, C
->error
, flags
)) {
1027 C
->error(PSI_WARNING
, "Failed to init PSI parser (%s): %s",
1028 psi
, strerror(errno
));
1032 while (0 < PSI_ParserScan(&P
)) {
1033 PSI_ParserParse(&P
, PSI_TokenAlloc(&P
));
1034 if (P
.num
== PSI_T_EOF
) {
1039 PSI_ParserParse(&P
, NULL
);
1040 PSI_ContextValidate(C
, &P
);
1046 for (i
= 0; i
< n
; ++i
) {
1056 if (PSI_ContextCompile(C
) && SUCCESS
!= zend_register_functions(NULL
, C
->closures
, NULL
, MODULE_PERSISTENT
)) {
1057 C
->error(PSI_WARNING
, "Failed to register functions!");
1064 zend_function_entry
*PSI_ContextCompile(PSI_Context
*C
)
1071 zc
.flags
= CONST_PERSISTENT
|CONST_CS
;
1072 zc
.module_number
= EG(current_module
)->module_number
;
1074 for (i
= 0; i
< C
->consts
->count
; ++i
) {
1075 constant
*c
= C
->consts
->list
[i
];
1077 zc
.name
= zend_string_init(c
->name
+ (c
->name
[0] == '\\'), strlen(c
->name
) - (c
->name
[0] == '\\'), 1);
1078 ZVAL_NEW_STR(&zc
.value
, zend_string_init(c
->val
->text
, strlen(c
->val
->text
), 1));
1080 switch (c
->type
->type
) {
1082 convert_to_boolean(&zc
.value
);
1085 convert_to_long(&zc
.value
);
1088 convert_to_double(&zc
.value
);
1091 zend_register_constant(&zc
);
1095 return C
->closures
= C
->ops
->compile(C
);
1099 void PSI_ContextCall(PSI_Context
*C
, impl_val
*ret_val
, decl
*decl
)
1102 C
->ops
->call(C
, ret_val
, decl
);
1105 static inline void dump_decl_type(int fd
, decl_type
*t
) {
1115 dprintf(fd
, "%s%s", pre
, t
->name
);
1117 static inline void dump_decl_var(int fd
, decl_var
*v
) {
1118 dprintf(fd
, "%.*s%s", v
->pointer_level
-!!v
->array_size
, "**********", v
->name
);
1119 if (v
->array_size
) {
1120 dprintf(fd
, "[%u]", v
->array_size
);
1123 static inline void dump_decl_arg(int fd
, decl_arg
*a
) {
1124 dump_decl_type(fd
, a
->type
);
1126 dump_decl_var(fd
, a
->var
);
1128 static inline void dump_level(int fd
, unsigned level
) {
1129 dprintf(fd
, "%.*s", level
, "\t\t\t\t\t\t\t\t\t");
1131 static inline void dump_impl_set_value(int fd
, set_value
*set
, unsigned level
) {
1135 /* only if not directly after `set ...` */
1136 dump_level(fd
, level
);
1138 dprintf(fd
, "%s(", set
->func
->name
);
1140 for (i
= 0; i
< set
->vars
->count
; ++i
) {
1141 decl_var
*svar
= set
->vars
->vars
[i
];
1145 dump_decl_var(fd
, svar
);
1149 for (i
= 0; i
< set
->count
; ++i
) {
1150 dump_impl_set_value(fd
, set
->inner
[i
], level
+1);
1152 /* only if inner stmts, i.e. with new lines, were dumped */
1153 dump_level(fd
, level
);
1156 dprintf(fd
, "),\n");
1158 dprintf(fd
, ");\n");
1161 static inline void dump_num_exp(int fd
, num_exp
*exp
) {
1164 dprintf(fd
, "%s", exp
->u
.numb
);
1167 dump_decl_var(fd
, exp
->u
.dvar
);
1170 dprintf(fd
, "%s", exp
->u
.cnst
->name
);
1172 EMPTY_SWITCH_DEFAULT_CASE();
1175 void PSI_ContextDump(PSI_Context
*C
, int fd
)
1180 if (C
->ops
== PSI_Libjit()) {
1181 dprintf(fd
, "// psi.engine=jit\n");
1185 if (C
->ops
== PSI_Libffi()) {
1186 dprintf(fd
, "// psi.engine=ffi\n");
1192 for (i
= 0; i
< C
->defs
->count
; ++i
) {
1193 decl_typedef
*tdef
= C
->defs
->list
[i
];
1195 dprintf(fd
, "typedef ");
1196 dump_decl_type(fd
, tdef
->type
);
1197 dprintf(fd
, " %s;\n", tdef
->alias
);
1203 for (i
= 0; i
< C
->structs
->count
; ++i
) {
1204 decl_struct
*strct
= C
->structs
->list
[i
];
1206 dprintf(fd
, "struct %s::(%zu) {\n", strct
->name
, strct
->size
);
1207 if (strct
->args
) for (j
= 0; j
< strct
->args
->count
; ++j
) {
1208 decl_arg
*sarg
= strct
->args
->args
[j
];
1211 dump_decl_arg(fd
, sarg
);
1212 dprintf(fd
, "::(%zu, %zu);\n", sarg
->layout
->pos
, sarg
->layout
->len
);
1219 for (i
= 0; i
< C
->consts
->count
; ++i
) {
1220 constant
*cnst
= C
->consts
->list
[i
];
1222 dprintf(fd
, "const %s %s = ", cnst
->type
->name
, cnst
->name
);
1223 if (cnst
->val
->type
== PSI_T_QUOTED_STRING
) {
1224 dprintf(fd
, "\"%s\";\n", cnst
->val
->text
);
1226 dprintf(fd
, "%s;\n", cnst
->val
->text
);
1232 for (i
= 0; i
< C
->decls
->count
; ++i
) {
1233 decl
*decl
= C
->decls
->list
[i
];
1235 dprintf(fd
, "%s ", decl
->abi
->convention
);
1236 dump_decl_arg(fd
, decl
->func
);
1238 if (decl
->args
) for (j
= 0; j
< decl
->args
->count
; ++j
) {
1242 dump_decl_arg(fd
, decl
->args
->args
[j
]);
1244 dprintf(fd
, ");\n");
1249 for (i
= 0; i
< C
->impls
->count
; ++i
) {
1250 impl
*impl
= C
->impls
->list
[i
];
1252 dprintf(fd
, "function %s(", impl
->func
->name
);
1253 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
1254 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
1256 dprintf(fd
, "%s%s %s$%s",
1259 iarg
->var
->reference
? "&" : "",
1262 dprintf(fd
, " = %s", iarg
->def
->text
);
1265 dprintf(fd
, ") : %s%s {\n",
1266 impl
->func
->return_reference
? "&":"",
1267 impl
->func
->return_type
->name
);
1269 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
1270 let_stmt
*let
= impl
->stmts
->let
.list
[j
];
1272 dprintf(fd
, "\tlet %s", let
->var
->name
);
1274 dprintf(fd
, " = %s", let
->val
->is_reference
? "&" : "");
1275 if (let
->val
->func
) {
1276 dprintf(fd
, "%s(", let
->val
->func
->name
);
1277 if (let
->val
->func
->alloc
) {
1278 dump_num_exp(fd
, let
->val
->func
->alloc
->nmemb
);
1280 dump_num_exp(fd
, let
->val
->func
->alloc
->size
);
1282 dprintf(fd
, "$%s", let
->val
->var
->name
);
1284 dprintf(fd
, ");\n");
1286 dprintf(fd
, "NULL;\n");
1290 for (j
= 0; j
< impl
->stmts
->ret
.count
; ++j
) {
1291 return_stmt
*ret
= impl
->stmts
->ret
.list
[j
];
1293 dprintf(fd
, "\treturn ");
1294 dump_impl_set_value(fd
, ret
->set
, 1);
1296 for (j
= 0; j
< impl
->stmts
->set
.count
; ++j
) {
1297 set_stmt
*set
= impl
->stmts
->set
.list
[j
];
1299 dprintf(fd
, "\tset $%s = ", set
->var
->name
);
1300 dump_impl_set_value(fd
, set
->val
, 1);
1302 for (j
= 0; j
< impl
->stmts
->fre
.count
; ++j
) {
1303 free_stmt
*fre
= impl
->stmts
->fre
.list
[j
];
1305 dprintf(fd
, "\tfree ");
1306 for (k
= 0; k
< fre
->calls
->count
; ++k
) {
1307 free_call
*call
= fre
->calls
->list
[k
];
1312 dprintf(fd
, "%s(", call
->func
);
1313 for (l
= 0; l
< call
->vars
->count
; ++l
) {
1314 decl_var
*fvar
= call
->vars
->vars
[l
];
1316 dump_decl_var(fd
, fvar
);
1318 dprintf(fd
, ");\n");
1328 void PSI_ContextDtor(PSI_Context
*C
)
1331 zend_function_entry
*zfe
;
1337 free_decl_libs(&C
->psi
.libs
);
1340 for (i
= 0; i
< C
->count
; ++i
) {
1341 PSI_DataDtor(&C
->data
[i
]);
1347 for (zfe
= C
->closures
; zfe
->fname
; ++zfe
) {
1348 free((void *) zfe
->arg_info
);
1354 if (C
->consts
->list
) {
1355 free(C
->consts
->list
);
1360 if (C
->defs
->list
) {
1361 free(C
->defs
->list
);
1366 if (C
->structs
->list
) {
1367 free(C
->structs
->list
);
1372 if (C
->decls
->list
) {
1373 free(C
->decls
->list
);
1378 if (C
->impls
->list
) {
1379 free(C
->impls
->list
);
1384 memset(C
, 0, sizeof(*C
));
1387 void PSI_ContextFree(PSI_Context
**C
)
1390 PSI_ContextDtor(*C
);