cvs: ZendEngine2 / zend_API.c php-src README.PARAMETER_PARSING_API
| From: | Andrei Zmievski | 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++;