From: Michael Wallner Date: Wed, 11 Nov 2015 18:35:10 +0000 (+0100) Subject: flush X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=commitdiff_plain;h=e32a2cebb5fef59de8c202fc2ff936b51945744a flush --- diff --git a/config.m4 b/config.m4 index 6854fd2..647b0a9 100644 --- a/config.m4 +++ b/config.m4 @@ -92,7 +92,8 @@ if test "$PHP_PSI" != "no"; then ]) 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` @@ -103,7 +104,7 @@ if test "$PHP_PSI" != "no"; then echo "PSI_T_STRUCT, \"$2\"" ;; *) - echo "PSI_T_NAME, \"$1\"" + echo "PSI_T_NAME, \"$psi_type_name\"" ;; esac } @@ -192,7 +193,7 @@ if test "$PHP_PSI" != "no"; then 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.] ) ]) @@ -200,26 +201,31 @@ if test "$PHP_PSI" != "no"; then 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" @@ -228,7 +234,7 @@ if test "$PHP_PSI" != "no"; then 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 @@ -447,6 +453,16 @@ if test "$PHP_PSI" != "no"; then 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], diff --git a/php_psi.h b/php_psi.h index f9e89b7..d387a06 100644 --- a/php_psi.h +++ b/php_psi.h @@ -32,14 +32,16 @@ int psi_internal_type(impl_type *type); 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); diff --git a/src/context.c b/src/context.c index 35cedee..3ff510f 100644 --- a/src/context.c +++ b/src/context.c @@ -254,21 +254,78 @@ static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) { } 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) { @@ -282,14 +339,17 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) { } 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; } @@ -383,6 +443,9 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { 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; } diff --git a/src/libffi.c b/src/libffi.c index e50ca0f..34a1598 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -224,7 +224,7 @@ static void psi_ffi_handler(ffi_cif *_sig, void *_result, void **_args, void *_d 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]; diff --git a/src/libjit.c b/src/libjit.c index ee9b1f3..f4f57c5 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -163,7 +163,7 @@ static void psi_jit_handler(jit_type_t _sig, void *result, void **_args, void *_ 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]; diff --git a/src/module.c b/src/module.c index a883e62..eec8611 100644 --- a/src/module.c +++ b/src/module.c @@ -93,6 +93,24 @@ size_t psi_num_min_args(impl *impl) 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) { @@ -550,35 +568,19 @@ void *psi_do_let(decl_arg *darg) 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) diff --git a/src/parser.h b/src/parser.h index 84de6e8..a9060bd 100644 --- a/src/parser.h +++ b/src/parser.h @@ -573,6 +573,7 @@ static inline void free_let_stmt(let_stmt *stmt) { 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) { @@ -639,13 +640,12 @@ static inline void free_set_stmt(set_stmt *set) { 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; }