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 #define psi_predef_count(of) ((sizeof(psi_predef ##of## s)/sizeof(psi_predef ##of))-1)
115 typedef struct psi_predef_type
{
117 const char *type_name
;
120 static const psi_predef_type psi_predef_types
[] = {
123 #define psi_predef_type_count() psi_predef_count(_type)
125 typedef struct psi_predef_const
{
127 const char *type_name
;
129 const char *val_text
;
130 token_t val_type_tag
;
132 static const psi_predef_const psi_predef_consts
[] = {
135 #define psi_predef_const_count() psi_predef_count(_const)
137 typedef struct psi_predef_struct_member
{
139 const char *type_name
;
143 size_t pointer_level
;
145 } psi_predef_struct_member
;
146 #define PSI_PREDEF_STRUCT_MEMBERS 32
147 typedef struct psi_predef_struct
{
150 psi_predef_struct_member members
[PSI_PREDEF_STRUCT_MEMBERS
];
152 static const psi_predef_struct psi_predef_structs
[] = {
155 #define psi_predef_struct_count() psi_predef_count(_struct)
159 typedef struct psi_predef_func
{
163 static psi_predef_func psi_predef_funcs
[] = {
166 #define psi_predef_func_count() psi_predef_count(_func)
168 static int validate_lib(PSI_Data
*data
, void **dlopened
) {
169 char lib
[MAXPATHLEN
];
170 const char *ptr
= data
->psi
.file
.ln
;
174 /* FIXME: assume stdlib */
176 } else if (!strchr(ptr
, '/')) {
177 len
= snprintf(lib
, MAXPATHLEN
, "lib%s.%s", ptr
, PHP_PSI_SHLIB_SUFFIX
);
178 if (MAXPATHLEN
== len
) {
179 data
->error(PSI_WARNING
, "Library name too long: '%s'", ptr
);
184 if (!(*dlopened
= dlopen(ptr
, RTLD_LAZY
|RTLD_LOCAL
))) {
185 data
->error(PSI_WARNING
, "Could not open library '%s': %s.",
186 data
->psi
.file
.ln
, dlerror());
192 static inline int locate_decl_type_alias(decl_typedefs
*defs
, decl_type
*type
) {
198 for (i
= 0; i
< defs
->count
; ++i
) {
199 if (!strcmp(defs
->list
[i
]->alias
, type
->name
)) {
200 type
->real
= defs
->list
[i
]->type
;
206 static inline int locate_decl_type_struct(decl_structs
*structs
, decl_type
*type
) {
212 for (i
= 0; i
< structs
->count
; ++i
) {
213 if (!strcmp(structs
->list
[i
]->name
, type
->name
)) {
214 type
->strct
= structs
->list
[i
];
221 static inline int validate_decl_type(PSI_Data
*data
, decl_type
*type
) {
222 switch (type
->type
) {
224 if (!data
->defs
|!locate_decl_type_alias(data
->defs
, type
)) {
227 return validate_decl_type(data
, type
->real
);
229 if (!data
->structs
|| !locate_decl_type_struct(data
->structs
, type
)) {
236 static inline int validate_decl_typedef(PSI_Data
*data
, decl_typedef
*def
) {
237 if (!validate_decl_type(data
, def
->type
)) {
238 data
->error(PSI_WARNING
, "Type '%s' cannot be aliased to '%s'",
239 def
->type
->name
, def
->alias
);
242 /* FIXME: check def->alias */
246 static inline int validate_constant(PSI_Data
*data
, constant
*c
) {
251 static inline int validate_decl_arg(PSI_Data
*data
, decl_arg
*arg
) {
252 if (!validate_decl_type(data
, arg
->type
)) {
253 data
->error(PSI_WARNING
, "Cannot use '%s'(%d) as type for '%s'",
254 arg
->type
->name
, arg
->type
->type
, arg
->var
->name
);
260 static inline int validate_decl_struct(PSI_Data
*data
, decl_struct
*s
) {
263 for (i
= 0; i
< s
->args
->count
; ++i
) {
264 if (!validate_decl_arg(data
, s
->args
->args
[i
])) {
269 for (i
= 0; i
< s
->args
->count
; ++i
) {
270 decl_arg
*darg
= s
->args
->args
[i
];
272 if (!validate_decl_arg(data
, darg
)) {
276 ZEND_ASSERT(!darg
->var
->arg
|| darg
->var
->arg
== darg
);
277 darg
->var
->arg
= darg
;
282 if (darg
->var
->pointer_level
&& (!darg
->var
->array_size
|| darg
->var
->pointer_level
== 1)) {
285 t
= real_decl_type(darg
->type
)->type
;
289 decl_arg
*last
= s
->args
->args
[i
-1];
290 darg
->layout
= init_decl_struct_layout(
291 psi_t_align(t
, last
->layout
->pos
+ last
->layout
->len
),
292 psi_t_size(t
) * darg
->var
->array_size
);
294 darg
->layout
= init_decl_struct_layout(0, psi_t_size(t
));
297 if (s
->size
< darg
->layout
->pos
+ darg
->layout
->len
) {
298 s
->size
= darg
->layout
->pos
+ darg
->layout
->len
;
304 static const char * const abi_ccs
[] = {
306 "extern", /* > - all the same */
311 static inline int validate_decl_abi(PSI_Data
*data
, decl_abi
*abi
) {
314 for (i
= 0; i
< sizeof(abi_ccs
)/sizeof(char*); ++i
) {
315 if (strcasecmp(abi
->convention
, abi_ccs
[i
])) {
319 data
->error(PSI_WARNING
, "Invalid calling convention: '%s'", abi
->convention
);
322 static inline int validate_decl_func(PSI_Data
*data
, void *dl
, decl
*decl
, decl_arg
*func
)
326 if (!strcmp(func
->var
->name
, "dlsym")) {
327 data
->error(PSI_WARNING
, "Cannot dlsym dlsym (sic!)");
331 if (!validate_decl_arg(data
, func
)) {
334 for (i
= 0; i
< psi_predef_func_count(); ++i
) {
335 psi_predef_func
*pre
= &psi_predef_funcs
[i
];
337 if (!strcmp(func
->var
->name
, pre
->name
)) {
338 decl
->call
.sym
= pre
->func
;
342 if (!decl
->call
.sym
) {
344 # define RTLD_NEXT ((void *) -1l)
346 decl
->call
.sym
= dlsym(dl
?: RTLD_NEXT
, func
->var
->name
);
347 if (!decl
->call
.sym
) {
348 data
->error(PSI_WARNING
, "Failed to locate symbol '%s': %s",
349 func
->var
->name
, dlerror());
355 static inline int validate_decl(PSI_Data
*data
, void *dl
, decl
*decl
) {
356 if (!validate_decl_abi(data
, decl
->abi
)) {
359 if (!validate_decl_func(data
, dl
, decl
, decl
->func
)) {
365 for (i
= 0; i
< decl
->args
->count
; ++i
) {
366 if (!validate_decl_arg(data
, decl
->args
->args
[i
])) {
373 static inline decl_arg
*locate_decl_var_arg(decl_var
*var
, decl_args
*args
) {
376 for (i
= 0; i
< args
->count
; ++i
) {
377 decl_arg
*arg
= args
->args
[i
];
379 if (!strcmp(var
->name
, arg
->var
->name
)) {
380 return var
->arg
= arg
;
386 static inline decl_arg
*locate_struct_member(decl_struct
*s
, decl_var
*var
) {
388 return locate_decl_var_arg(var
, s
->args
);
393 static inline int validate_set_value(PSI_Data
*data
, set_value
*set
, decl_arg
*ref
, decl_args
*ref_list
) {
395 decl_type
*ref_type
= real_decl_type(ref
->type
);
396 decl_var
*set_var
= set
->vars
->vars
[0];
398 switch (set
->func
->type
) {
400 set
->func
->handler
= psi_to_bool
;
403 set
->func
->handler
= psi_to_int
;
406 set
->func
->handler
= psi_to_double
;
408 case PSI_T_TO_STRING
:
409 set
->func
->handler
= psi_to_string
;
412 set
->func
->handler
= psi_to_array
;
414 EMPTY_SWITCH_DEFAULT_CASE();
417 for (i
= 1; i
< set
->vars
->count
; ++i
) {
418 if (!locate_decl_var_arg(set
->vars
->vars
[i
], ref_list
)) {
424 if (set
->count
&& (set
->func
->type
!= PSI_T_TO_ARRAY
|| (ref_type
->type
!= PSI_T_STRUCT
&& !ref
->var
->arg
->var
->pointer_level
))) {
425 data
->error(E_WARNING
, "Inner `set` statement casts only work with to_array() casts on structs or pointers");
429 if (ref_type
->type
== PSI_T_STRUCT
) {
430 /* to_array(struct, to_...) */
431 for (i
= 0; i
< set
->count
; ++i
) {
432 decl_var
*sub_var
= set
->inner
[i
]->vars
->vars
[0];
433 decl_arg
*sub_ref
= locate_struct_member(ref_type
->strct
, sub_var
);
436 if (!validate_set_value(data
, set
->inner
[i
], sub_ref
, ref_type
->strct
->args
)) {
439 set
->inner
[i
]->outer
.set
= set
;
442 } else if (set
->count
== 1) {
443 /* to_array(ptr, to_string(*ptr)) */
444 decl_var
*sub_var
= set
->inner
[0]->vars
->vars
[0];
445 decl_arg
*sub_ref
= locate_decl_var_arg(sub_var
, ref_list
);
448 if (strcmp(sub_var
->name
, set_var
->name
)) {
449 data
->error(E_WARNING
, "Inner `set` statement casts on pointers must reference the same variable");
452 if (!validate_set_value(data
, set
->inner
[0], sub_ref
, ref_list
)) {
455 set
->inner
[0]->outer
.set
= set
;
457 } else if (set
->count
> 1) {
458 data
->error(E_WARNING
, "Inner `set` statement casts on pointers may only occur once");
464 static inline decl
*locate_impl_decl(decls
*decls
, return_stmt
*ret
) {
468 for (i
= 0; i
< decls
->count
; ++i
) {
469 if (!strcmp(decls
->list
[i
]->func
->var
->name
, ret
->set
->vars
->vars
[0]->name
)) {
470 ret
->decl
= decls
->list
[i
]->func
;
471 return decls
->list
[i
];
478 static inline int validate_impl_ret_stmt(PSI_Data
*data
, impl
*impl
) {
481 /* we must have exactly one ret stmt delcaring the native func to call */
482 /* and which type cast to apply */
483 if (impl
->stmts
->ret
.count
!= 1) {
484 if (impl
->stmts
->ret
.count
> 1) {
485 data
->error(PSI_WARNING
, "Too many `return` statements for implmentation %s;"
486 " found %zu, exactly one is needed",
487 impl
->func
->name
, impl
->stmts
->ret
.count
);
489 data
->error(PSI_WARNING
, "Missing `return` statement for implementation %s",
495 ret
= impl
->stmts
->ret
.list
[0];
497 if (!(impl
->decl
= locate_impl_decl(data
->decls
, ret
))) {
498 data
->error(PSI_WARNING
, "Missing declaration for implementation %s",
503 if (!validate_set_value(data
, ret
->set
, ret
->decl
, impl
->decl
->args
)) {
507 impl
->decl
->impl
= impl
;
511 static inline int validate_impl_let_stmts(PSI_Data
*data
, impl
*impl
) {
513 /* we can have multiple let stmts */
514 /* check that we have a let stmt for every decl arg */
515 if (impl
->decl
->args
) for (i
= 0; i
< impl
->decl
->args
->count
; ++i
) {
516 decl_arg
*darg
= impl
->decl
->args
->args
[i
];
519 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
520 let_stmt
*let
= impl
->stmts
->let
.list
[j
];
522 if (!strcmp(let
->var
->name
, darg
->var
->name
)) {
529 data
->error(PSI_WARNING
, "Missing `let` statement for arg '%s %.*s%s'"
530 " of declaration '%s' for implementation '%s'",
531 darg
->type
->name
, (int) darg
->var
->pointer_level
, "*****",
532 darg
->var
->name
, impl
->decl
->func
->var
->name
, impl
->func
->name
);
536 /* check that the let_value references a known variable or NULL */
537 for (i
= 0; i
< impl
->stmts
->let
.count
; ++i
) {
538 let_stmt
*let
= impl
->stmts
->let
.list
[i
];
541 if (let
->val
&& let
->val
->func
&& let
->val
->func
->alloc
) {
542 if (!validate_decl_type(data
, let
->val
->func
->alloc
->type
)) {
543 data
->error(PSI_WARNING
, "Cannot use '%s' as type for calloc in `let` statement",
544 let
->val
->func
->alloc
->type
->name
);
548 if (let
->val
&& let
->val
->var
) {
549 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
550 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
552 if (!strcmp(let
->val
->var
->name
, iarg
->var
->name
)) {
559 data
->error(PSI_WARNING
, "Unknown value '$%s' of `let` statement"
560 " for variable '%s' of implementation '%s'",
561 let
->val
->var
->name
, let
->var
->name
, impl
->func
->name
);
568 static inline int validate_impl_set_stmts(PSI_Data
*data
, impl
*impl
) {
570 /* we can have any count of set stmts; processing out vars */
571 /* check that set stmts reference known variables */
572 for (i
= 0; i
< impl
->stmts
->set
.count
; ++i
) {
573 set_stmt
*set
= impl
->stmts
->set
.list
[i
];
576 if (impl
->func
->args
) for (j
= 0; j
< impl
->func
->args
->count
; ++j
) {
577 impl_arg
*iarg
= impl
->func
->args
->args
[j
];
579 if (!strcmp(set
->var
->name
, iarg
->var
->name
)) {
586 data
->error(PSI_WARNING
, "Unknown variable '$%s' of `set` statement"
587 " of implementation '%s'",
588 set
->var
->name
, impl
->func
->name
);
592 for (j
= 0; j
< set
->val
->vars
->count
; ++j
) {
593 decl_var
*set_var
= set
->val
->vars
->vars
[j
];
596 if (impl
->decl
->args
) for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
597 decl_arg
*set_arg
= impl
->decl
->args
->args
[k
];
599 if (!strcmp(set_var
->name
, set_arg
->var
->name
)) {
601 if (!validate_set_value(data
, set
->val
, set_arg
, impl
->decl
->args
)) {
604 set_var
->arg
= set_arg
;
610 data
->error(PSI_WARNING
, "Unknown value '%s' of `set` statement"
611 " for variable '$%s' of implementation '%s'",
612 set_var
->name
, set
->arg
->var
->name
, impl
->func
->name
);
619 static inline decl
*locate_free_decl(decls
*decls
, free_call
*f
) {
623 for (i
= 0; i
< decls
->count
; ++i
) {
624 if (!strcmp(decls
->list
[i
]->func
->var
->name
, f
->func
)) {
625 f
->decl
= decls
->list
[i
];
626 return decls
->list
[i
];
633 static inline int validate_impl_free_stmts(PSI_Data
*data
, impl
*impl
) {
635 /* we can have any count of free stmts; freeing any out vars */
636 for (i
= 0; i
< impl
->stmts
->fre
.count
; ++i
) {
637 free_stmt
*fre
= impl
->stmts
->fre
.list
[i
];
639 for (j
= 0; j
< fre
->calls
->count
; ++j
) {
640 free_call
*free_call
= fre
->calls
->list
[j
];
642 /* first find the decl of the free func */
643 if (!locate_free_decl(data
->decls
, free_call
)) {
644 data
->error(PSI_WARNING
, "Unknown function '%s' in `free` statement"
645 " of implementation '%s'", free_call
->func
, impl
->func
->name
);
648 if (!impl
->decl
->args
) {
649 data
->error(PSI_WARNING
, "Declaration '%s' of implementation '%s'"
650 " does not have any arguments to free",
651 impl
->decl
->func
->var
->name
, impl
->func
->name
);
654 /* now check for known vars */
655 for (l
= 0; l
< free_call
->vars
->count
; ++l
) {
657 decl_var
*free_var
= free_call
->vars
->vars
[l
];
659 for (k
= 0; k
< impl
->decl
->args
->count
; ++k
) {
660 decl_arg
*free_arg
= impl
->decl
->args
->args
[k
];
662 if (!strcmp(free_var
->name
, free_arg
->var
->name
)) {
664 free_var
->arg
= free_arg
;
670 data
->error(PSI_WARNING
, "Unknown variable '%s' of `free` statement"
671 " of implementation '%s'",
672 free_var
->name
, impl
->func
->name
);
680 static inline int validate_impl_stmts(PSI_Data
*data
, impl
*impl
) {
682 data
->error(PSI_WARNING
, "Missing body for implementation %s!",
687 if (!validate_impl_ret_stmt(data
, impl
)) {
691 if (!validate_impl_let_stmts(data
, impl
)) {
694 if (!validate_impl_set_stmts(data
, impl
)) {
697 if (!validate_impl_free_stmts(data
, impl
)) {
704 PSI_Context
*PSI_ContextInit(PSI_Context
*C
, PSI_ContextOps
*ops
, PSI_ContextErrorFunc error
)
710 C
= malloc(sizeof(*C
));
712 memset(C
, 0, sizeof(*C
));
721 ZEND_ASSERT(ops
->call
!= NULL
);
722 ZEND_ASSERT(ops
->compile
!= NULL
);
724 /* build up predefs in a temporary PSI_Data for validation */
725 memset(&T
, 0, sizeof(T
));
728 for (i
= 0; i
< psi_predef_type_count(); ++i
) {
729 const psi_predef_type
*pre
= &psi_predef_types
[i
];
730 decl_type
*type
= init_decl_type(pre
->type_tag
, pre
->type_name
);
731 decl_typedef
*def
= init_decl_typedef(pre
->alias
, type
);
733 T
.defs
= add_decl_typedef(T
.defs
, def
);
735 for (i
= 0; i
< psi_predef_const_count(); ++i
) {
736 const psi_predef_const
*pre
= &psi_predef_consts
[i
];
737 impl_def_val
*val
= init_impl_def_val(pre
->val_type_tag
, pre
->val_text
);
738 const_type
*type
= init_const_type(pre
->type_tag
, pre
->type_name
);
739 constant
*constant
= init_constant(type
, pre
->name
, val
);
741 T
.consts
= add_constant(T
.consts
, constant
);
743 for (i
= 0; i
< psi_predef_struct_count(); ++i
) {
744 const psi_predef_struct
*pre
= &psi_predef_structs
[i
];
745 decl_args
*dargs
= init_decl_args(NULL
);
746 decl_struct
*dstruct
;
748 for (j
= 0; j
< PSI_PREDEF_STRUCT_MEMBERS
; ++j
) {
749 const psi_predef_struct_member
*member
= &pre
->members
[j
];
758 type
= init_decl_type(member
->type_tag
, member
->type_name
);
759 dvar
= init_decl_var(member
->name
, member
->pointer_level
, member
->array_size
);
760 darg
= init_decl_arg(type
, dvar
);
761 darg
->layout
= init_decl_struct_layout(member
->off
, member
->len
);
762 dargs
= add_decl_arg(dargs
, darg
);
765 dstruct
= init_decl_struct(pre
->name
, dargs
);
766 dstruct
->size
= pre
->size
;
767 T
.structs
= add_decl_struct(T
.structs
, dstruct
);
770 for (i
= 0; i
< psi_predef_type_count(); ++i
) {
771 decl_typedef
*def
= T
.defs
->list
[i
];
773 if (validate_decl_typedef(&T
, def
)) {
774 C
->defs
= add_decl_typedef(C
->defs
, def
);
778 for (i
= 0; i
< psi_predef_const_count(); ++i
) {
779 constant
*constant
= T
.consts
->list
[i
];
781 if (validate_constant(&T
, constant
)) {
782 C
->consts
= add_constant(C
->consts
, constant
);
786 for (i
= 0; i
< psi_predef_struct_count(); ++i
) {
787 decl_struct
*dstruct
= T
.structs
->list
[i
];
789 if (validate_decl_struct(&T
, dstruct
)) {
790 C
->structs
= add_decl_struct(C
->structs
, dstruct
);
795 C
->data
= malloc(sizeof(*C
->data
));
796 PSI_DataExchange(C
->data
, &T
);
801 int PSI_ContextValidate(PSI_Context
*C
, PSI_Parser
*P
)
804 void *dlopened
= NULL
;
805 size_t count
= C
->count
++;
807 C
->data
= realloc(C
->data
, C
->count
* sizeof(*C
->data
));
808 D
= PSI_DataExchange(&C
->data
[count
], PSI_DATA(P
));
813 for (i
= 0; i
< D
->defs
->count
; ++i
) {
814 if (validate_decl_typedef(PSI_DATA(C
), D
->defs
->list
[i
])) {
815 C
->defs
= add_decl_typedef(C
->defs
, D
->defs
->list
[i
]);
822 for (i
= 0; i
< D
->structs
->count
; ++i
) {
823 if (validate_decl_struct(PSI_DATA(C
), D
->structs
->list
[i
])) {
824 C
->structs
= add_decl_struct(C
->structs
, D
->structs
->list
[i
]);
831 for (i
= 0; i
< D
->consts
->count
; ++i
) {
832 if (validate_constant(PSI_DATA(C
), D
->consts
->list
[i
])) {
833 C
->consts
= add_constant(C
->consts
, D
->consts
->list
[i
]);
838 if (!validate_lib(D
, &dlopened
)) {
842 add_decl_lib(&C
->psi
.libs
, dlopened
);
847 for (i
= 0; i
< D
->decls
->count
; ++i
) {
848 if (validate_decl(PSI_DATA(C
), dlopened
, D
->decls
->list
[i
])) {
849 C
->decls
= add_decl(C
->decls
, D
->decls
->list
[i
]);
856 for (i
= 0; i
< D
->impls
->count
; ++i
) {
857 if (validate_impl_stmts(PSI_DATA(C
), D
->impls
->list
[i
])) {
858 C
->impls
= add_impl(C
->impls
, D
->impls
->list
[i
]);
866 static int psi_select_dirent(const struct dirent
*entry
)
869 #define FNM_CASEFOLD 0
871 return 0 == fnmatch("*.psi", entry
->d_name
, FNM_CASEFOLD
);
874 void PSI_ContextBuild(PSI_Context
*C
, const char *paths
)
876 int i
, n
, flags
= getenv("PSI_DEBUG") ? PSI_PARSER_DEBUG
: 0;
877 char *sep
= NULL
, *cpy
= strdup(paths
), *ptr
= cpy
;
878 struct dirent
**entries
= NULL
;
882 sep
= strchr(ptr
, ':');
888 n
= php_scandir(ptr
, &entries
, psi_select_dirent
, alphasort
);
891 for (i
= 0; i
< n
; ++i
) {
892 char psi
[MAXPATHLEN
];
895 if (MAXPATHLEN
<= slprintf(psi
, MAXPATHLEN
, "%s/%s", ptr
, entries
[i
]->d_name
)) {
896 C
->error(PSI_WARNING
, "Path to PSI file too long: %s/%s",
897 ptr
, entries
[i
]->d_name
);
899 if (!PSI_ParserInit(&P
, psi
, C
->error
, flags
)) {
900 C
->error(PSI_WARNING
, "Failed to init PSI parser (%s): %s",
901 psi
, strerror(errno
));
905 while (-1 != PSI_ParserScan(&P
)) {
906 PSI_ParserParse(&P
, PSI_TokenAlloc(&P
));
908 PSI_ParserParse(&P
, NULL
);
909 PSI_ContextValidate(C
, &P
);
915 for (i
= 0; i
< n
; ++i
) {
925 if (PSI_ContextCompile(C
) && SUCCESS
!= zend_register_functions(NULL
, C
->closures
, NULL
, MODULE_PERSISTENT
)) {
926 C
->error(PSI_WARNING
, "Failed to register functions!");
933 zend_function_entry
*PSI_ContextCompile(PSI_Context
*C
)
940 zc
.flags
= CONST_PERSISTENT
|CONST_CS
;
941 zc
.module_number
= EG(current_module
)->module_number
;
943 for (i
= 0; i
< C
->consts
->count
; ++i
) {
944 constant
*c
= C
->consts
->list
[i
];
946 zc
.name
= zend_string_init(c
->name
+ (c
->name
[0] == '\\'), strlen(c
->name
) - (c
->name
[0] == '\\'), 1);
947 ZVAL_NEW_STR(&zc
.value
, zend_string_init(c
->val
->text
, strlen(c
->val
->text
), 1));
949 switch (c
->type
->type
) {
951 convert_to_boolean(&zc
.value
);
954 convert_to_long(&zc
.value
);
957 convert_to_double(&zc
.value
);
960 zend_register_constant(&zc
);
964 return C
->closures
= C
->ops
->compile(C
);
968 void PSI_ContextCall(PSI_Context
*C
, impl_val
*ret_val
, decl
*decl
)
970 C
->ops
->call(C
, ret_val
, decl
);
973 static inline void dump_decl_type(int fd
, decl_type
*t
) {
983 dprintf(fd
, "%s%s", pre
, t
->name
);
985 static inline void dump_decl_var(int fd
, decl_var
*v
) {
986 dprintf(fd
, "%.*s%s", v
->pointer_level
-!!v
->array_size
, "**********", v
->name
);
988 dprintf(fd
, "[%u]", v
->array_size
);
991 static inline void dump_decl_arg(int fd
, decl_arg
*a
) {
992 dump_decl_type(fd
, a
->type
);
994 dump_decl_var(fd
, a
->var
);
996 void PSI_ContextDump(PSI_Context
*C
, int fd
)
1001 if (C
->ops
== PSI_Libjit()) {
1002 dprintf(fd
, "#PSI(libjit)\n");
1006 if (C
->ops
== PSI_Libffi()) {
1007 dprintf(fd
, "#PSI(libffi)\n");
1011 if (C
->defs
) for (i
= 0; i
< C
->defs
->count
; ++i
) {
1012 decl_typedef
*tdef
= C
->defs
->list
[i
];
1014 dprintf(fd
, "typedef ");
1015 dump_decl_type(fd
, tdef
->type
);
1016 dprintf(fd
, " %s;\n", tdef
->alias
);
1018 if (C
->structs
) for (i
= 0; i
< C
->structs
->count
; ++i
) {
1019 decl_struct
*strct
= C
->structs
->list
[i
];
1020 decl_arg
*sarg
= NULL
;
1022 dprintf(fd
, "struct %s::(%zu) {\n", strct
->name
, strct
->size
);
1023 for (j
= 0; j
< strct
->args
->count
; ++j
) {
1024 sarg
= strct
->args
->args
[j
];
1026 dump_decl_arg(fd
, sarg
);
1027 dprintf(fd
, "::(%zu, %zu);\n", sarg
->layout
->pos
, sarg
->layout
->len
);
1035 void PSI_ContextDtor(PSI_Context
*C
)
1038 zend_function_entry
*zfe
;
1044 free_decl_libs(&C
->psi
.libs
);
1047 for (i
= 0; i
< C
->count
; ++i
) {
1048 PSI_DataDtor(&C
->data
[i
]);
1054 for (zfe
= C
->closures
; zfe
->fname
; ++zfe
) {
1055 free((void *) zfe
->arg_info
);
1061 if (C
->consts
->list
) {
1062 free(C
->consts
->list
);
1067 if (C
->defs
->list
) {
1068 free(C
->defs
->list
);
1073 if (C
->structs
->list
) {
1074 free(C
->structs
->list
);
1079 if (C
->decls
->list
) {
1080 free(C
->decls
->list
);
1085 if (C
->impls
->list
) {
1086 free(C
->impls
->list
);
1091 memset(C
, 0, sizeof(*C
));
1094 void PSI_ContextFree(PSI_Context
**C
)
1097 PSI_ContextDtor(*C
);