- } else if (set->num) {
- /* to_array(arr_var, num_expr, to_int(*arr_var)) */
- zval ele;
- char *ptr;
- zend_long i, n = psi_long_num_exp(set->num, set->outer.val);
- size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
- set_value *sub_set = set->inner[0];
-
- sub_set->outer.val = set->outer.val;
- for (i = 0; i < n; ++i) {
- ptr = (char *) ret_val->ptr + i * size;
- sub_set->func->handler(&ele, sub_set, (void *) ptr);
- add_next_index_zval(return_value, &ele);
- }
- } else {
- /* to_array(arr_var, to_int(*arr_var)) */
- zval ele;
- char *ptr = ret_val->ptr;
- size_t size = psi_t_size(var->arg->var->pointer_level ? PSI_T_POINTER : t);
- set_value *sub_set = set->inner[0];
-
- sub_set->outer.val = set->outer.val;
- while (*(void **) ptr) {
- sub_set->func->handler(&ele, sub_set, (void *) ptr);
- add_next_index_zval(return_value, &ele);
- ptr += size;
- }
- }
-}
-
-void psi_to_object(zval *return_value, set_value *set, impl_val *r_val)
-{
- decl_var *var = set->vars->vars[0];
- impl_val *ret_val = deref_impl_val(r_val, var);
- psi_object *obj;
-
- if ((intptr_t) ret_val->ptr > (intptr_t) 0) {
- object_init_ex(return_value, psi_class_entry);
- obj = PSI_OBJ(return_value, NULL);
- obj->data = ret_val->ptr;
- } else {
- RETVAL_NULL();
- }
-}
-
-static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl)
-{
- size_t i;
- impl_arg *iarg;
- zend_error_handling zeh;
-
- zend_replace_error_handling(EH_THROW, zend_exception_get_default(), &zeh);
-
- if (!impl->func->args->count) {
- ZEND_RESULT_CODE rv;
-
- rv = zend_parse_parameters_none();
- zend_restore_error_handling(&zeh);
- return rv;
- }
-
- ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->vararg.name ? -1 : impl->func->args->count)
- nextarg:
- if (impl->func->args->vararg.name && _i >= impl->func->args->count) {
- impl_arg *varg = impl->func->args->vararg.name;
- iarg = init_impl_arg(
- init_impl_type(varg->type->type, varg->type->name),
- init_impl_var(varg->var->name, varg->var->reference),
- NULL);
-
- Z_PARAM_OPTIONAL;
- if (_i == impl->func->args->count) {
- impl->func->args->vararg.args = init_impl_args(iarg);
- } else {
- add_impl_arg(impl->func->args->vararg.args, iarg);
- }
- } else {
- iarg = impl->func->args->args[_i];
- if (iarg->def) {
- Z_PARAM_OPTIONAL;
- }
- }
- if (PSI_T_BOOL == iarg->type->type) {
- Z_PARAM_BOOL(iarg->val.zend.bval);
- } else if (PSI_T_INT == iarg->type->type) {
- Z_PARAM_LONG(iarg->val.zend.lval);
- } else if (PSI_T_FLOAT == iarg->type->type || PSI_T_DOUBLE == iarg->type->type) {
- Z_PARAM_DOUBLE(iarg->val.dval);
- } else if (PSI_T_STRING == iarg->type->type) {
- Z_PARAM_STR_EX(iarg->val.zend.str, 1, iarg->var->reference);
- if (iarg->val.zend.str) {
- zend_string_addref(iarg->val.zend.str);
- }
- } else if (PSI_T_ARRAY == iarg->type->type) {
- Z_PARAM_PROLOGUE(0);
- } else if (PSI_T_OBJECT == iarg->type->type) {
- Z_PARAM_PROLOGUE(0);
- } else if (PSI_T_MIXED == iarg->type->type) {
- Z_PARAM_PROLOGUE(0);
- } else {
- error_code = ZPP_ERROR_FAILURE;
- break;
- }
- iarg->_zv = _arg;
- ZVAL_DEREF(iarg->_zv);
- if (_i < _num_args) {
- goto nextarg;
- }
- ZEND_PARSE_PARAMETERS_END_EX(
- zend_restore_error_handling(&zeh);
- return FAILURE
- );
-
- /* set up defaults */
- for (i = 0; i < impl->func->args->count; ++i) {
- if (i >= EX_NUM_ARGS() && iarg->def) {
- iarg = impl->func->args->args[i];
-
- switch (iarg->type->type) {
- case PSI_T_BOOL:
- iarg->val.zend.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
- break;
- case PSI_T_INT:
- iarg->val.zend.lval = zend_atol(iarg->def->text, strlen(iarg->def->text));
- break;
- case PSI_T_FLOAT:
- case PSI_T_DOUBLE:
- iarg->val.dval = zend_strtod(iarg->def->text, NULL);
- break;
- case PSI_T_STRING:
- /* FIXME */
- iarg->val.zend.str = zend_string_init(&iarg->def->text[1], strlen(iarg->def->text) - 2, 0);
- break;
- }
- }
- }
-
- zend_restore_error_handling(&zeh);
- return SUCCESS;
-}
-
-static inline void *psi_do_calloc(let_calloc *alloc)
-{
- 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 *));
-#if 0
- fprintf(stderr, "calloc: %p\n", mem);
-#endif
- 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)
-{
- switch (let_func) {
- case PSI_T_BOOLVAL:
- if (iarg->type->type == PSI_T_BOOL) {
- arg_val->cval = iarg->val.zend.bval;
- } else {
- arg_val->cval = zend_is_true(iarg->_zv);
- }
- break;
- case PSI_T_INTVAL:
- if (iarg->type->type == PSI_T_INT) {
- arg_val->lval = iarg->val.zend.lval;
- } else {
- arg_val->lval = zval_get_long(iarg->_zv);
- }
- break;
- case PSI_T_FLOATVAL:
- if (iarg->type->type == PSI_T_FLOAT || iarg->type->type == PSI_T_DOUBLE) {
- arg_val->dval = iarg->val.dval;
- } else {
- arg_val->dval = zval_get_double(iarg->_zv);
- }
- break;
- case PSI_T_PATHVAL:
- case PSI_T_STRVAL:
- if (iarg->type->type == PSI_T_STRING) {
- if (iarg->val.zend.str) {
- arg_val->ptr = estrndup(iarg->val.zend.str->val, iarg->val.zend.str->len);
- *to_free = arg_val->ptr;
- } else {
- arg_val->ptr = "";
- }
- } else {
- zend_string *zs = zval_get_string(iarg->_zv);
- arg_val->ptr = estrdup(zs->val);
- *to_free = arg_val->ptr;
- zend_string_release(zs);
- }
- if (PSI_T_PATHVAL == let_func) {
- if (SUCCESS != php_check_open_basedir(arg_val->ptr)) {
- efree(arg_val->ptr);
- return NULL;
- }
- }
- break;
- case PSI_T_STRLEN:
- if (iarg->type->type == PSI_T_STRING) {
- if (iarg->val.zend.str) {
- arg_val->lval = iarg->val.zend.str->len;
- } else {
- arg_val->lval = 0;
- }
- } else {
- zend_string *zs = zval_get_string(iarg->_zv);
- arg_val->lval = zs->len;
- zend_string_release(zs);
- }
- break;
- case PSI_T_ARRVAL:
- if (iarg->type->type == PSI_T_ARRAY) {
- arg_val = psi_array_to_struct(strct, HASH_OF(iarg->_zv));
- *to_free = arg_val;
- }
- break;
- case PSI_T_OBJVAL:
- if (iarg->type->type == PSI_T_OBJECT) {
- psi_object *obj;
-
- if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_class_entry)) {
- return NULL;
- }
-
- obj = PSI_OBJ(iarg->_zv, NULL);
- arg_val->ptr = obj->data;
- }
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return arg_val;
-}
-
-static inline void *psi_do_let(let_stmt *let)
-{
- decl_arg *darg = let->var->arg;
- impl_val *arg_val = darg->ptr;
- impl_arg *iarg;
-
- switch (let->val ? let->val->kind : PSI_LET_NULL) {
- case PSI_LET_TMP:
- memcpy(arg_val, deref_impl_val(let->val->data.var->arg->let->ptr, let->val->data.var), sizeof(*arg_val));
-#if 0
- fprintf(stderr, "LET TMP: %p -> %p\n",
- let->val->data.var->arg->let->ptr,
- arg_val->ptr);
-#endif
- break;
- case PSI_LET_NULL:
- if (darg->var->array_size) {
- arg_val->ptr = ecalloc(darg->var->array_size, sizeof(*arg_val));
- darg->mem = arg_val->ptr;
- } else {
- memset(arg_val, 0, sizeof(*arg_val));
- }
- break;
- case PSI_LET_CALLOC:
- arg_val->ptr = psi_do_calloc(let->val->data.alloc);
- darg->mem = arg_val->ptr;
- break;
- case PSI_LET_NUMEXP:
- arg_val->zend.lval = psi_long_num_exp(let->val->data.num, NULL);
- break;
- case PSI_LET_FUNC:
- iarg = let->val->data.func->arg;
-
- if (!(darg->ptr = psi_let_val(let->val->data.func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem))) {
- return NULL;
- }
- }
-
- if (let->val && let->val->flags.one.is_reference) {
- return let->ptr = &darg->ptr;
- } else {
- return let->ptr = darg->ptr;
- }
-}
-
-static inline void psi_do_set(zval *return_value, set_value *set)
-{
- decl_arg *set_arg = set->vars->vars[0]->arg;
-
- zval_dtor(return_value);
- set->func->handler(return_value, set, set_arg->let ? set_arg->let->ptr : set_arg->ptr);
-}
-
-static inline void psi_do_return(zval *return_value, return_stmt *ret)
-{
- ret->set->func->handler(return_value, ret->set, ret->set->vars->vars[0]->arg->ptr);
-}
-
-static inline void psi_do_free(free_stmt *fre)
-{
- size_t i, j;
-
- for (i = 0; i < fre->calls->count; ++i) {
- free_call *f = fre->calls->list[i];
-
- for (j = 0; j < f->vars->count; ++j) {
- decl_var *dvar = f->vars->vars[j];
- decl_arg *darg = dvar->arg;
- impl_val *fval = darg->let ? darg->let->ptr : darg->ptr;
-
- f->decl->call.args[j] = deref_impl_val(fval, dvar);
- }
-
- /* FIXME: check in validate_* that free functions return scalar */
- PSI_ContextCall(&PSI_G(context), &f->decl->call, NULL);