Michael Wallner wrote:
> Hi,
> 
> I'd like to see zend_fcall_info_init() signature extended with an additional 
> 'zval *callable_name' argument.
> Additionally it seems that a vararg version of the zend_fcall_info_args() 
> function would be valuable too:

Please see attached patch.

Regards,
-- 
Michael
Index: Zend/zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.407
diff -u -p -d -r1.407 zend_API.c
--- Zend/zend_API.c     21 Sep 2006 23:58:06 -0000      1.407
+++ Zend/zend_API.c     4 Oct 2006 08:37:28 -0000
@@ -777,7 +777,7 @@ static char *zend_parse_arg_impl(int arg
                                        break;
                                } 
 
-                               if (zend_fcall_info_init(*arg, fci, fcc 
TSRMLS_CC) == SUCCESS) {
+                               if (zend_fcall_info_init(*arg, fci, fcc, NULL 
TSRMLS_CC) == SUCCESS) {
                                        break;
                                } else {
                                        return "valid callback";
@@ -2739,13 +2739,13 @@ ZEND_API zend_bool zend_make_callable(zv
 }
 
 
-ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, 
zend_fcall_info_cache *fcc TSRMLS_DC)
+ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, 
zend_fcall_info_cache *fcc, zval *callable_name TSRMLS_DC)
 {
        zend_class_entry *ce;
        zend_function    *func;
        zval             **obj;
 
-       if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, NULL, &ce, 
&func, &obj TSRMLS_CC)) {
+       if (!zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, 
&ce, &func, &obj TSRMLS_CC)) {
                return FAILURE;
        }
 
@@ -2767,20 +2767,41 @@ ZEND_API int zend_fcall_info_init(zval *
        return SUCCESS;
 }
 
-
-ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC)
+static inline void zend_fcall_info_args_clear(zend_fcall_info *fci, int 
free_mem)
 {
-       HashPosition pos;
-       zval         **arg, ***params;
-
        if (fci->params) {
                while (fci->param_count) {
                        zval_ptr_dtor(fci->params[--fci->param_count]);
                }
-               efree(fci->params);
+               if (free_mem) {
+                       efree(fci->params);
+                       fci->params = NULL;
+               }
        }
-       fci->params = NULL;
        fci->param_count = 0;
+}
+
+static inline void zend_fcall_info_args_save(zend_fcall_info *fci, int 
*param_count, zval ****params)
+{
+       *param_count = fci->param_count;
+       *params = fci->params;
+       fci->param_count = 0;
+       fci->params = NULL;
+}
+
+static inline void zend_fcall_info_args_restore(zend_fcall_info *fci, int 
param_count, zval ***params)
+{
+       zend_fcall_info_args_clear(fci, 1);
+       fci->param_count = param_count;
+       fci->params = params;
+}
+
+ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC)
+{
+       HashPosition pos;
+       zval         **arg, ***params;
+
+       zend_fcall_info_args_clear(fci, !args);
 
        if (!args) {
                return SUCCESS;
@@ -2791,18 +2812,45 @@ ZEND_API int zend_fcall_info_args(zend_f
        }
 
        fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
-       fci->params = params = (zval***)safe_emalloc(sizeof(zval**), 
fci->param_count, 0);
+       fci->params = params = (zval ***) erealloc(fci->params, 
fci->param_count * sizeof(zval **));
 
        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
-
-       while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &arg, 
&pos) == SUCCESS) {
+       while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, 
&pos) == SUCCESS) {
                *params++ = arg;
-               (*arg)->refcount++;
+               ZVAL_ADDREF(*arg);
                zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
        }
+
        return SUCCESS;
 }
 
+ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, 
...)
+{
+       int i;
+       zval **arg;
+       va_list argv;
+       
+       if (argc < 0) {
+               return FAILURE;
+       }
+       
+       zend_fcall_info_args_clear(fci, !argc);
+       
+       if (argc) {
+               fci->param_count = argc;
+               fci->params = (zval ***) erealloc(fci->params, fci->param_count 
* sizeof(zval **));
+               
+               va_start(argv, argc);
+               for (i = 0; i < argc; ++i) {
+                       arg = va_arg(argv, zval **);
+                       ZVAL_ADDREF(*arg);
+                       fci->params[i] = arg;
+               }
+               va_end(argv);
+       }
+       
+       return SUCCESS;
+}
 
 ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache 
*fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC)
 {
@@ -2811,8 +2859,7 @@ ZEND_API int zend_fcall_info_call(zend_f
 
        fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
        if (args) {
-               org_params = fci->params;
-               org_count = fci->param_count;
+               zend_fcall_info_args_save(fci, &org_count, &org_params);
                zend_fcall_info_args(fci, args TSRMLS_CC);
        }
        result = zend_call_function(fci, fcc TSRMLS_CC);
@@ -2821,9 +2868,7 @@ ZEND_API int zend_fcall_info_call(zend_f
                zval_ptr_dtor(&retval);
        }
        if (args) {
-               zend_fcall_info_args(fci, NULL TSRMLS_CC);
-               fci->params = org_params;
-               fci->param_count = org_count;
+               zend_fcall_info_args_restore(fci, org_count, org_params);
        }
        return result;
 }
Index: Zend/zend_API.h
===================================================================
RCS file: /repository/ZendEngine2/zend_API.h,v
retrieving revision 1.260
diff -u -p -d -r1.260 zend_API.h
--- Zend/zend_API.h     19 Sep 2006 10:38:30 -0000      1.260
+++ Zend/zend_API.h     4 Oct 2006 08:37:29 -0000
@@ -1229,14 +1229,21 @@ ZEND_API extern zend_fcall_info_cache em
  * In order to pass parameters the following members need to be set:
  * fci->param_count = 0;
  * fci->params = NULL;
+ * The callable_name argument may be NULL.
  */
-ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, 
zend_fcall_info_cache *fcc TSRMLS_DC);
+ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, 
zend_fcall_info_cache *fcc, zval *callable_name TSRMLS_DC);
 
 /** Set or clear the arguments in the zend_call_info struct taking care of
  * refcount. If args is NULL and arguments are set then those are cleared.
  */
 ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC);
 
+/** Set arguments in the zend_fcall_info struct taking care of refcount.
+ * If argc is 0 the arguments which are set will be cleared, else pass
+ * a variable amount of zval** arguments.
+ */
+ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, 
...);
+
 /** Call a function using information created by zend_fcall_info_init()/args().
  * If args is given then those replace the arguement info in fci is 
temporarily.
  */

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to