X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmodule.c;h=4a5aa3e0df9516ce943e1231fa896af6a0d6e7e6;hb=58066949f02dbdbc3ba7b3fa3a0e01836fa72663;hp=da623b2c16ee78b772c1dfd85daceb22651ddf95;hpb=2421d323be79e4a811a4197914330a8c0124b130;p=m6w6%2Fext-psi diff --git a/src/module.c b/src/module.c index da623b2..4a5aa3e 100644 --- a/src/module.c +++ b/src/module.c @@ -7,6 +7,8 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "zend_exceptions.h" +#include "zend_constants.h" +#include "zend_operators.h" #include "php_psi.h" #include "parser.h" @@ -357,16 +359,6 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) return mem; } -static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) { - void *ptr = (char *) struct_ptr->ptr + set_arg->layout->pos; - impl_val *val = enref_impl_val(ptr, set_arg->var); - - if (val != ptr) { - *to_free = val; - } - - return val; -} void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) { size_t i; @@ -429,12 +421,12 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) } else if (set->vars->count > 1) { /* to_array(arr_var, cnt_var[, cnt_var...], to_int(*arr_var)) * check for length in second var - */ + * / size_t count = 0; zval ele; if (set->outer.set) { - /* struct */ + /* struct *//* for (i = 1; i < set->vars->count; ++i) { impl_val *tmp = NULL, *cnt_val; decl_var *cnt_var = set->vars->vars[i]; @@ -454,6 +446,20 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val) size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t); impl_val *ptr = iterate(ret_val, size, i, &tmp); + set->inner[0]->func->handler(&ele, set->inner[0], ptr); + add_next_index_zval(return_value, &ele); + } + */ + } else if (set->num) { + /* to_array(arr_var, num_expr, to_int(*arr_var)) + */ + zval ele; + zend_long i, n = psi_long_num_exp(set->num, r_val); + + for (i = 0; i < n; ++i) { + size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t); + impl_val *ptr = iterate(ret_val, size, i, &tmp); + set->inner[0]->func->handler(&ele, set->inner[0], ptr); add_next_index_zval(return_value, &ele); } @@ -550,17 +556,10 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i static inline void *psi_do_calloc(let_calloc *alloc) { - decl_type *type = real_decl_type(alloc->type); - size_t size; - - if (type->type == PSI_T_STRUCT) { - /* psi_do_clean expects at least one NULL pointer after the struct */ - size = type->strct->size + sizeof(void *); - } else { - size = psi_t_size(type->type); - } - - return ecalloc(alloc->n, size); + zend_long n = psi_long_num_exp(alloc->nmemb, NULL), s = psi_long_num_exp(alloc->size, NULL); + void *mem = safe_emalloc(n, s, sizeof(void *)); + memset(mem, 0, n * s + sizeof(void *)); + return mem; } static inline void *psi_do_let(decl_arg *darg) @@ -734,6 +733,221 @@ static inline void psi_do_clean(impl *impl) } } +static inline int psi_calc_num_exp_value(num_exp *exp, impl_val *ref, impl_val *res) { + impl_val *tmp = NULL; + + switch (exp->t) { + case PSI_T_NUMBER: + switch (is_numeric_string(exp->u.numb, strlen(exp->u.numb), (zend_long *) res, (double *) res, 0)) { + case IS_LONG: + return PSI_T_INT64; + case IS_DOUBLE: + return PSI_T_DOUBLE; + } + break; + + case PSI_T_NSNAME: + switch (exp->u.cnst->type->type) { + case PSI_T_INT: + res->i64 = zend_get_constant_str(exp->u.cnst->name, strlen(exp->u.cnst->name))->value.lval; + return PSI_T_INT64; + case PSI_T_FLOAT: + res->dval = zend_get_constant_str(exp->u.cnst->name, strlen(exp->u.cnst->name))->value.dval; + return PSI_T_DOUBLE; + default: + return 0; + } + break; + + case PSI_T_NAME: + if (exp->u.dvar->arg->let) { + ref = exp->u.dvar->arg->let->ptr; + } else { + ref = struct_member_ref(exp->u.dvar->arg, ref, &tmp); + } + switch (real_decl_type(exp->u.dvar->arg->type)->type) { + case PSI_T_INT8: + case PSI_T_UINT8: + case PSI_T_INT16: + case PSI_T_UINT16: + case PSI_T_INT32: + case PSI_T_UINT32: + case PSI_T_INT64: + case PSI_T_UINT64: + memcpy(res, deref_impl_val(ref, exp->u.dvar), sizeof(*res)); + if (tmp) { + free(tmp); + } + return real_decl_type(exp->u.dvar->arg->type)->type; + + case PSI_T_FLOAT: + case PSI_T_DOUBLE: + memcpy(res, deref_impl_val(ref, exp->u.dvar), sizeof(*res)); + if (tmp) { + free(tmp); + } + return real_decl_type(exp->u.dvar->arg->type)->type; + + EMPTY_SWITCH_DEFAULT_CASE(); + } + break; + + EMPTY_SWITCH_DEFAULT_CASE(); + } + return 0; +} + +int psi_calc_num_exp(num_exp *exp, impl_val *ref, impl_val *res) { + impl_val num = {0}; + int num_type = psi_calc_num_exp_value(exp, ref, &num); + + if (exp->operand) { + impl_val tmp = {0}; + int tmp_type = psi_calc_num_exp(exp->operand, ref, &tmp); + + return exp->calculator(num_type, &num, tmp_type, &tmp, res); + } + + memcpy(res, &num, sizeof(*res)); + return num_type; +} + +#define PSI_CALC_OP(var) res->var = PSI_CALC(v1->var, v2->var) +#define PSI_CALC_OP2(vres, var1, var2) res->vres = PSI_CALC(v1->var1, v2->var2) +#define PSI_CALC_FN(op) int psi_calc_##op(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res) \ +{ \ + if (t1 == t2) { \ + switch (t1) { \ + case PSI_T_FLOAT: PSI_CALC_OP(fval); break; \ + case PSI_T_DOUBLE: PSI_CALC_OP(dval); break; \ + case PSI_T_INT8: PSI_CALC_OP(i8); break; \ + case PSI_T_UINT8: PSI_CALC_OP(u8); break; \ + case PSI_T_INT16: PSI_CALC_OP(i16); break; \ + case PSI_T_UINT16: PSI_CALC_OP(u16); break; \ + case PSI_T_INT32: PSI_CALC_OP(i32); break; \ + case PSI_T_UINT32: PSI_CALC_OP(u32); break; \ + case PSI_T_INT64: PSI_CALC_OP(i64); break; \ + case PSI_T_UINT64: PSI_CALC_OP(u64); break; \ + EMPTY_SWITCH_DEFAULT_CASE(); \ + } \ + return t1; \ + } else if (t1 == PSI_T_DOUBLE) { \ + switch (t2) { \ + case PSI_T_FLOAT: PSI_CALC_OP2(dval, dval, fval); break; \ + case PSI_T_INT8: PSI_CALC_OP2(dval, dval, i8); break; \ + case PSI_T_UINT8: PSI_CALC_OP2(dval, dval, u8); break; \ + case PSI_T_INT16: PSI_CALC_OP2(dval, dval, i16); break; \ + case PSI_T_UINT16: PSI_CALC_OP2(dval, dval, u16); break; \ + case PSI_T_INT32: PSI_CALC_OP2(dval, dval, i32); break; \ + case PSI_T_UINT32: PSI_CALC_OP2(dval, dval, u32); break; \ + case PSI_T_INT64: PSI_CALC_OP2(dval, dval, i64); break; \ + case PSI_T_UINT64: PSI_CALC_OP2(dval, dval, u64); break; \ + EMPTY_SWITCH_DEFAULT_CASE(); \ + } \ + return t1; \ + } else if (t2 == PSI_T_DOUBLE) { \ + switch (t1) { \ + case PSI_T_FLOAT: PSI_CALC_OP2(dval, fval, dval); break; \ + case PSI_T_INT8: PSI_CALC_OP2(dval, i8, dval); break; \ + case PSI_T_UINT8: PSI_CALC_OP2(dval, u8, dval); break; \ + case PSI_T_INT16: PSI_CALC_OP2(dval, i16, dval); break; \ + case PSI_T_UINT16: PSI_CALC_OP2(dval, u16, dval); break; \ + case PSI_T_INT32: PSI_CALC_OP2(dval, i32, dval); break; \ + case PSI_T_UINT32: PSI_CALC_OP2(dval, u32, dval); break; \ + case PSI_T_INT64: PSI_CALC_OP2(dval, i64, dval); break; \ + case PSI_T_UINT64: PSI_CALC_OP2(dval, u64, dval); break; \ + EMPTY_SWITCH_DEFAULT_CASE(); \ + } \ + return t2; \ + } else if (t1 == PSI_T_FLOAT) { \ + switch (t2) { \ + case PSI_T_DOUBLE: PSI_CALC_OP2(dval, fval, dval); return t2; \ + case PSI_T_INT8: PSI_CALC_OP2(fval, fval, i8); break; \ + case PSI_T_UINT8: PSI_CALC_OP2(fval, fval, u8); break; \ + case PSI_T_INT16: PSI_CALC_OP2(fval, fval, i16); break; \ + case PSI_T_UINT16: PSI_CALC_OP2(fval, fval, u16); break; \ + case PSI_T_INT32: PSI_CALC_OP2(fval, fval, i32); break; \ + case PSI_T_UINT32: PSI_CALC_OP2(fval, fval, u32); break; \ + case PSI_T_INT64: PSI_CALC_OP2(fval, fval, i64); break; \ + case PSI_T_UINT64: PSI_CALC_OP2(fval, fval, u64); break; \ + EMPTY_SWITCH_DEFAULT_CASE(); \ + } \ + return t1; \ + } else if (t2 == PSI_T_FLOAT) { \ + switch (t1) { \ + case PSI_T_DOUBLE: PSI_CALC_OP2(dval, dval, fval); return t1; \ + case PSI_T_INT8: PSI_CALC_OP2(fval, i8, fval); break; \ + case PSI_T_UINT8: PSI_CALC_OP2(fval, u8, fval); break; \ + case PSI_T_INT16: PSI_CALC_OP2(fval, i16, fval); break; \ + case PSI_T_UINT16: PSI_CALC_OP2(fval, u16, fval); break; \ + case PSI_T_INT32: PSI_CALC_OP2(fval, i32, fval); break; \ + case PSI_T_UINT32: PSI_CALC_OP2(fval, u32, fval); break; \ + case PSI_T_INT64: PSI_CALC_OP2(fval, i64, fval); break; \ + case PSI_T_UINT64: PSI_CALC_OP2(fval, u64, fval); break; \ + EMPTY_SWITCH_DEFAULT_CASE(); \ + } \ + return t2; \ + } else { \ + int64_t sval1 = v1->i64, sval2 = v2->i64; \ + uint64_t uval1 = v1->u64, uval2 = v2->u64; \ + switch (t1) { \ + case PSI_T_INT8: sval1 >>= 8; \ + case PSI_T_INT16: sval1 >>= 8; \ + case PSI_T_INT32: sval1 >>= 8; \ + case PSI_T_INT64: \ + switch (t2) { \ + case PSI_T_INT8: sval2 >>= 8; \ + case PSI_T_INT16: sval2 >>= 8; \ + case PSI_T_INT32: sval2 >>= 8; \ + case PSI_T_INT64: \ + res->i64 = PSI_CALC(sval1 , sval2); \ + return PSI_T_INT64; \ + case PSI_T_UINT8: uval2 >>= 8; \ + case PSI_T_UINT16: uval2 >>= 8; \ + case PSI_T_UINT32: uval2 >>= 8; \ + case PSI_T_UINT64: \ + res->i64 = PSI_CALC(sval1, uval2); \ + return PSI_T_INT64; \ + } \ + break; \ + case PSI_T_UINT8: uval1 >>= 8; \ + case PSI_T_UINT16: uval1 >>= 8; \ + case PSI_T_UINT32: uval1 >>= 8; \ + case PSI_T_UINT64: \ + switch (t2) { \ + case PSI_T_INT8: sval2 >>= 8; \ + case PSI_T_INT16: sval2 >>= 8; \ + case PSI_T_INT32: sval2 >>= 8; \ + case PSI_T_INT64: \ + res->i64 = PSI_CALC(uval1, sval2); \ + return PSI_T_INT64; \ + case PSI_T_UINT8: uval2 >>= 8; \ + case PSI_T_UINT16: uval2 >>= 8; \ + case PSI_T_UINT32: uval2 >>= 8; \ + case PSI_T_UINT64: \ + res->u64 = PSI_CALC(uval1, uval2); \ + return PSI_T_UINT64; \ + } \ + break; \ + } \ + } \ + ZEND_ASSERT(0); \ + return 0; \ +} + +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) + (var2) +PSI_CALC_FN(add) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) * (var2) +PSI_CALC_FN(mul) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) - (var2) +PSI_CALC_FN(sub) +#undef PSI_CALC +#define PSI_CALC(var1, var2) (var1) / (var2) +PSI_CALC_FN(div) + void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl) { impl_val ret_val;