X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Fmodule.c;h=ac08a9541a21aef83d2efa92fc8eceaafb481aa7;hb=bcd9e150292290ce2951fdca61fad526c478e787;hp=ee1230f3667267e8689a4ddfc2da73b589435b5a;hpb=22b4a95d8fd6525e4539f843ba5bebb9a56e89f2;p=m6w6%2Fext-psi diff --git a/src/module.c b/src/module.c index ee1230f..ac08a95 100644 --- a/src/module.c +++ b/src/module.c @@ -281,14 +281,96 @@ static impl_val *iterate(impl_val *val, token_t t, unsigned i, impl_val *tmp) 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_CHAR: + case PSI_T_SINT8: + 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; + } + default: + mem->lval = zval_get_long(zv); + break; + } +} + +void *psi_array_to_struct(decl_struct *s, HashTable *arr) +{ + size_t i, j = 0, size = decl_struct_size(s); + char *mem = ecalloc(1, size + s->args->count * sizeof(void *)); + + for (i = 0; i < s->args->count; ++i) { + decl_struct_layout *layout = &s->layout[i]; + decl_arg *darg = s->args->args[i]; + decl_type *type = real_decl_type(darg->type); + 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 + layout->pos, &val, layout->len); + if (tmp) { + ((void **)(mem + size))[j++] = tmp; + } + } + } + return mem; +} + void psi_to_array(impl_val *ret_val, decl_arg *func, zval *return_value) { zval ele; unsigned i; impl_val tmp; - token_t t = real_decl_type(func->type)->type; + decl_type *type = real_decl_type(func->type); + token_t t = type->type; array_init(return_value); + + if (t == PSI_T_STRUCT) { + decl_struct *s = type->strct; + ret_val = deref_impl_val(func->var->pointer_level, ret_val, func); + + ZEND_ASSERT(s); + for (i = 0; i < s->args->count; ++i) { + decl_arg *darg = s->args->args[i]; + decl_struct_layout layout = s->layout[i]; + impl_val tmp; + zval ztmp; + char *ptr = (char *) ret_val->ptr + layout.pos; + + memset(&tmp, 0, sizeof(tmp)); + memcpy(&tmp, ptr, layout.len); + switch (real_decl_type(darg->type)->type) { + case PSI_T_INT: + case PSI_T_LONG: + psi_to_int(&tmp, darg, &ztmp); + break; + case PSI_T_CHAR: + psi_to_string(&tmp, darg, &ztmp); + break; + EMPTY_SWITCH_DEFAULT_CASE(); + } + add_assoc_zval(return_value, darg->var->name, &ztmp); + } + return; + } ret_val = deref_impl_val(0, ret_val, func); for (i = 0; i < func->var->array_size; ++i) { impl_val *ptr = iterate(ret_val, t, i, &tmp); @@ -424,6 +506,18 @@ impl_val *psi_do_let(decl_arg *darg) arg_val->ptr = calloc(1, darg->let->val->func->size); darg->let->mem = arg_val->ptr; break; + case PSI_T_ARRVAL: + if (iarg->type->type == PSI_T_ARRAY) { + decl_type *type = real_decl_type(darg->type); + + switch (type->type) { + case PSI_T_STRUCT: + arg_val->ptr = psi_array_to_struct(type->strct, HASH_OF(iarg->_zv)); + darg->let->mem = arg_val->ptr; + break; + } + } + break; EMPTY_SWITCH_DEFAULT_CASE(); } @@ -457,6 +551,9 @@ void psi_do_return(impl *impl, impl_val *ret_val, zval *return_value) case PSI_T_TO_INT: psi_to_int(ret_val, impl->decl->func, return_value); break; + case PSI_T_TO_ARRAY: + psi_to_array(ret_val, impl->decl->func, return_value); + break; EMPTY_SWITCH_DEFAULT_CASE(); } } @@ -495,6 +592,16 @@ void psi_do_clean(impl *impl) decl_arg *darg = impl->decl->args->args[i]; if (darg->let && darg->let->mem) { + decl_type *type = real_decl_type(darg->type); + + if (type->type == PSI_T_STRUCT) { + size_t eos = decl_struct_size(type->strct); + void **ptr = (void **) ((char *) darg->let->mem + eos); + + while (*ptr) { + efree(*ptr++); + } + } efree(darg->let->mem); darg->let->mem = NULL; }