build administrativa
[m6w6/ext-psi] / src / types / let_func.c
index 27c37027ad5c7f2cd6f98693bde452e5782e1831..11e5c4278b6d29b0933a675fb59508e19194106f 100644 (file)
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *******************************************************************************/
 
-#include "php_psi_stdinc.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
 #include "data.h"
 #include "call.h"
 #include "marshal.h"
 
 #include <assert.h>
 
-struct psi_let_func *psi_let_func_init(token_t type, const char *name,
+struct psi_let_func *psi_let_func_init(token_t type, zend_string *name,
                struct psi_impl_var *var)
 {
-       struct psi_let_func *func = calloc(1, sizeof(*func));
+       struct psi_let_func *func = pecalloc(1, sizeof(*func), 1);
        func->type = type;
-       func->name = strdup(name);
+       func->name = zend_string_copy(name);
        func->var = var;
        return func;
 }
@@ -48,11 +52,9 @@ void psi_let_func_free(struct psi_let_func **func_ptr)
                struct psi_let_func *func = *func_ptr;
 
                *func_ptr = NULL;
-               if (func->token) {
-                       free(func->token);
-               }
+               psi_token_free(&func->token);
                psi_impl_var_free(&func->var);
-               free(func->name);
+               zend_string_release(func->name);
                if (func->inner) {
                        psi_plist_free(func->inner);
                }
@@ -60,29 +62,30 @@ void psi_let_func_free(struct psi_let_func **func_ptr)
        }
 }
 
-void psi_let_func_dump(int fd, struct psi_let_func *func, unsigned level)
+void psi_let_func_dump(struct psi_dump *dump, struct psi_let_func *func, unsigned level)
 {
-       dprintf(fd, "%s(%s\t/* fqn=%s */", func->name, func->var->name, func->var->fqn);
+       PSI_DUMP(dump, "%s(%s\t/* fqn=%s */", func->name->val, func->var->name->val,
+                       func->var->fqn->val);
 
        if (func->inner) {
                size_t i = 0, count = psi_plist_count(func->inner);
                struct psi_let_exp *inner;
 
-               dprintf(fd, ",");
+               PSI_DUMP(dump, ",");
                ++level;
                while (psi_plist_get(func->inner, i++, &inner)) {
-                       dprintf(fd, "\n");
-                       psi_let_exp_dump(fd, inner, level, i == count);
+                       PSI_DUMP(dump, "\n");
+                       psi_let_exp_dump(dump, inner, level, i == count);
                }
                --level;
-               dprintf(fd, "\n");
-               dprintf(fd, "%s", psi_t_indent(level));
+               PSI_DUMP(dump, "\n");
+               PSI_DUMP(dump, "%s", psi_t_indent(level));
        }
-       dprintf(fd, ")");
+       PSI_DUMP(dump, ")");
 }
 
 static inline int validate_let_func_type(struct psi_data *data,
-               struct psi_let_func *func, struct psi_impl *impl)
+               struct psi_let_func *func, struct psi_validate_scope *scope)
 {
        switch (func->type) {
        case PSI_T_BOOLVAL:
@@ -108,15 +111,16 @@ static inline int validate_let_func_type(struct psi_data *data,
        default:
                data->error(data, func->var->token, PSI_WARNING,
                                "Unknown `let` cast function '%s' of implementation '%s'",
-                               func->name, impl->func->name);
+                               func->name->val, scope->impl->func->name->val);
                return false;
        }
 }
 
 static inline bool validate_let_func_inner(struct psi_data *data,
-               struct psi_let_exp *exp, struct psi_let_func *func,
-               struct psi_impl *impl)
+               struct psi_let_func *func, struct psi_validate_scope *scope)
 {
+       struct psi_let_exp *exp = scope->current_let;
+
        if (func->inner) {
                struct psi_decl_var *let_var = psi_let_exp_get_decl_var(exp);
                struct psi_decl_type *var_typ;
@@ -132,20 +136,26 @@ static inline bool validate_let_func_inner(struct psi_data *data,
                        struct psi_let_exp *inner;
 
                        while (psi_plist_get(func->inner, i++, &inner)) {
-                               const char *name = psi_let_exp_get_decl_var_name(inner);
+                               zend_string *name = psi_let_exp_get_decl_var_name(inner);
                                struct psi_decl_arg *sub_arg;
 
                                inner->outer = exp;
 
                                if (name) {
                                        sub_arg = psi_decl_arg_get_by_name(sub_args, name);
+                                       zend_string_release(name);
                                }
                                if (!name || !sub_arg) {
                                        /* remove expr for portability with different struct members */
                                        psi_plist_del(func->inner, --i, NULL);
                                        psi_let_exp_free(&inner);
-                               } else if (!psi_let_exp_validate(data, inner, impl)) {
-                                       return false;
+                               } else {
+                                       scope->current_let = inner;
+                                       if (!psi_let_exp_validate(data, inner, scope)) {
+                                               scope->current_let = exp;
+                                               return false;
+                                       }
+                                       scope->current_let = exp;
                                }
                        }
                } else if (func->type == PSI_T_ARRVAL
@@ -163,21 +173,24 @@ static inline bool validate_let_func_inner(struct psi_data *data,
 
                        sub_var = psi_let_exp_get_impl_var(exp);
                        sub_ref = psi_let_exp_get_impl_var(inner);
-                       if (strcmp(sub_var->name, sub_ref->name)) {
+                       if (!zend_string_equals(sub_var->name, sub_ref->name)) {
                                data->error(data, sub_var->token, E_WARNING,
                                                "Inner `set` statement casts on pointers must"
                                                                " reference the same variable");
                                return false;
                        }
-                       if (!psi_let_exp_validate(data, inner, impl)) {
+                       scope->current_let = inner;
+                       if (!psi_let_exp_validate(data, inner, scope)) {
+                               scope->current_let = exp;
                                return false;
                        }
+                       scope->current_let = exp;
                } else {
                        data->error(data, let_var->token, PSI_WARNING,
                                        "Inner let statement's values must refer to a structure or"
                                                        " array type, got '%s%s' for '%s'", var_typ->name,
                                        psi_t_indirection(let_var->arg->var->pointer_level),
-                                       let_var->name);
+                                       let_var->name->val);
                        return false;
                }
 
@@ -191,28 +204,28 @@ static inline bool validate_let_func_inner(struct psi_data *data,
        return true;
 }
 
-bool psi_let_func_validate(struct psi_data *data, struct psi_let_exp *val,
-               struct psi_let_func *func, struct psi_impl *impl)
+bool psi_let_func_validate(struct psi_data *data, struct psi_let_func *func,
+               struct psi_validate_scope *scope)
 {
-       if (impl->func->args) {
+       if (scope->impl->func->args) {
                /* FIXME, func->var does not need to be referring to a func arg */
-               psi_impl_get_arg(impl, func->var);
+               psi_impl_get_arg(scope->impl, func->var);
        }
 
-       if (!psi_impl_var_validate(data, func->var, impl, val, NULL)) {
+       if (!psi_impl_var_validate(data, func->var, scope)) {
                return false;
        }
 
-       if (!validate_let_func_type(data, func, impl)) {
+       if (!validate_let_func_type(data, func, scope)) {
                return false;
        }
-       if (!validate_let_func_inner(data, val, func, impl)) {
+       if (!validate_let_func_inner(data, func, scope)) {
                return false;
        }
        return 1;
 }
 
-void exec_let_func_arrval_inner(struct psi_let_func *func,
+static void exec_let_func_arrval_inner(struct psi_let_func *func,
                struct psi_decl_arg *darg, struct psi_decl_arg *inner_decl_arg,
                struct psi_call_frame_argument *frame_arg,
                struct psi_let_exp *inner_let_exp, void *container,
@@ -226,7 +239,7 @@ void exec_let_func_arrval_inner(struct psi_let_func *func,
                 * we only want to set supplied data on unions
                 */
                if (!zend_symtable_str_exists(Z_ARRVAL_P(frame_arg->zval_ptr),
-                               &inner_var->name[1], strlen(&inner_var->name[1]))) {
+                               &inner_var->name->val[1], inner_var->name->len - 1)) {
                        return;
                }
        }
@@ -235,8 +248,8 @@ void exec_let_func_arrval_inner(struct psi_let_func *func,
 
        /* example from dm_store/dbm_fetch with arrval($string) conversion:
         let key = arrval($key,
-        dptr = strval($0),
-        dsize = strlen($0)
+          dptr = strval($0),
+          dsize = strlen($0)
         );
         # ---
         darg = key
@@ -254,13 +267,13 @@ static void *exec_let_func_arrval(struct psi_let_exp *val,
                struct psi_let_func *func, struct psi_decl_arg *darg,
                struct psi_call_frame *frame);
 
-void exec_let_func_arrval_seq(struct psi_let_func *func,
-               struct psi_decl_arg *darg, struct psi_decl_type *darg_type,
+static void exec_let_func_arrval_seq(struct psi_let_func *func,
+               struct psi_decl_arg *darg,
                struct psi_call_frame_argument *frame_arg,
                struct psi_let_exp *inner_let_exp, void *container,
                struct psi_call_frame *frame)
 {
-       zval *zval_ptr;
+       zval *zval_ptr = NULL;
        psi_marshal_let let_fn;
        size_t i = 0, size;
        struct psi_decl_var *dvar;
@@ -287,7 +300,7 @@ void exec_let_func_arrval_seq(struct psi_let_func *func,
                impl_val val = {0}, *ptr, *sub;
 
                if (let_fn) {
-                       ptr = let_fn(&val, darg_type, 0, NULL, zval_ptr, &temp);
+                       ptr = let_fn(&val, darg, 0, NULL, zval_ptr, &temp);
                        if (temp) {
                                psi_call_frame_push_auto(frame, temp);
                        }
@@ -296,6 +309,7 @@ void exec_let_func_arrval_seq(struct psi_let_func *func,
                                        inner_let_exp->data.func, darg, frame);
                } else {
                        assert(0);
+                       return;
                }
 
                sub = deref_impl_val(ptr, dvar);
@@ -315,10 +329,9 @@ static void *exec_let_func_arrval(struct psi_let_exp *val,
 {
        void *container = NULL;
        struct psi_call_frame_argument *frame_arg;
-       struct psi_decl_type *darg_type;
        struct psi_plist *darg_members;
 
-       darg_members = psi_decl_type_get_args(darg->type, &darg_type);
+       darg_members = psi_decl_type_get_args(darg->type, NULL);
        frame_arg = psi_call_frame_get_argument(frame, func->var->fqn);
 
        if (frame_arg->zval_ptr && Z_TYPE_P(frame_arg->zval_ptr) != IS_ARRAY) {
@@ -342,11 +355,12 @@ static void *exec_let_func_arrval(struct psi_let_exp *val,
 
                if (frame_arg->zval_ptr) {
                        while (psi_plist_get(func->inner, i++, &inner)) {
-                               darg_member = psi_decl_arg_get_by_name(darg_members,
-                                               psi_let_exp_get_decl_var_name(inner));
+                               zend_string *var_name = psi_let_exp_get_decl_var_name(inner);
+                               darg_member = psi_decl_arg_get_by_name(darg_members, var_name);
 
                                exec_let_func_arrval_inner(func, darg, darg_member, frame_arg,
                                                inner, container, frame);
+                               zend_string_release(var_name);
                        }
                }
        } else if (func->inner) {
@@ -368,8 +382,7 @@ static void *exec_let_func_arrval(struct psi_let_exp *val,
                container = ecalloc(arcount + 1, psi_decl_var_get_size(inner->var));
                inner->var->pointer_level -= inner->is_reference;
 
-               exec_let_func_arrval_seq(func, darg, darg_type, frame_arg, inner,
-                               container, frame);
+               exec_let_func_arrval_seq(func, darg, frame_arg, inner, container, frame);
        } else {
                assert(0);
        }
@@ -393,8 +406,7 @@ void *psi_let_func_exec(struct psi_let_exp *val, struct psi_let_func *func,
 
                assert(iarg);
 
-               frame_sym->ival_ptr = let_fn(&frame_sym->temp_val,
-                               psi_decl_type_get_real(darg->type),
+               frame_sym->ival_ptr = let_fn(&frame_sym->temp_val, darg,
                                iarg->spec ? iarg->spec->type->type : 0, iarg->ival_ptr,
                                iarg->zval_ptr, &temp);
                if (temp) {