functor types
authorMichael Wallner <mike@php.net>
Thu, 1 Sep 2016 17:34:42 +0000 (19:34 +0200)
committerMichael Wallner <mike@php.net>
Tue, 18 Oct 2016 08:26:57 +0000 (10:26 +0200)
.gitignore
m4/psi.m4
m4/psi_decl.m4
m4/psi_type.m4
m4/signal.m4
src/context.c
src/context_dump.c
src/engine.c
src/marshal.c
src/marshal.h

index f0b0682d344fca8ae2c89abb3fafca9cf62eae0c..89a5d13d44ffddfd640b9b6b2f7350ff573175e9 100644 (file)
@@ -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
index 41acc565fbdaf7ac31b22eb86ecc851efe96b53e..8d8797c86116f2d489edd78d3b72f158caf8bdc2 100644 (file)
--- 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 <<EOF
 /* generated by configure */
 #include "php_psi_stdinc.h"
@@ -94,6 +95,9 @@ static struct psi_predef_decl {
 EOF
        cat >>$PSI_VA_DECLS <<EOF
 static struct psi_predef_decl psi_predef_vararg_decls@<:@@:>@ = {
+EOF
+       cat >>$PSI_FN_DECLS <<EOF
+static struct psi_predef_decl psi_predef_functor_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 <<EOF
        {0}
 };
index e142f708dbf911c2ce714416ee8116bbdef81cd6..540b48f2662ce977bbfd03a1321903e440a4dca7 100644 (file)
@@ -10,6 +10,11 @@ EOF
 # Add a pre-defined decl to $PSI_VA_DECLS/$PSI_DECLS.
 psi_add_decl() {
        case "$2" in
+ *functor*)
+               cat >>$PSI_FN_DECLS <<EOF
+       $1, {0},
+EOF
+               ;;
        *vararg*)
                cat >>$PSI_VA_DECLS <<EOF
        $1, {0}, 
@@ -23,6 +28,12 @@ EOF
        esac
 }
 
+dnl PSI_DECL_TYPE(type functor_name, args)
+dnl Adds a pre-defined functor decl to $PSI_FN_DECLS.
+AC_DEFUN(PSI_DECL_TYPE, [
+       PSI_DECL_ARGS($1, $2)
+       psi_add_decl "$psi_decl_args" functor
+])
 dnl PSI_REDIR(name, custom symbol)
 dnl Create a function redirection to an optional custom symbol.
 AC_DEFUN(PSI_REDIR, [
index ef073ca3191f844bb5325a41310ef76ee99556ef..ad2d0001cbc6275d722f0c836d13f318bc65f0a0 100644 (file)
@@ -127,6 +127,14 @@ AC_DEFUN(PSI_OPAQUE_TYPE, [
        fi
 ])
 
+dnl PSI_FUNCTOR_TYPE(type functor_name, args)
+dnl Forwards to PSI_DECL_TYPE.
+AC_DEFUN(PSI_FUNCTOR_TYPE, [
+       dnl psi_add_type "{PSI_T_POINTER, \"void\", \"PSI_VAR_NAME($1)\"}"
+       AS_TR_SH([ac_cv_sizeof_]PSI_VAR_NAME($1))=PSI_SH_SIZEOF(void *)
+       PSI_DECL_TYPE([$1], [$2])
+])
+
 dnl PSI_VAR_TYPE(decl arg)
 dnl Extracts the type of a decl arg, e.g. dnl unsigned char* buf[16] -> unsigned char*.
 AC_DEFUN(PSI_VAR_TYPE, [m4_bregexp([$1], [^\(const \)?\(.*\) \([*]*\)[^ ]+$], [\2\3])])
index 8a0f1417546796e5239cc9c1746e4bb63a6ca95b..d16bf49ef8d21f8d2fe8240b83bcfe9eb4ce0c56 100644 (file)
@@ -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, [
index 805309d268753bc159e3bc759a884da80bbf0b3c..fe2b5bc688f76001749f26c79d984799e524cd22 100644 (file)
@@ -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;
index 1f40e4fca0f5bd20e31bb68ef8080a2d9f44c38b..b84f6c8f2c63371bec2cc680546f11a505f5eda4 100644 (file)
@@ -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);
index 38cdb0e09193c1cf6d314ca2e76d798446cfad12..37f99766acd63dfda8817084efd173084067703c 100644 (file)
@@ -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;
                }
        }
 }
index 28553173862e69caebfb0f1d474fd77a777bd2a6..622db12bd817ce05ea02573c65fafe370541c934 100644 (file)
@@ -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();
        }
 
index a011c1bb115d794a393dd92fe74242b34c568515..4e2aab4ae52e1c7ad3620f36c6d22e5a6a7d61c1 100644 (file)
@@ -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);