])
psi_type_pair() { # (type, size)
- local psi_type_lower=`tr A-Z a-z <<<$1`
+ local psi_type_name=`tr -cd A-Za-z <<<$1`
+ local psi_type_lower=`tr A-Z a-z <<<$psi_type_name`
case $psi_type_lower in
int*|uint*)
local psi_type_upper=`tr a-z A-Z <<<$1`
echo "PSI_T_STRUCT, \"$2\""
;;
*)
- echo "PSI_T_NAME, \"$1\""
+ echo "PSI_T_NAME, \"$psi_type_name\""
;;
esac
}
AC_DEFINE_UNQUOTED(
AS_TR_CPP(offsetof_$1_$2),
$AS_TR_SH([ac_cv_offsetof_$1_$2]),
- [The offset of `$1' in `$2', as computed by offsetof.]
+ [The offset of `$2' in `$1', as computed by offsetof.]
)
])
PSI_STRUCTS=
AC_DEFUN(PSI_STRUCT, [
AC_CHECK_SIZEOF(struct $1, [], PSI_INCLUDES_DEFAULT($4))
+ psi_struct_size=$ac_cv_sizeof_struct_$1
psi_struct_members=
m4_foreach(member, [$2], [
AC_CHECK_MEMBER(struct $1.member, [
- case member in
- $3
- *) psi_member_type=int ;;
- esac
+ psi_member_name=member
AC_CHECK_SIZEOF(struct_$1[_]member, [], PSI_INCLUDES_DEFAULT($4,
[#define struct_$1_]member ((struct $1 *)0)->member
))
+ psi_member_size=$ac_cv_sizeof_struct_$1[]_[]member
PSI_CHECK_OFFSETOF(struct $1, member, PSI_INCLUDES_DEFAULT($4))
+ psi_member_offset=$ac_cv_offsetof_struct_$1[]_[]member
+ # type
+ case member in
+ $3
+ *) psi_member_type=int ;;
+ esac
# pointer level
psi_struct_member_pl=`echo $psi_member_type | tr -cd '*' | wc -c`
# array size
- psi_struct_member_as=`echo $psi_member_type | $AWK -F'\x5b\x5d\x5b\x5d' 'END {print 0} /\\x5b\x5b\x5b:digit:\x5d\x5d+\\x5d/ {print$[]2; exit}'`
+ psi_struct_member_as=`echo $psi_member_type | $AWK -F'\x5b\x5d\x5b\x5d' 'END {if(!found)print 0} /\\x5b\x5b\x5b:digit:\x5d\x5d+\\x5d/ {found=1; print$[]2}'`
if test $psi_struct_member_as -gt 0
then
psi_struct_member_pl=`expr $psi_struct_member_pl + 1`
fi
- psi_struct_member="{`psi_type_pair $psi_member_type $ac_cv_sizeof_struct_$1[]_[]member`, \"[]member[]\", $ac_cv_offsetof_struct_$1[]_[]member, $ac_cv_sizeof_struct_$1[]_[]member, $psi_struct_member_pl, $psi_struct_member_as}"
+ psi_struct_member="{`psi_type_pair $psi_member_type $psi_member_size`, \"$psi_member_name\", $psi_member_offset, $psi_member_size, $psi_struct_member_pl, $psi_struct_member_as}"
if test "$psi_struct_members"
then
psi_struct_members="$psi_struct_members, $psi_struct_member"
fi
], [], PSI_INCLUDES_DEFAULT($4))
])
- PSI_STRUCTS="{\"$1\", $ac_cv_sizeof_struct_$1, {$psi_struct_members}}, $PSI_STRUCTS"
+ PSI_STRUCTS="{\"$1\", $psi_struct_size, {$psi_struct_members}}, $PSI_STRUCTS"
])
AC_TYPE_INT8_T
PSI_TYPE(time_t, int)
PSI_TYPE(timer_t, int)
PSI_TYPE(uid_t)
+ dnl sys/utsname.h
+ PSI_STRUCT(utsname, [
+ [sysname],
+ [nodename],
+ [release],
+ [version],
+ [machine],
+ [domainname]], [
+ *) psi_member_type="char@<:@$psi_member_size@:>@" ;;
+ ], sys/utsname.h)
dnl time.h
PSI_STRUCT(tm, [
[tm_sec],
zend_internal_arg_info *psi_internal_arginfo(impl *impl);
size_t psi_num_min_args(impl *impl);
+void psi_to_bool(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
void psi_to_int(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
void psi_to_double(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
void psi_to_string(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
+void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl);
void *psi_do_let(decl_arg *darg);
-void psi_do_set(zval *return_value, set_func *func, decl_vars *vars);
-void psi_do_return(impl *impl, impl_val *ret_val, zval *return_value);
+void psi_do_set(zval *return_value, set_value *set);
+void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val);
void psi_do_free(free_stmt *fre);
void psi_do_clean(impl *impl);
}
return 1;
}
-static inline int validate_set_value(PSI_Data *data, set_value *set) {
- set->
+
+static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) {
+ size_t i;
+
+ ZEND_ASSERT(s);
+ for (i = 0; i < s->args->count; ++i) {
+ decl_arg *darg = s->args->args[i];
+
+ if (!strcmp(var->name, darg->var->name)) {
+ return darg;
+ }
+ }
+
+ return NULL;
+}
+static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *ref) {
+ size_t i;
+
+ switch (set->func->type) {
+ case PSI_T_TO_BOOL:
+ set->func->handler = psi_to_bool;
+ break;
+ case PSI_T_TO_INT:
+ set->func->handler = psi_to_int;
+ break;
+ case PSI_T_TO_FLOAT:
+ set->func->handler = psi_to_double;
+ break;
+ case PSI_T_TO_STRING:
+ set->func->handler = psi_to_string;
+ break;
+ case PSI_T_TO_ARRAY:
+ set->func->handler = psi_to_array;
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+
+ if (strcmp(set->vars->vars[0]->name, ref->var->name)) {
+ return 0;
+ }
+
+ if (set->count && (set->func->type != PSI_T_TO_ARRAY || real_decl_type(ref->type)->type != PSI_T_STRUCT)) {
+ data->error(E_WARNING, "Inner `set` statement casts only work with to_array() casts on structs");
+ return 0;
+ }
+ for (i = 0; i < set->count; ++i) {
+ decl_arg *sub_ref = locate_struct_member(real_decl_type(ref->type)->strct, set->inner[i]->vars->vars[0]);
+
+ if (!sub_ref) {
+ return 0;
+ }
+ if (!validate_set_value(data, set->inner[i], sub_ref)) {
+ return 0;
+ }
+ }
+
+ return 1;
}
static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
size_t i;
for (i = 0; i < decls->count; ++i) {
- if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
- ret->decl->arg = decls->list[i]->func;
+ if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) {
+ ret->decl = decls->list[i]->func;
return decls->list[i];
}
}
return NULL;
}
static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
+ return_stmt *ret;
+
/* we must have exactly one ret stmt delcaring the native func to call */
/* and which type cast to apply */
if (impl->stmts->ret.count != 1) {
}
return 0;
}
- if (!validate_impl_set_value(data, impl->stmts->ret.list[0]->set)) {
- return 0;
- }
- if (!(impl->decl = locate_impl_decl(data->decls, impl->stmts->ret.list[0]))) {
+
+ ret = impl->stmts->ret.list[0];
+
+ if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
data->error(PSI_WARNING, "Missing declaration for implementation %s",
impl->func->name);
return 0;
}
+ if (!validate_set_value(data, ret->set, ret->decl)) {
+ return 0;
+ }
return 1;
}
if (!strcmp(set_var->name, set_arg->var->name)) {
check = 1;
+ if (!validate_set_value(data, set->val, set_arg)) {
+ return 0;
+ }
set_var->arg = set_arg;
break;
}
ffi_call(&data->signature, FFI_FN(data->impl->decl->dlptr), &ret_val, arg_prm);
- psi_do_return(data->impl->stmts->ret.list[0], &ret_val, *(zval **)_args[1]);
+ psi_do_return(*(zval **)_args[1], data->impl->stmts->ret.list[0], &ret_val);
for (i = 0; i < data->impl->stmts->set.count; ++i) {
set_stmt *set = data->impl->stmts->set.list[i];
jit_apply(data->signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val);
- psi_do_return(data->impl->stmts->ret.list[0], &ret_val, *(zval **)_args[1]);
+ psi_do_return(*(zval **)_args[1], data->impl->stmts->ret.list[0], &ret_val);
for (i = 0; i < data->impl->stmts->set.count; ++i) {
set_stmt *set = data->impl->stmts->set.list[i];
return n;
}
+void psi_to_bool(zval *return_value, token_t t, impl_val *ret_val, decl_var *var)
+{
+ switch (t) {
+ case PSI_T_FLOAT:
+ RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval);
+ convert_to_boolean(return_value);
+ break;
+ case PSI_T_DOUBLE:
+ RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval);
+ convert_to_boolean(return_value);
+ break;
+ default:
+ RETVAL_LONG(deref_impl_val(ret_val, var)->lval);
+ convert_to_boolean(return_value);
+ break;
+ }
+}
+
void psi_to_int(zval *return_value, token_t t, impl_val *ret_val, decl_var *var)
{
switch (t) {
void psi_do_set(zval *return_value, set_value *set)
{
impl_val *val = (impl_val *) &set->vars->vars[0]->arg->let->ptr;
+ token_t t = real_decl_type(set->vars->vars[0]->arg->type)->type;
ZVAL_DEREF(return_value);
zval_dtor(return_value);
- switch (func->type) {
- case PSI_T_TO_STRING:
- psi_to_string(return_value, real_decl_type(vars->vars[0]->arg->type)->type, val, vars->vars[0]);
- break;
- case PSI_T_TO_ARRAY:
- psi_to_array(return_value, real_decl_type(vars->vars[0]->arg->type)->type, val, vars->vars[0]);
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
+ set->func->handler(return_value, t, val, set->vars->vars[0]);
}
-void psi_do_return(return_stmt *ret, impl_val *ret_val, zval *return_value)
+void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val)
{
- switch (ret->func->type) {
- case PSI_T_TO_STRING:
- psi_to_string(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, ret->decl);
- break;
- case PSI_T_TO_INT:
- psi_to_int(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, ret->decl);
- break;
- case PSI_T_TO_ARRAY:
- psi_to_array(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, ret->decl);
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
+ token_t t = real_decl_type(ret->decl->type)->type;
+
+ ret->set->func->handler(return_value, t, ret_val, ret->decl->var);
}
void psi_do_free(free_stmt *fre)
typedef struct set_func {
token_t type;
char *name;
+ void (*handler)(zval *, token_t, impl_val *, decl_var *);
} set_func;
static inline set_func *init_set_func(token_t type, const char *name) {
typedef struct return_stmt {
set_value *set;
- decl_var *decl;
+ decl_arg *decl;
} return_stmt;
static inline return_stmt *init_return_stmt(set_value *val) {
return_stmt *ret = calloc(1, sizeof(*ret));
ret->set = val;
- ret->decl = val->vars->vars[0];
return ret;
}