php_psi_structs.h
php_psi_types.h
php_psi_va_decls.h
+php_psi_fn_decls.h
/tmp/
*.loT
php_psi_unions.h
PSI_MACROS=$PHP_PSI_SRCDIR/php_psi_macros.h
PSI_DECLS=$PHP_PSI_SRCDIR/php_psi_decls.h
PSI_VA_DECLS=$PHP_PSI_SRCDIR/php_psi_va_decls.h
+PSI_FN_DECLS=$PHP_PSI_SRCDIR/php_psi_fn_decls.h
dnl PSI_CONFIG_INIT()
dnl Creates stubs of the headers with pre-defined types etc.
dnl These headers are included by src/context.c.
dnl This macro must be called prior any checks for a type, struct, decl etc.
AC_DEFUN(PSI_CONFIG_INIT, [
- for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_MACROS $PSI_DECLS $PSI_VA_DECLS; do
+ for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_MACROS $PSI_DECLS $PSI_VA_DECLS $PSI_FN_DECLS; do
cat >$i <<EOF
/* generated by configure */
#include "php_psi_stdinc.h"
EOF
cat >>$PSI_VA_DECLS <<EOF
static struct psi_predef_decl psi_predef_vararg_decls@<:@@:>@ = {
+EOF
+ cat >>$PSI_FN_DECLS <<EOF
+static struct psi_predef_decl psi_predef_functor_decls@<:@@:>@ = {
EOF
])
PSI_INCLUDES
#endif
EOF
- for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS; do
+ for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS $PSI_FN_DECLS; do
cat >>$i <<EOF
{0}
};
# Add a pre-defined decl to $PSI_VA_DECLS/$PSI_DECLS.
psi_add_decl() {
case "$2" in
+ *functor*)
+ cat >>$PSI_FN_DECLS <<EOF
+ $1, {0},
+EOF
+ ;;
*vararg*)
cat >>$PSI_VA_DECLS <<EOF
$1, {0},
esac
}
+dnl PSI_DECL_TYPE(type functor_name, args)
+dnl Adds a pre-defined functor decl to $PSI_FN_DECLS.
+AC_DEFUN(PSI_DECL_TYPE, [
+ PSI_DECL_ARGS($1, $2)
+ psi_add_decl "$psi_decl_args" functor
+])
dnl PSI_REDIR(name, custom symbol)
dnl Create a function redirection to an optional custom symbol.
AC_DEFUN(PSI_REDIR, [
fi
])
+dnl PSI_FUNCTOR_TYPE(type functor_name, args)
+dnl Forwards to PSI_DECL_TYPE.
+AC_DEFUN(PSI_FUNCTOR_TYPE, [
+ dnl psi_add_type "{PSI_T_POINTER, \"void\", \"PSI_VAR_NAME($1)\"}"
+ AS_TR_SH([ac_cv_sizeof_]PSI_VAR_NAME($1))=PSI_SH_SIZEOF(void *)
+ PSI_DECL_TYPE([$1], [$2])
+])
+
dnl PSI_VAR_TYPE(decl arg)
dnl Extracts the type of a decl arg, e.g. dnl unsigned char* buf[16] -> unsigned char*.
AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [^\(const \)?\(.*\) \([*]*\)[^ ]+$], [\2\3])])
int ss_flags]
)
+ PSI_FUNCTOR_TYPE(void sa_handler, [(int signo)])
+ PSI_FUNCTOR_TYPE(void sa_sigaction, [(int signo, siginfo_t *info, void *context)])
+
PSI_STRUCT(struct sigaction, [
- void *sa_handler,
+ sa_handler sa_handler,
sigset_t sa_mask,
int sa_flags,
- void *sa_sigaction]
+ sa_sigaction sa_sigaction]
)
PSI_STRUCT(ucontext_t, [
#include "php_psi_consts.h"
#include "php_psi_decls.h"
#include "php_psi_va_decls.h"
+#include "php_psi_fn_decls.h"
#include "php_psi_structs.h"
#include "php_psi_unions.h"
predef_decl = farg;
}
+ for (predef_decl = &psi_predef_functor_decls[0]; predef_decl->type_tag; ++predef_decl) {
+ struct psi_predef_decl *farg;
+ decl_type *dtype, *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name);
+ decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size);
+ decl_arg *tdef, *func = init_decl_arg(ftype, fname);
+ decl_args *args = init_decl_args(NULL);
+ decl *decl = init_decl(init_decl_abi("default"), func, args);
+
+ for (farg = &predef_decl[1]; farg->type_tag; ++farg) {
+ decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name);
+ decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size);
+ decl_arg *darg = init_decl_arg(arg_type, arg_var);
+ args = add_decl_arg(args, darg);
+ }
+
+ dtype = init_decl_type(PSI_T_FUNCTION, fname->name);
+ dtype->real.func = decl;
+ tdef = init_decl_arg(dtype, copy_decl_var(fname));
+ T.defs = add_decl_typedef(T.defs, tdef);
+
+ predef_decl = farg;
+ }
+
psi_context_validate_data(PSI_DATA(C), &T);
C->count = 1;
func->return_type->name);
}
-static inline void dump_impl_let_stmt(int fd, let_stmt *let) {
- dprintf(fd, "\tlet %s", let->var->name);
- if (let->val) {
- dprintf(fd, " = %s", let->val->flags.one.is_reference ? "&" : "");
- switch (let->val->kind) {
- case PSI_LET_NULL:
- dprintf(fd, "NULL");
- break;
- case PSI_LET_TMP:
- dump_decl_var(fd, let->val->data.var);
- break;
- case PSI_LET_CALLOC:
- dprintf(fd, "calloc(");
- dump_num_exp(fd, let->val->data.alloc->nmemb);
- dprintf(fd, ", ");
- dump_num_exp(fd, let->val->data.alloc->size);
- dprintf(fd, ")");
- break;
- case PSI_LET_CALLBACK:
- dprintf(fd, "callback %s(%s(", let->val->data.callback->func->name,
- let->val->data.callback->func->var->name);
- if (let->val->data.callback->args) {
- size_t i, c = let->val->data.callback->args->count;
-
- dprintf(fd, "\n");
- for (i = 0; i < c; ++i) {
- set_value *set = let->val->data.callback->args->vals[i];
- dump_impl_set_value(fd, set, 2, i + 1 == c);
- }
- dprintf(fd, "\t");
+static inline void dump_impl_let_func(int fd, let_func *func, unsigned level);
+
+static inline void dump_impl_let_val(int fd, let_val *val, unsigned level, int last) {
+ if (level > 1) {
+ /* only if not directly after `set ...` */
+ dump_level(fd, level);
+ }
+
+ dprintf(fd, "%s", val->flags.one.is_reference ? "&" : "");
+ switch (val->kind) {
+ case PSI_LET_NULL:
+ dprintf(fd, "NULL");
+ break;
+ case PSI_LET_TMP:
+ dump_decl_var(fd, val->data.var);
+ break;
+ case PSI_LET_CALLOC:
+ dprintf(fd, "calloc(");
+ dump_num_exp(fd, val->data.alloc->nmemb);
+ dprintf(fd, ", ");
+ dump_num_exp(fd, val->data.alloc->size);
+ dprintf(fd, ")");
+ break;
+ case PSI_LET_CALLBACK:
+ dprintf(fd, "callback %s(%s(", val->data.callback->func->name,
+ val->data.callback->func->var->name);
+ if (val->data.callback->args) {
+ size_t i, c = val->data.callback->args->count;
+
+ dprintf(fd, "\n");
+ for (i = 0; i < c; ++i) {
+ set_value *set = val->data.callback->args->vals[i];
+ ++level;
+ dump_impl_set_value(fd, set, level, i + 1 == c);
+ --level;
}
- dprintf(fd, "));");
- break;
- case PSI_LET_FUNC:
- dprintf(fd, "%s(%s)", let->val->data.func->name,
- let->val->data.func->var->name);
- break;
- case PSI_LET_NUMEXP:
- dump_num_exp(fd, let->val->data.num);
- break;
+ dump_level(fd, level);
+ }
+ dprintf(fd, "))");
+ break;
+ case PSI_LET_FUNC:
+ dump_impl_let_func(fd, val->data.func, level);
+ break;
+ case PSI_LET_NUMEXP:
+ dump_num_exp(fd, val->data.num);
+ break;
- EMPTY_SWITCH_DEFAULT_CASE();
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+ if (level > 1) {
+ if (!last) {
+ dprintf(fd, ",");
}
+ } else {
dprintf(fd, ";");
}
}
+static inline void dump_impl_let_func(int fd, let_func *func, unsigned level) {
+ dprintf(fd, "%s(%s", func->name,
+ func->var->name);
+ if (func->inner) {
+ size_t i;
+
+ dprintf(fd, ",");
+ ++level;
+ for (i = 0; i < func->inner->count; ++i) {
+ dprintf(fd, "\n");
+ dump_impl_let_val(fd, func->inner->vals[i], level, i+1 == func->inner->count);
+ }
+ --level;
+ dprintf(fd, "\n");
+ dump_level(fd, level);
+ }
+ dprintf(fd, ")");
+}
+static inline void dump_impl_let_stmt(int fd, let_stmt *let) {
+ dprintf(fd, "\tlet %s", let->var->name);
+ if (let->val) {
+ dprintf(fd, " = ");
+ dump_impl_let_val(fd, let->val, 1, 1);
+ }
+}
+
static inline void dump_impl_return_stmt(int fd, return_stmt *ret) {
dprintf(fd, "\treturn ");
dump_impl_set_value(fd, ret->set, 1, 0);
return mem;
}
-static inline impl_val *psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free)
-{
- abort();
- return arg_val;
-}
-
static inline impl_val *psi_let_func(let_func *func, decl_arg *darg) {
return darg->ptr = func->handler(darg->ptr, darg->type, func->var->arg, &darg->mem);
}
while (*ptr) {
efree(*ptr++);
}
+ } else if (type->type == PSI_T_STRUCT) {
+ void **ptr = (void **) ((char *) darg->mem + type->real.unn->size);
+
+ if (*ptr) {
+ efree(*ptr);
+ }
}
}
}
case PSI_T_STRUCT:
impl->decl->func->ptr = psi_array_to_struct(real->real.strct, NULL);
break;
+ case PSI_T_UNION:
+ impl->decl->func->ptr = psi_array_to_union(real->real.unn, NULL);
+ break;
}
}
}
decl_type *type = real_decl_type(spec->type);
switch (type->type) {
+ case PSI_T_FUNCTION:
+ break;
case PSI_T_FLOAT:
mem->fval = (float) zval_get_double(zv);
break;
return mem;
}
+void *psi_array_to_union(decl_union *u, HashTable *arr) {
+ size_t i;
+ char *mem = ecalloc(1, u->size + sizeof(void *));
+
+ if (arr) for (i = 0; i < u->args->count; ++i) {
+ decl_arg *darg = u->args->args[i];
+ zval *entry = zend_hash_str_find_ind(arr, darg->var->name, strlen(darg->var->name));
+
+ if (entry) {
+ impl_val val;
+ void *tmp = NULL;
+
+ memset(&tmp, 0, sizeof(tmp));
+ psi_from_zval(&val, darg, entry, &tmp);
+ memcpy(mem, &val, darg->layout->len);
+ if (tmp) {
+ ((void **)(mem + u->size))[0] = tmp;
+ }
+ /* first found entry wins */
+ break;
+ }
+ }
+
+ return mem;
+}
+
void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val)
{
set->outer.set->func->handler(return_value, set, r_val);
case PSI_T_STRUCT:
*to_free = tmp = psi_array_to_struct(real->real.strct, arr);
break;
+ case PSI_T_UNION:
+ *to_free = tmp = psi_array_to_union(real->real.unn, arr);
+ break;
EMPTY_SWITCH_DEFAULT_CASE();
}
void psi_to_object(zval *return_value, set_value *set, impl_val *ret_val);
void psi_to_zval(zval *return_value, set_value *set, impl_val *ret_val);
+void *psi_array_to_union(decl_union *u, HashTable *arr);
void *psi_array_to_struct(decl_struct *s, HashTable *arr);
void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp);