+
+static impl_val *iterate(impl_val *val, token_t t, unsigned i, impl_val *tmp)
+{
+ size_t size = psi_t_size(t);
+
+ memset(tmp, 0, sizeof(*tmp));
+ memcpy(tmp, val->ptr + size * i, size);
+ return tmp;
+}
+
+void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp)
+{
+ decl_type *type = real_decl_type(spec->type);
+
+ switch (type->type) {
+ case PSI_T_FLOAT:
+ mem->fval = (float) zval_get_double(zv);
+ break;
+ case PSI_T_DOUBLE:
+ mem->dval = zval_get_double(zv);
+ break;
+ case PSI_T_INT8:
+ case PSI_T_UINT8:
+ if (spec->var->pointer_level) {
+ zend_string *zs = zval_get_string(zv);
+ *tmp = mem->ptr = estrndup(zs->val, zs->len);
+ zend_string_release(zs);
+ break;
+ }
+ /* no break */
+ default:
+ mem->zend.lval = zval_get_long(zv);
+ break;
+ }
+}
+
+void *psi_array_to_struct(decl_struct *s, HashTable *arr)
+{
+ size_t i, j = 0;
+ char *mem = ecalloc(1, s->size + s->args->count * sizeof(void *));
+
+ if (arr) for (i = 0; i < s->args->count; ++i) {
+ decl_arg *darg = s->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 + darg->layout->pos, &val, darg->layout->len);
+ if (tmp) {
+ ((void **)(mem + s->size))[j++] = tmp;
+ }
+ }
+ }
+ return mem;
+}
+
+void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, set_value *set, decl_var *var)
+{
+ zval ele;
+ unsigned i;
+ impl_val tmp;
+
+ array_init(return_value);
+
+ if (t == PSI_T_STRUCT) {
+ decl_struct *s = real_decl_type(var->arg->type)->strct;
+ ret_val = deref_impl_val(ret_val, var);
+
+ ZEND_ASSERT(s);
+
+ if (set->count) {
+ /* explicit member casts */
+ for (i = 0; i < set->count; ++i) {
+ zval ztmp;
+ impl_val *tmp_ptr;
+ set_value *sub_set = set->inner[i];
+ decl_var *sub_var = sub_set->vars->vars[0];
+ decl_arg *sub_arg = sub_var->arg;
+ token_t t = real_decl_type(sub_arg->type)->type;
+ void *ptr = malloc(sub_arg->layout->len);
+
+ memcpy(ptr, (char *) ret_val->ptr + sub_arg->layout->pos,
+ sub_arg->layout->len);
+ tmp_ptr = enref_impl_val(ptr, sub_arg->var);
+ sub_set->func->handler(&ztmp, t, tmp_ptr, sub_set, sub_var);
+ add_assoc_zval(return_value, sub_var->name, &ztmp);
+ free(tmp_ptr);
+ if (tmp_ptr != ptr) {
+ free(ptr);
+ }
+ }