Commit:    980dc7111bc1d1e759c5b6044f6e7d203915d81f
Author:    Gustavo André dos Santos Lopes <cataphr...@php.net>         Wed, 18 
Jul 2012 21:42:36 +0200
Parents:   94a0f8722b1f480f2cd8c0fc044cff40f2418607
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=980dc7111bc1d1e759c5b6044f6e7d203915d81f

Log:
zend_parse_parameters: allow ! for non pointers

This commit allows getting information about whether a certain value
was a NULL value by using the ! modifier together with the l/L, d and
b.

Example:
long l;
zend_bool is_null;
zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l!", &l, &is_null)

For the specifiers l/L, d and b, NULL values are reported as 0, 0., or
false. But sometimes one wants to distinguish NULL from those other
values -- for instance, to give NULL the same effect as the argument
not having been passed.

The usual way this problem is handled is by fetching the parameter
with 'z' or 'Z', check if it is NULL and if not use
convert_to_long_ex()/convert_to_double_ex(), etc. Unfortunately, this
is not equivalent. convert_to_long_ex() does a cast, while zpp() is
stricter. For instance, zpp will not accept 'foo' for a long argument,
and it will emit a notice when encountering '5foo'.

In fact, the only way to otherwise zpp semantics (without duplicating
its logic) is to fetch the raw zval from the stack and check whether
it's NULL (with zpp itself or its relatives) and then run zpp again.
That is not an elegant solution.

Changed paths:
  M  Zend/zend_API.c


Diff:
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 98a33e5..d7170eb 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -306,16 +306,14 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
 {
        const char *spec_walk = *spec;
        char c = *spec_walk++;
-       int return_null = 0;
+       int check_null = 0;
 
        /* scan through modifiers */
        while (1) {
                if (*spec_walk == '/') {
                        SEPARATE_ZVAL_IF_NOT_REF(arg);
                } else if (*spec_walk == '!') {
-                       if (Z_TYPE_PP(arg) == IS_NULL) {
-                               return_null = 1;
-                       }
+                       check_null = 1;
                } else {
                        break;
                }
@@ -327,6 +325,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'L':
                        {
                                long *p = va_arg(*va, long *);
+
+                               if (check_null) {
+                                       zend_bool *p = va_arg(*va, zend_bool *);
+                                       *p = (Z_TYPE_PP(arg) == IS_NULL);
+                               }
+
                                switch (Z_TYPE_PP(arg)) {
                                        case IS_STRING:
                                                {
@@ -380,6 +384,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'd':
                        {
                                double *p = va_arg(*va, double *);
+
+                               if (check_null) {
+                                       zend_bool *p = va_arg(*va, zend_bool *);
+                                       *p = (Z_TYPE_PP(arg) == IS_NULL);
+                               }
+
                                switch (Z_TYPE_PP(arg)) {
                                        case IS_STRING:
                                                {
@@ -418,7 +428,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                                int *pl = va_arg(*va, int *);
                                switch (Z_TYPE_PP(arg)) {
                                        case IS_NULL:
-                                               if (return_null) {
+                                               if (check_null) {
                                                        *p = NULL;
                                                        *pl = 0;
                                                        break;
@@ -462,6 +472,12 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'b':
                        {
                                zend_bool *p = va_arg(*va, zend_bool *);
+
+                               if (check_null) {
+                                       zend_bool *p = va_arg(*va, zend_bool *);
+                                       *p = (Z_TYPE_PP(arg) == IS_NULL);
+                               }
+
                                switch (Z_TYPE_PP(arg)) {
                                        case IS_NULL:
                                        case IS_STRING:
@@ -484,7 +500,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'r':
                        {
                                zval **p = va_arg(*va, zval **);
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                        break;
                                }
@@ -499,7 +515,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'a':
                        {
                                zval **p = va_arg(*va, zval **);
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                        break;
                                }
@@ -514,7 +530,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'h':
                        {
                                HashTable **p = va_arg(*va, HashTable **);
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                        break;
                                }
@@ -534,7 +550,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'o':
                        {
                                zval **p = va_arg(*va, zval **);
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                        break;
                                }
@@ -551,7 +567,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                                zval **p = va_arg(*va, zval **);
                                zend_class_entry *ce = va_arg(*va, 
zend_class_entry *);
 
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                        break;
                                }
@@ -573,7 +589,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                                zend_class_entry **lookup, **pce = va_arg(*va, 
zend_class_entry **);
                                zend_class_entry *ce_base = *pce;
 
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *pce = NULL;
                                        break;
                                }
@@ -607,7 +623,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                                zend_fcall_info_cache *fcc = va_arg(*va, 
zend_fcall_info_cache *);
                                char *is_callable_error = NULL;
 
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        fci->size = 0;
                                        fcc->initialized = 0;
                                        break;
@@ -637,7 +653,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'z':
                        {
                                zval **p = va_arg(*va, zval **);
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                } else {
                                        *p = *arg;
@@ -648,7 +664,7 @@ static const char *zend_parse_arg_impl(int arg_num, zval 
**arg, va_list *va, con
                case 'Z':
                        {
                                zval ***p = va_arg(*va, zval ***);
-                               if (return_null) {
+                               if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
                                        *p = NULL;
                                } else {
                                        *p = arg;


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to