cvs: ZendEngine2 / zend_API.c php-src README.PARAMETER_PARSING_API

From: Date: Tue, 18 Jul 2006 22:07:20 +0000
Subject: cvs: ZendEngine2 / zend_API.c php-src README.PARAMETER_PARSING_API
Groups: php.zend-engine.cvs 
Request: Send a blank email to php-zend-engine-cvs+get-5086@lists.php.net to get a copy of this message
andrei Tue Jul 18 22:07:20 2006 UTC Modified files: /php-src README.PARAMETER_PARSING_API /ZendEngine2 zend_API.c Log: Implement varargs parameter parsing. See README for examples. http://cvs.php.net/viewvc.cgi/php-src/README.PARAMETER_PARSING_API?r1=1.12&r2=1.13&diff_format=u Index: php-src/README.PARAMETER_PARSING_API diff -u php-src/README.PARAMETER_PARSING_API:1.12 php-src/README.PARAMETER_PARSING_API:1.13 --- php-src/README.PARAMETER_PARSING_API:1.12 Wed Jul 12 07:31:56 2006 +++ php-src/README.PARAMETER_PARSING_API Tue Jul 18 22:07:20 2006 @@ -59,6 +59,7 @@ U - Unicode string, does not allow conversion from binary strings z - the actual zval (zval*) Z - the actual zval (zval**) + * - variable arguments list The following characters also have a meaning in the specifier string: | - indicates that the remaining parameters are optional, they @@ -185,3 +186,41 @@ return; } + +/* Function that accepts only varargs */ + +int i, num_varargs; +zval ***varargs = NULL; + + +if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &varargs, &num_varargs) == FAILURE) { + return; +} + +for (i = 0; i < num_varargs; i++) { + /* do something with varargs[i] */ +} + +if (varargs) { + efree(varargs); +} + + +/* Function that takes an array, followed by varargs, and ending with a long */ +long num; +zval *array; +int i, num_varargs; +zval ***varargs = NULL; + +if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) { + return; +} + +for (i = 0; i < num_varargs; i++) { + /* do something with varargs[i] */ +} + +if (varargs) { + efree(varargs); +} + http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_API.c?r1=1.380&r2=1.381&diff_format=u Index: ZendEngine2/zend_API.c diff -u ZendEngine2/zend_API.c:1.380 ZendEngine2/zend_API.c:1.381 --- ZendEngine2/zend_API.c:1.380 Tue Jul 18 17:52:44 2006 +++ ZendEngine2/zend_API.c Tue Jul 18 22:07:20 2006 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_API.c,v 1.380 2006/07/18 17:52:44 andrei Exp $ */ +/* $Id: zend_API.c,v 1.381 2006/07/18 22:07:20 andrei Exp $ */ #include "zend.h" #include "zend_execute.h" @@ -823,12 +823,16 @@ 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; zend_bool T_present = 0; char T_arg_type = -1; + zval ****varargs = NULL; + int *n_varargs = NULL; for (spec_walk = type_spec; *spec_walk; spec_walk++) { c = *spec_walk; @@ -857,13 +861,27 @@ /* Pass */ break; + case '*': + if (have_varargs) { + if (!quiet) { + char *space; + zstr class_name = get_active_class_name(&space TSRMLS_CC); + zend_error(E_WARNING, "%v%s%v(): only one varargs specifier '*' is permitted", + class_name, space, get_active_function_name(TSRMLS_C)); + } + return FAILURE; + } + have_varargs = 1; + /* mark the beginning of varargs */ + post_varargs = max_num_args; + break; + default: if (!quiet) { char *space; zstr class_name = get_active_class_name(&space TSRMLS_CC); zend_error(E_WARNING, "%v%s%v(): bad type specifier while parsing parameters", - class_name, space, - get_active_function_name(TSRMLS_C)); + class_name, space, get_active_function_name(TSRMLS_C)); } return FAILURE; } @@ -873,7 +891,13 @@ 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) { char *space; zstr class_name = get_active_class_name(&space TSRMLS_CC); @@ -917,6 +941,10 @@ /* pass */ break; + case '*': + i = arg_count - post_varargs; + break; + default: i++; break; @@ -926,11 +954,46 @@ i = 0; while (num_args-- > 0) { - arg = (zval **) p - (arg_count-i); if (*type_spec == '|') { type_spec++; } + + if (*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 */ + varargs = va_arg(*va, zval ****); + n_varargs = va_arg(*va, int *); + type_spec++; + + if (num_varargs > 0) { + int iv = 0; + *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++] = (zval **) p - (arg_count-i); + i++; + } + + /* adjust how many args we have left and restart loop */ + num_args = num_args + 1 - iv; + continue; + } else { + *varargs = NULL; + *n_varargs = 0; + } + } + + arg = (zval **) p - (arg_count-i); + if (zend_parse_arg(i+1, arg, va, &type_spec, quiet, T_arg_type TSRMLS_CC) == FAILURE) { + /* clean up varargs array if it was used */ + if (varargs && *varargs) { + efree(*varargs); + *varargs = NULL; + } return FAILURE; } i++;

« previous php.zend-engine.cvs (#5086) next »