mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Backport +/* vararg specifiers from PHP6
This commit is contained in:
parent
19bf724c48
commit
b38282c3fd
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user