]> granicus.if.org Git - php/commitdiff
Backport +/* vararg specifiers from PHP6
authorSara Golemon <pollita@php.net>
Mon, 29 Oct 2007 17:09:57 +0000 (17:09 +0000)
committerSara Golemon <pollita@php.net>
Mon, 29 Oct 2007 17:09:57 +0000 (17:09 +0000)
Zend/zend_API.c

index 2bc48cd3d094df0a38ac27811c8b3d92b681604c..f8ad2f3f2730d37e03caf4976b2e56e0672aaa6b 100644 (file)
@@ -639,10 +639,12 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
        int c, i;
        int min_num_args = -1;
        int max_num_args = 0;
+       int post_varargs = 0;
        zval **arg;
        void **p;
        int arg_count;
        int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
+       zend_bool have_varargs = 0;
 
        for (spec_walk = type_spec; *spec_walk; spec_walk++) {
                c = *spec_walk;
@@ -666,6 +668,29 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
                                /* Pass */
                                break;
 
+                       case '*':
+                       case '+':
+                               if (have_varargs) {
+                                       if (!quiet) {
+                                               zend_function *active_function = EG(function_state_ptr)->function;
+                                               char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
+                                               zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
+                                                               class_name,
+                                                               class_name[0] ? "::" : "",
+                                                               get_active_function_name(TSRMLS_C));
+                                       }
+                                       return FAILURE;
+                               }
+
+                               have_varargs = 1;
+                               /* we expect at least one parameter in varargs */
+                               if (c == '+') {
+                                       max_num_args++;
+                               }
+                               /* mark the beginning of varargs */
+                               post_varargs = max_num_args;
+                               break;
+
                        default:
                                if (!quiet) {
                                        zend_function *active_function = EG(function_state_ptr)->function;
@@ -683,7 +708,14 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
                min_num_args = max_num_args;
        }
 
-       if (num_args < min_num_args || num_args > max_num_args) {
+       if (have_varargs) {
+               /* calculate how many required args are at the end of the specifier list */
+               post_varargs = max_num_args - post_varargs;
+               max_num_args = -1;
+       }
+
+
+       if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
                if (!quiet) {
                        zend_function *active_function = EG(function_state_ptr)->function;
                        char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
@@ -714,6 +746,39 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
                if (*type_spec == '|') {
                        type_spec++;
                }
+
+               if (*type_spec == '*' || *type_spec == '+') {
+                       int num_varargs = num_args + 1 - post_varargs;
+
+                       /* eat up the passed in storage even if it won't be filled in with varargs */
+                       zval ****varargs   = (zval ****)va_arg(*va, zval ****);
+                       int     *n_varargs =  (int *)   va_arg(*va, int *);
+                       type_spec++;
+
+                       if (num_varargs > 0) {
+                               int iv = 0;
+                               zval **p = (zval **) (EG(argument_stack).top_element - 2 - (arg_count - i));
+
+                               *n_varargs = num_varargs;
+
+                               /* allocate space for array and store args */
+                               *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0);
+                               while (num_varargs-- > 0) {
+                                       (*varargs)[iv++] = p++;
+                               }
+
+                               /* adjust how many args we have left and restart loop */
+                               num_args = num_args + 1 - iv;
+                               i += iv;
+                               continue;
+                       } else {
+                               *varargs = NULL;
+                               *n_varargs = 0;
+                       }
+               }
+
+               arg = (zval **) (EG(argument_stack).top_element - 2 - (arg_count-i));
+
                if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
                        return FAILURE;
                }