prepare varargs calls
[m6w6/ext-psi] / src / module.c
index bde40a4524244c2c8bc90d074cfffeeb10186d68..ba3e4d5a98d5af9478ae3fa172d5a482c7f72d58 100644 (file)
@@ -11,8 +11,6 @@
 #include "zend_operators.h"
 
 #include "php_psi.h"
-#include "parser.h"
-#include "context.h"
 
 #if HAVE_LIBJIT
 # include "libjit.h"
@@ -124,13 +122,26 @@ zend_internal_arg_info *psi_internal_arginfo(impl *impl)
        zend_internal_arg_info *aip;
        zend_internal_function_info *fi;
 
-       aip = calloc(impl->func->args->count + 1, sizeof(*aip));
+       aip = calloc(impl->func->args->count + 1 + !!impl->func->args->vararg, sizeof(*aip));
 
        fi = (zend_internal_function_info *) &aip[0];
+       fi->allow_null = 1;
        fi->required_num_args = psi_num_min_args(impl);
        fi->return_reference = impl->func->return_reference;
        fi->type_hint = psi_internal_type(impl->func->return_type);
 
+       if (impl->func->args->vararg) {
+               impl_arg *vararg = impl->func->args->vararg;
+               zend_internal_arg_info *ai = &aip[impl->func->args->count];
+
+               ai->name = vararg->var->name;
+               ai->type_hint = psi_internal_type(vararg->type);
+               if (vararg->var->reference) {
+                       ai->pass_by_reference = 1;
+               }
+               ai->is_variadic = 1;
+       }
+
        for (i = 0; i < impl->func->args->count; ++i) {
                impl_arg *iarg = impl->func->args->args[i];
                zend_internal_arg_info *ai = &aip[i+1];
@@ -479,7 +490,7 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i
                return rv;
        }
 
-       ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->count)
+       ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->vararg ? -1 : impl->func->args->count)
        nextarg:
                iarg = impl->func->args->args[_i];
                if (iarg->def) {
@@ -504,6 +515,20 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i
                        error_code = ZPP_ERROR_FAILURE;
                        break;
                }
+               if (impl->func->args->vararg) {
+                       iarg = impl->func->args->vararg;
+
+                       if (_i == impl->func->args->count) {
+                               zval *ptr = iarg->_zv = calloc(_num_args - _i + 1, sizeof(zval));
+
+                               _optional = 1;
+                               while (_i < _num_args) {
+                                       Z_PARAM_PROLOGUE(0);
+                                       ZVAL_COPY_VALUE(ptr++, _arg);
+                               }
+                               break;
+                       }
+               }
                if (_i < _num_args) {
                        goto nextarg;
                }
@@ -678,7 +703,6 @@ static inline void psi_do_return(zval *return_value, return_stmt *ret)
 static inline void psi_do_free(free_stmt *fre)
 {
        size_t i, j;
-       impl_val dummy;
 
        for (i = 0; i < fre->calls->count; ++i) {
                free_call *f = fre->calls->list[i];
@@ -691,7 +715,7 @@ static inline void psi_do_free(free_stmt *fre)
                }
 
                /* FIXME: check in validate_* that free functions return scalar */
-               PSI_ContextCall(&PSI_G(context), &dummy, f->decl);
+               PSI_ContextCall(&PSI_G(context), &f->decl->call);
        }
 }
 
@@ -982,7 +1006,7 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl)
                impl->decl->call.args[i] = impl->decl->args->args[i]->let->ptr;
        }
 
-       PSI_ContextCall(&PSI_G(context), var->arg->ptr, impl->decl);
+       PSI_ContextCall(&PSI_G(context), &impl->decl->call);
        psi_do_return(return_value, ret);
 
        for (i = 0; i < impl->stmts->set.count; ++i) {