]> granicus.if.org Git - php/commitdiff
- Ease writing functions that deal with php function 'pointers'
authorMarcus Boerger <helly@php.net>
Thu, 25 May 2006 22:20:13 +0000 (22:20 +0000)
committerMarcus Boerger <helly@php.net>
Thu, 25 May 2006 22:20:13 +0000 (22:20 +0000)
Zend/zend_API.c
Zend/zend_API.h

index 2ab16741a412162d619574053283f27383e07547..d500c0cec2020931c7269c5d1c2dceb81e1db1c8 100644 (file)
@@ -751,6 +751,22 @@ static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **sp
                        }
                        break;
 
+               case 'f':
+                       {
+                               zend_fcall_info       *fci = va_arg(*va, zend_fcall_info *);
+                               zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
+
+                               if (zend_fcall_info_init(*arg, fci, fcc TSRMLS_DC) == SUCCESS) {
+                                       break;
+                               } else if (return_null) {
+                                       fci->size = 0;
+                                       fcc->initialized = 0;
+                                       break;
+                               } else {
+                                       return "function";
+                               }
+                       }
+
                case 'z':
                        {
                                zval **p = va_arg(*va, zval **);
@@ -828,7 +844,7 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
                        case 't': case 'y':
                        case 'u': case 'C':
                        case 'h': case 'U':
-                       case 'S':
+                       case 'S': case 'f':
                                max_num_args++;
                                break;
 
@@ -2824,7 +2840,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zval *callable_name TSRMLS
        zend_class_entry **pce;
        int class_name_len;
 
-       if (zend_is_callable_ex(callable, 0, callable_name, NULL, NULL, NULL TSRMLS_CC)) {
+       if (zend_is_callable_ex(callable, IS_CALLABLE_STRICT, callable_name, NULL, NULL, NULL TSRMLS_CC)) {
                return 1;
        }
        switch (Z_TYPE_P(callable)) {
@@ -2852,6 +2868,88 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zval *callable_name TSRMLS
 }
 
 
+ZEND_API int zend_fcall_info_init(zval *callable, zend_fcall_info *fci, zend_fcall_info_cache *fcc 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)) {
+               return FAILURE;
+       }
+
+       fci->size = sizeof(*fci);
+       fci->function_table = ce ? &ce->function_table : EG(function_table);
+       fci->object_pp = obj;
+       fci->function_name = NULL;
+       fci->retval_ptr_ptr = NULL;
+       fci->param_count = 0;
+       fci->params = NULL;
+       fci->no_separation = 1;
+       fci->symbol_table = NULL;
+
+       fcc->initialized = 1;
+       fcc->function_handler = func;
+       fcc->calling_scope = ce;
+       fcc->object_pp = obj;
+
+       return SUCCESS;
+}
+
+
+ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC)
+{
+       HashPosition pos;
+       zval         **arg, ***params;
+
+       if (fci->params) {
+               efree(fci->params);
+       }
+       fci->params = NULL;
+       fci->param_count = 0;
+
+       if (!args) {
+               return SUCCESS;
+       }
+
+       if (Z_TYPE_P(args) != IS_ARRAY) {
+               return FAILURE;
+       }
+
+       fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
+       fci->params = params = (zval***)safe_emalloc(sizeof(zval**), fci->param_count, 0);
+
+       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) {
+               *params++ = arg;
+               zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
+       }
+       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)
+{
+       zval *retval;
+       int  result;
+
+       fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
+       if (args) {
+               zend_fcall_info_args(fci, args TSRMLS_CC);
+       }
+       result = zend_call_function(fci, fcc TSRMLS_CC);
+       
+       if (!retval_ptr_ptr && retval) {
+               zval_ptr_dtor(&retval);
+       }
+       if (args && fci->params) {
+               efree(fci->params);
+       }
+       return result;
+}
+
+
 ZEND_API char *zend_get_module_version(char *module_name)
 {
        zend_module_entry *module;
index 1ef01368a3461a4ec76611c543e679678319667d..541218b6765683269cfe5157c55f61db0a531df5 100644 (file)
@@ -653,8 +653,19 @@ typedef struct _zend_fcall_info_cache {
 BEGIN_EXTERN_C()
 ZEND_API extern zend_fcall_info_cache empty_fcall_info_cache;
 
-ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC);
+/* Build zend_call_info/cache from a zval*
+ *
+ * Caller is responsible to provide a return value, otherwise the we will crash. 
+ * fci->retval_ptr_ptr = NULL;
+ * In order to pass parameters the following members need to be set:
+ * fci->param_count = 0;
+ * fci->params = 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_args(zend_fcall_info *fci, zval *args TSRMLS_DC);
+ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval, zval *args TSRMLS_DC);
 
+ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TSRMLS_DC);
 
 ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
                                   zend_bool is_ref, int num_symbol_tables, ...);