From: Michael Wallner Date: Thu, 1 Sep 2016 17:34:42 +0000 (+0200) Subject: functor types X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=commitdiff_plain;h=b25cb3852e3c6ef6da608001585218015aaf5d3e functor types --- diff --git a/.gitignore b/.gitignore index f0b0682..89a5d13 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ php_psi_stdtypes.h php_psi_structs.h php_psi_types.h php_psi_va_decls.h +php_psi_fn_decls.h /tmp/ *.loT php_psi_unions.h diff --git a/m4/psi.m4 b/m4/psi.m4 index 41acc56..8d8797c 100644 --- a/m4/psi.m4 +++ b/m4/psi.m4 @@ -9,13 +9,14 @@ PSI_REDIRS=$PHP_PSI_SRCDIR/php_psi_redirs.h PSI_MACROS=$PHP_PSI_SRCDIR/php_psi_macros.h PSI_DECLS=$PHP_PSI_SRCDIR/php_psi_decls.h PSI_VA_DECLS=$PHP_PSI_SRCDIR/php_psi_va_decls.h +PSI_FN_DECLS=$PHP_PSI_SRCDIR/php_psi_fn_decls.h dnl PSI_CONFIG_INIT() dnl Creates stubs of the headers with pre-defined types etc. dnl These headers are included by src/context.c. dnl This macro must be called prior any checks for a type, struct, decl etc. AC_DEFUN(PSI_CONFIG_INIT, [ - for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_MACROS $PSI_DECLS $PSI_VA_DECLS; do + for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_MACROS $PSI_DECLS $PSI_VA_DECLS $PSI_FN_DECLS; do cat >$i <>$PSI_VA_DECLS <@ = { +EOF + cat >>$PSI_FN_DECLS <@ = { EOF ]) @@ -113,7 +117,7 @@ AC_DEFUN(PSI_CONFIG_DONE, [ PSI_INCLUDES #endif EOF - for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS; do + for i in $PSI_STDTYPES $PSI_TYPES $PSI_STRUCTS $PSI_UNIONS $PSI_CONSTS $PSI_REDIRS $PSI_DECLS $PSI_VA_DECLS $PSI_FN_DECLS; do cat >>$i <>$PSI_FN_DECLS <>$PSI_VA_DECLS < unsigned char*. AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [^\(const \)?\(.*\) \([*]*\)[^ ]+$], [\2\3])]) diff --git a/m4/signal.m4 b/m4/signal.m4 index 8a0f141..d16bf49 100644 --- a/m4/signal.m4 +++ b/m4/signal.m4 @@ -123,11 +123,14 @@ PSI_CHECK_SIGNAL() { int ss_flags] ) + PSI_FUNCTOR_TYPE(void sa_handler, [(int signo)]) + PSI_FUNCTOR_TYPE(void sa_sigaction, [(int signo, siginfo_t *info, void *context)]) + PSI_STRUCT(struct sigaction, [ - void *sa_handler, + sa_handler sa_handler, sigset_t sa_mask, int sa_flags, - void *sa_sigaction] + sa_sigaction sa_sigaction] ) PSI_STRUCT(ucontext_t, [ diff --git a/src/context.c b/src/context.c index 805309d..fe2b5bc 100644 --- a/src/context.c +++ b/src/context.c @@ -38,6 +38,7 @@ #include "php_psi_consts.h" #include "php_psi_decls.h" #include "php_psi_va_decls.h" +#include "php_psi_fn_decls.h" #include "php_psi_structs.h" #include "php_psi_unions.h" @@ -167,6 +168,29 @@ struct psi_context *psi_context_init(struct psi_context *C, struct psi_context_o predef_decl = farg; } + for (predef_decl = &psi_predef_functor_decls[0]; predef_decl->type_tag; ++predef_decl) { + struct psi_predef_decl *farg; + decl_type *dtype, *ftype = init_decl_type(predef_decl->type_tag, predef_decl->type_name); + decl_var *fname = init_decl_var(predef_decl->var_name, predef_decl->pointer_level, predef_decl->array_size); + decl_arg *tdef, *func = init_decl_arg(ftype, fname); + decl_args *args = init_decl_args(NULL); + decl *decl = init_decl(init_decl_abi("default"), func, args); + + for (farg = &predef_decl[1]; farg->type_tag; ++farg) { + decl_type *arg_type = init_decl_type(farg->type_tag, farg->type_name); + decl_var *arg_var = init_decl_var(farg->var_name, farg->pointer_level, farg->array_size); + decl_arg *darg = init_decl_arg(arg_type, arg_var); + args = add_decl_arg(args, darg); + } + + dtype = init_decl_type(PSI_T_FUNCTION, fname->name); + dtype->real.func = decl; + tdef = init_decl_arg(dtype, copy_decl_var(fname)); + T.defs = add_decl_typedef(T.defs, tdef); + + predef_decl = farg; + } + psi_context_validate_data(PSI_DATA(C), &T); C->count = 1; diff --git a/src/context_dump.c b/src/context_dump.c index 1f40e4f..b84f6c8 100644 --- a/src/context_dump.c +++ b/src/context_dump.c @@ -372,53 +372,90 @@ static inline void dump_impl_func(int fd, impl_func *func) { func->return_type->name); } -static inline void dump_impl_let_stmt(int fd, let_stmt *let) { - dprintf(fd, "\tlet %s", let->var->name); - if (let->val) { - dprintf(fd, " = %s", let->val->flags.one.is_reference ? "&" : ""); - switch (let->val->kind) { - case PSI_LET_NULL: - dprintf(fd, "NULL"); - break; - case PSI_LET_TMP: - dump_decl_var(fd, let->val->data.var); - break; - case PSI_LET_CALLOC: - dprintf(fd, "calloc("); - dump_num_exp(fd, let->val->data.alloc->nmemb); - dprintf(fd, ", "); - dump_num_exp(fd, let->val->data.alloc->size); - dprintf(fd, ")"); - break; - case PSI_LET_CALLBACK: - dprintf(fd, "callback %s(%s(", let->val->data.callback->func->name, - let->val->data.callback->func->var->name); - if (let->val->data.callback->args) { - size_t i, c = let->val->data.callback->args->count; - - dprintf(fd, "\n"); - for (i = 0; i < c; ++i) { - set_value *set = let->val->data.callback->args->vals[i]; - dump_impl_set_value(fd, set, 2, i + 1 == c); - } - dprintf(fd, "\t"); +static inline void dump_impl_let_func(int fd, let_func *func, unsigned level); + +static inline void dump_impl_let_val(int fd, let_val *val, unsigned level, int last) { + if (level > 1) { + /* only if not directly after `set ...` */ + dump_level(fd, level); + } + + dprintf(fd, "%s", val->flags.one.is_reference ? "&" : ""); + switch (val->kind) { + case PSI_LET_NULL: + dprintf(fd, "NULL"); + break; + case PSI_LET_TMP: + dump_decl_var(fd, val->data.var); + break; + case PSI_LET_CALLOC: + dprintf(fd, "calloc("); + dump_num_exp(fd, val->data.alloc->nmemb); + dprintf(fd, ", "); + dump_num_exp(fd, val->data.alloc->size); + dprintf(fd, ")"); + break; + case PSI_LET_CALLBACK: + dprintf(fd, "callback %s(%s(", val->data.callback->func->name, + val->data.callback->func->var->name); + if (val->data.callback->args) { + size_t i, c = val->data.callback->args->count; + + dprintf(fd, "\n"); + for (i = 0; i < c; ++i) { + set_value *set = val->data.callback->args->vals[i]; + ++level; + dump_impl_set_value(fd, set, level, i + 1 == c); + --level; } - dprintf(fd, "));"); - break; - case PSI_LET_FUNC: - dprintf(fd, "%s(%s)", let->val->data.func->name, - let->val->data.func->var->name); - break; - case PSI_LET_NUMEXP: - dump_num_exp(fd, let->val->data.num); - break; + dump_level(fd, level); + } + dprintf(fd, "))"); + break; + case PSI_LET_FUNC: + dump_impl_let_func(fd, val->data.func, level); + break; + case PSI_LET_NUMEXP: + dump_num_exp(fd, val->data.num); + break; - EMPTY_SWITCH_DEFAULT_CASE(); + EMPTY_SWITCH_DEFAULT_CASE(); + } + if (level > 1) { + if (!last) { + dprintf(fd, ","); } + } else { dprintf(fd, ";"); } } +static inline void dump_impl_let_func(int fd, let_func *func, unsigned level) { + dprintf(fd, "%s(%s", func->name, + func->var->name); + if (func->inner) { + size_t i; + + dprintf(fd, ","); + ++level; + for (i = 0; i < func->inner->count; ++i) { + dprintf(fd, "\n"); + dump_impl_let_val(fd, func->inner->vals[i], level, i+1 == func->inner->count); + } + --level; + dprintf(fd, "\n"); + dump_level(fd, level); + } + dprintf(fd, ")"); +} +static inline void dump_impl_let_stmt(int fd, let_stmt *let) { + dprintf(fd, "\tlet %s", let->var->name); + if (let->val) { + dprintf(fd, " = "); + dump_impl_let_val(fd, let->val, 1, 1); + } +} + static inline void dump_impl_return_stmt(int fd, return_stmt *ret) { dprintf(fd, "\treturn "); dump_impl_set_value(fd, ret->set, 1, 0); diff --git a/src/engine.c b/src/engine.c index 38cdb0e..37f9976 100644 --- a/src/engine.c +++ b/src/engine.c @@ -207,12 +207,6 @@ static inline void *psi_do_calloc(let_calloc *alloc) 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) -{ - abort(); - return arg_val; -} - static inline impl_val *psi_let_func(let_func *func, decl_arg *darg) { return darg->ptr = func->handler(darg->ptr, darg->type, func->var->arg, &darg->mem); } @@ -293,6 +287,12 @@ static inline void psi_clean_array_struct(let_stmt *let, decl_arg *darg) { while (*ptr) { efree(*ptr++); } + } else if (type->type == PSI_T_STRUCT) { + void **ptr = (void **) ((char *) darg->mem + type->real.unn->size); + + if (*ptr) { + efree(*ptr); + } } } } @@ -378,6 +378,9 @@ static inline void psi_do_args(impl *impl) { case PSI_T_STRUCT: impl->decl->func->ptr = psi_array_to_struct(real->real.strct, NULL); break; + case PSI_T_UNION: + impl->decl->func->ptr = psi_array_to_union(real->real.unn, NULL); + break; } } } diff --git a/src/marshal.c b/src/marshal.c index 2855317..622db12 100644 --- a/src/marshal.c +++ b/src/marshal.c @@ -348,6 +348,8 @@ 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_FUNCTION: + break; case PSI_T_FLOAT: mem->fval = (float) zval_get_double(zv); break; @@ -394,6 +396,32 @@ void *psi_array_to_struct(decl_struct *s, HashTable *arr) return mem; } +void *psi_array_to_union(decl_union *u, HashTable *arr) { + size_t i; + char *mem = ecalloc(1, u->size + sizeof(void *)); + + if (arr) for (i = 0; i < u->args->count; ++i) { + decl_arg *darg = u->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, &val, darg->layout->len); + if (tmp) { + ((void **)(mem + u->size))[0] = tmp; + } + /* first found entry wins */ + break; + } + } + + return mem; +} + void psi_to_recursive(zval *return_value, set_value *set, impl_val *r_val) { set->outer.set->func->handler(return_value, set, r_val); @@ -507,6 +535,9 @@ impl_val *psi_let_arrval(impl_val *tmp, decl_type *type, impl_arg *iarg, void ** case PSI_T_STRUCT: *to_free = tmp = psi_array_to_struct(real->real.strct, arr); break; + case PSI_T_UNION: + *to_free = tmp = psi_array_to_union(real->real.unn, arr); + break; EMPTY_SWITCH_DEFAULT_CASE(); } diff --git a/src/marshal.h b/src/marshal.h index a011c1b..4e2aab4 100644 --- a/src/marshal.h +++ b/src/marshal.h @@ -11,6 +11,7 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *ret_val); void psi_to_object(zval *return_value, set_value *set, impl_val *ret_val); void psi_to_zval(zval *return_value, set_value *set, impl_val *ret_val); +void *psi_array_to_union(decl_union *u, HashTable *arr); void *psi_array_to_struct(decl_struct *s, HashTable *arr); void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp);