summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Zmievski <andrei@php.net>2001-07-09 18:51:29 +0000
committerAndrei Zmievski <andrei@php.net>2001-07-09 18:51:29 +0000
commit58f88057b1f16fba975bf48a8996627520e5a84e (patch)
tree3bcf64e0d2117f2964a2bfb7f8ff6b952fed4c01
parent9f3110ea32f489af972d574c5bec46108774778a (diff)
downloadphp-git-58f88057b1f16fba975bf48a8996627520e5a84e.tar.gz
Adding new parameter parsing API.
-rw-r--r--Zend/zend_API.c394
-rw-r--r--Zend/zend_API.h11
2 files changed, 405 insertions, 0 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index a4c9d7ec9b..3ccc557056 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -14,6 +14,7 @@
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
+ | Andrei Zmievski <andrei@php.net> |
+----------------------------------------------------------------------+
*/
@@ -182,7 +183,400 @@ ZEND_API void wrong_param_count()
zend_error(E_WARNING,"Wrong parameter count for %s()",get_active_function_name());
}
+
+/* Argument parsing API -- andrei */
+
+static char *zend_zval_type_name(zval *arg)
+{
+ switch (Z_TYPE_P(arg)) {
+ case IS_NULL:
+ return "null";
+
+ case IS_LONG:
+ return "integer";
+
+ case IS_DOUBLE:
+ return "double";
+
+ case IS_STRING:
+ return "string";
+
+ case IS_ARRAY:
+ return "array";
+
+ case IS_OBJECT:
+ return "object";
+
+ case IS_BOOL:
+ return "boolean";
+
+ case IS_RESOURCE:
+ return "resource";
+
+ default:
+ return "unknown";
+ }
+}
+
+static int zend_check_class(zval *obj, zend_class_entry *expected_ce)
+{
+ zend_class_entry *ce;
+
+ if (Z_TYPE_P(obj) != IS_OBJECT) {
+ return 0;
+ }
+
+ for (ce = Z_OBJCE_P(obj); ce != NULL; ce = ce->parent) {
+ if (ce == expected_ce) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec)
+{
+ char *spec_walk = *spec;
+ char c = *spec_walk++;
+ int return_null = 0;
+
+ while (*spec_walk == '/' || *spec_walk == '!') {
+ if (*spec_walk == '/') {
+ SEPARATE_ZVAL_IF_NOT_REF(arg);
+ } else if (*spec_walk == '!' && Z_TYPE_PP(arg) == IS_NULL) {
+ return_null = 1;
+ }
+ spec_walk++;
+ }
+
+ switch (c) {
+ case 'l':
+ {
+ long *p = va_arg(*va, long *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_STRING:
+ {
+ double d;
+ int type;
+
+ if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d)) == 0) {
+ return "long";
+ } else if (type == IS_DOUBLE) {
+ *p = (long) d;
+ }
+ }
+ break;
+
+ case IS_NULL:
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ convert_to_long_ex(arg);
+ *p = Z_LVAL_PP(arg);
+ break;
+
+ case IS_ARRAY:
+ case IS_OBJECT:
+ case IS_RESOURCE:
+ default:
+ return "long";
+ }
+ }
+ break;
+
+ case 'd':
+ {
+ double *p = va_arg(*va, double *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_STRING:
+ {
+ long l;
+ int type;
+
+ if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p)) == 0) {
+ return "double";
+ } else if (type == IS_LONG) {
+ *p = (double) l;
+ }
+ }
+ break;
+
+ case IS_NULL:
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ convert_to_double_ex(arg);
+ *p = Z_LVAL_PP(arg);
+ break;
+
+ case IS_ARRAY:
+ case IS_OBJECT:
+ case IS_RESOURCE:
+ default:
+ return "double";
+ }
+ }
+ break;
+
+ case 's':
+ {
+ char **p = va_arg(*va, char **);
+ int *pl = va_arg(*va, int *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ if (return_null) {
+ *p = NULL;
+ *pl = 0;
+ break;
+ }
+ /* break omitted intentionally */
+
+ case IS_STRING:
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ convert_to_string_ex(arg);
+ *p = Z_STRVAL_PP(arg);
+ *pl = Z_STRLEN_PP(arg);
+ break;
+
+ case IS_ARRAY:
+ case IS_OBJECT:
+ case IS_RESOURCE:
+ default:
+ return "string";
+ }
+ }
+ break;
+
+ case 'b':
+ {
+ zend_bool *p = va_arg(*va, zend_bool *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ case IS_STRING:
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ convert_to_boolean_ex(arg);
+ *p = Z_BVAL_PP(arg);
+ break;
+
+ case IS_ARRAY:
+ case IS_OBJECT:
+ case IS_RESOURCE:
+ default:
+ return "boolean";
+ }
+ }
+ break;
+
+ case 'r':
+ {
+ zval **p = va_arg(*va, zval **);
+ if (Z_TYPE_PP(arg) != IS_RESOURCE) {
+ if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
+ *p = NULL;
+ } else {
+ return "resource";
+ }
+ } else
+ *p = *arg;
+ }
+ break;
+
+ case 'a':
+ {
+ zval **p = va_arg(*va, zval **);
+ if (Z_TYPE_PP(arg) != IS_ARRAY) {
+ if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
+ *p = NULL;
+ } else {
+ return "array";
+ }
+ } else
+ *p = *arg;
+ }
+ break;
+
+ case 'o':
+ {
+ zval **p = va_arg(*va, zval **);
+ if (Z_TYPE_PP(arg) != IS_OBJECT) {
+ if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
+ *p = NULL;
+ } else {
+ return "object";
+ }
+ } else
+ *p = *arg;
+ }
+ break;
+
+ case 'O':
+ {
+ zval **p = va_arg(*va, zval **);
+ zend_class_entry *ce = va_arg(*va, zend_class_entry *);
+ if (Z_TYPE_PP(arg) != IS_OBJECT || !zend_check_class(*arg, ce)) {
+ if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
+ *p = NULL;
+ } else {
+ return ce->name;
+ }
+ } else
+ *p = *arg;
+ }
+ break;
+
+ case 'z':
+ {
+ zval **p = va_arg(*va, zval **);
+ if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
+ *p = NULL;
+ } else {
+ *p = *arg;
+ }
+ }
+ break;
+
+ default:
+ return "unknown";
+ }
+
+ *spec = spec_walk;
+
+ return NULL;
+}
+
+static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet)
+{
+ char *expected_type = NULL;
+ char buf[1024];
+
+ expected_type = zend_parse_arg_impl(arg, va, spec);
+ if (expected_type) {
+ if (!quiet) {
+ sprintf(buf, "%s() expects argument %d to be %s, %s given",
+ get_active_function_name(), arg_num, expected_type,
+ zend_zval_type_name(*arg));
+ zend_error(E_WARNING, buf);
+ }
+ return FAILURE;
+ }
+
+ return SUCCESS;
+}
+
+static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags)
+{
+ char *spec_walk;
+ char buf[1024];
+ int c, i;
+ int min_num_args = -1;
+ int max_num_args = 0;
+ zval **arg;
+ void **p;
+ int arg_count;
+ int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
+ ELS_FETCH();
+
+ for (spec_walk = type_spec; *spec_walk; spec_walk++) {
+ c = *spec_walk;
+ switch (c) {
+ case 'l': case 'd':
+ case 's': case 'b':
+ case 'r': case 'a':
+ case 'o': case 'O':
+ case 'z':
+ max_num_args++;
+ break;
+
+ case '|':
+ min_num_args = max_num_args;
+ break;
+
+ case '/':
+ case '!':
+ /* Pass */
+ break;
+
+ default:
+ if (!quiet) {
+ zend_error(E_WARNING, "%s(): bad type specifier while parsing arguments", get_active_function_name());
+ }
+ return FAILURE;
+ }
+ }
+
+ if (min_num_args < 0) {
+ min_num_args = max_num_args;
+ }
+
+ if (num_args < min_num_args || num_args > max_num_args) {
+ if (!quiet) {
+ sprintf(buf, "%s() requires %s %d argument%s, %d given",
+ get_active_function_name(),
+ min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
+ num_args < min_num_args ? min_num_args : max_num_args,
+ (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
+ num_args);
+ zend_error(E_WARNING, buf);
+ }
+ return FAILURE;
+ }
+
+ p = EG(argument_stack).top_element-2;
+ arg_count = (ulong) *p;
+
+ if (num_args > arg_count) {
+ zend_error(E_WARNING, "%s(): could not obtain arguments for parsing",
+ get_active_function_name());
+ return FAILURE;
+ }
+
+ i = 0;
+ while (num_args-- > 0) {
+ arg = (zval **) p - (arg_count-i);
+ if (*type_spec == '|') {
+ type_spec++;
+ }
+ if (zend_parse_arg(i+1, arg, va, &type_spec, quiet) == FAILURE) {
+ return FAILURE;
+ }
+ i++;
+ }
+
+ return SUCCESS;
+}
+
+ZEND_API int zend_parse_parameters_ex(int flags, int num_args, char *type_spec, ...)
+{
+ va_list va;
+ int retval;
+ va_start(va, type_spec);
+ retval = zend_parse_va_args(num_args, type_spec, &va, flags);
+ va_end(va);
+
+ return retval;
+}
+
+ZEND_API int zend_parse_parameters(int num_args, char *type_spec, ...)
+{
+ va_list va;
+ int retval;
+
+ va_start(va, type_spec);
+ retval = zend_parse_va_args(num_args, type_spec, &va, 0);
+ va_end(va);
+
+ return retval;
+}
+
+/* Argument parsing API -- andrei */
+
+
ZEND_API inline int _array_init(zval *arg ZEND_FILE_LINE_DC)
{
ALLOC_HASHTABLE_REL(arg->value.ht);
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 38717a4577..52e60d8dd6 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -14,6 +14,7 @@
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <andi@zend.com> |
| Zeev Suraski <zeev@zend.com> |
+ | Andrei Zmievski <andrei@php.net> |
+----------------------------------------------------------------------+
*/
@@ -111,6 +112,16 @@ ZEND_API int zend_get_parameters_array(int ht, int param_count, zval **argument_
ZEND_API int zend_get_parameters_ex(int param_count, ...);
ZEND_API int zend_get_parameters_array_ex(int param_count, zval ***argument_array);
+
+/* Parameter parsing API -- andrei */
+
+#define ZEND_PARSE_PARAMS_QUIET 1<<1
+ZEND_API int zend_parse_parameters(int num_args, char *type_spec, ...);
+ZEND_API int zend_parse_parameters_ex(int flags, int num_args, char *type_spec, ...);
+
+/* Parameter parsing API -- andrei */
+
+
ZEND_API int ParameterPassedByReference(int ht, uint n);
int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type);