+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);
+ }
+ }
+ }
+ return;
+
+// for (i = 0; i < s->args->count; ++i) {
+// decl_arg *darg = s->args->args[i];
+// impl_val tmp, tmp_ptr;
+// zval ztmp;
+// char *ptr = (char *) ret_val->ptr + darg->layout->pos;
+//
+// tmp_ptr.ptr = &tmp;
+// memset(&tmp, 0, sizeof(tmp));
+// memcpy(&tmp, ptr, darg->layout->len);
+// switch (real_decl_type(darg->type)->type) {
+// case PSI_T_FLOAT:
+// case PSI_T_DOUBLE:
+// psi_to_double(&ztmp, real_decl_type(darg->type)->type, &tmp, darg->var);
+// break;
+// case PSI_T_INT8:
+// case PSI_T_UINT8:
+// if (darg->var->pointer_level) {
+// psi_to_string(&ztmp, real_decl_type(darg->type)->type, &tmp_ptr, darg->var);
+// break;
+// }
+// /* no break */
+// case PSI_T_INT16:
+// case PSI_T_UINT16:
+// case PSI_T_INT32:
+// case PSI_T_UINT32:
+// case PSI_T_INT64:
+// case PSI_T_UINT64:
+// psi_to_int(&ztmp, real_decl_type(darg->type)->type, &tmp, darg->var);
+// break;
+// case PSI_T_STRUCT:
+// psi_to_array(&ztmp, real_decl_type(darg->type)->type, &tmp_ptr, darg->var);
+// break;
+// default:
+// printf("t=%d\n", real_decl_type(darg->type)->type);
+// abort();
+// }
+// add_assoc_zval(return_value, darg->var->name, &ztmp);
+// }
+ return;
+ }
+ ret_val = deref_impl_val(ret_val, var);
+ for (i = 0; i < var->arg->var->array_size; ++i) {
+ impl_val *ptr = iterate(ret_val, t, i, &tmp);
+
+ switch (t) {
+ case PSI_T_FLOAT:
+ ZVAL_DOUBLE(&ele, (double) ptr->fval);
+ break;
+ case PSI_T_DOUBLE:
+ ZVAL_DOUBLE(&ele, ptr->dval);
+ break;
+ default:
+ ZVAL_LONG(&ele, ptr->lval);
+ break;
+ }
+
+ add_next_index_zval(return_value, &ele);
+ }
+}
+