summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>2001-08-13 00:28:18 +0000
committerZeev Suraski <zeev@php.net>2001-08-13 00:28:18 +0000
commit8722b31d8af773cd108eb3d3cf541b47c6a99db1 (patch)
tree3dd3affd9b5138db78e2258e4fcce994708a5c06
parente8f4e4660c1884ba36f5d7948a15b7ca559fccac (diff)
downloadphp-git-8722b31d8af773cd108eb3d3cf541b47c6a99db1.tar.gz
MFZE1
-rw-r--r--Zend/zend_API.c4
-rw-r--r--Zend/zend_operators.c92
-rw-r--r--Zend/zend_operators.h84
3 files changed, 58 insertions, 122 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 3145ce5987..7390aab7eb 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -239,7 +239,7 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec)
double d;
int type;
- if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d)) == 0) {
+ if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, 0)) == 0) {
return "long";
} else if (type == IS_DOUBLE) {
*p = (long) d;
@@ -273,7 +273,7 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec)
long l;
int type;
- if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p)) == 0) {
+ if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, 0)) == 0) {
return "double";
} else if (type == IS_LONG) {
*p = (double) l;
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 8ac4164420..42f0972600 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -114,7 +114,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
char *strval;
strval = op->value.str.val;
- switch ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval))) {
+ switch ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval, 1))) {
case IS_DOUBLE:
case IS_LONG:
break;
@@ -152,7 +152,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
switch ((op)->type) { \
case IS_STRING: \
{ \
- switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval))) { \
+ switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
case IS_DOUBLE: \
case IS_LONG: \
break; \
@@ -1456,7 +1456,7 @@ ZEND_API int increment_function(zval *op1)
double dval;
char *strval = op1->value.str.val;
- switch (is_numeric_string(strval, op1->value.str.len, &lval, &dval)) {
+ switch (is_numeric_string(strval, op1->value.str.len, &lval, &dval, 0)) {
case IS_LONG:
op1->value.lval = lval+1;
op1->type = IS_LONG;
@@ -1502,7 +1502,7 @@ ZEND_API int decrement_function(zval *op1)
op1->value.lval = -1;
op1->type = IS_LONG;
break;
- } else if (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, NULL)==IS_LONG) { /* long */
+ } else if (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, NULL, 0)==IS_LONG) { /* long */
STR_FREE(op1->value.str.val);
op1->value.lval = lval-1;
op1->type = IS_LONG;
@@ -1627,8 +1627,8 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
long lval1, lval2;
double dval1, dval2;
- if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1)) &&
- (ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2))) {
+ if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1, 0)) &&
+ (ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0))) {
#if 0&&WITH_BCMATH
if ((ret1==FLAG_IS_BC) || (ret2==FLAG_IS_BC)) {
bc_num first, second;
@@ -1703,83 +1703,3 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
}
zend_compare_symbol_tables(result, Z_OBJPROP_P(o1), Z_OBJPROP_P(o2) TSRMLS_CC);
}
-
-
-/* returns 0 for non-numeric string
- * returns IS_DOUBLE for floating point string, and assigns the value to *dval (if it's not NULL)
- * returns IS_LONG for integer strings, and assigns the value to *lval (if it's not NULL)
- * returns FLAG_IS_BC if the number might lose accuracy when converted to a double
- */
-
-#if 0
-
-static inline int is_numeric_string(char *str, int length, long *lval, double *dval)
-{
- register char *p=str, *end=str+length;
- unsigned char had_period=0, had_exponent=0;
- char *end_ptr;
-
- if (!length) {
- return 0;
- }
- switch (*p) {
- case '-':
- case '+':
- while (*++p==' '); /* ignore spaces after the sign */
- break;
- default:
- break;
- }
- while (p<end) {
- if (isdigit((int)(unsigned char)*p)) {
- p++;
- } else if (*p=='.') {
- if (had_period) {
- return 0;
- } else {
- had_period=1;
- p++;
- }
- } else if (*p=='e' || *p=='E') {
- p++;
- if (is_numeric_string(p, length - (int) (p-str), NULL, NULL)==IS_LONG) { /* valid exponent */
- had_exponent=1;
- break;
- } else {
- return 0;
- }
- } else {
- return 0;
- }
- }
- errno=0;
- if (had_period || had_exponent) { /* floating point number */
- double local_dval;
-
- local_dval = strtod(str, &end_ptr);
- if (errno==ERANGE || end_ptr != str+length) { /* overflow or bad string */
- return 0;
- } else {
- if (dval) {
- *dval = local_dval;
- }
- return IS_DOUBLE;
- }
- } else {
- long local_lval;
-
- local_lval = strtol(str, &end_ptr, 10);
- if (errno==ERANGE || end_ptr != str+length) { /* overflow or bad string */
- return 0;
- } else {
- if (lval) {
- *lval = local_lval;
- }
- return IS_LONG;
- }
- }
-}
-
-
-
-#endif
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index b1e2a4410e..3cc733a70d 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -58,11 +58,11 @@ ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
-static inline int is_numeric_string(char *str, int length, long *lval, double *dval)
+static inline int is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
{
long local_lval;
double local_dval;
- char *end_ptr;
+ char *end_ptr_long, *end_ptr_double;
int conv_base=10;
if (!length) {
@@ -74,12 +74,16 @@ static inline int is_numeric_string(char *str, int length, long *lval, double *d
conv_base=16;
}
errno=0;
- local_lval = strtol(str, &end_ptr, conv_base);
- if (errno!=ERANGE && end_ptr == str+length) { /* integer string */
- if (lval) {
- *lval = local_lval;
+ local_lval = strtol(str, &end_ptr_long, conv_base);
+ if (errno!=ERANGE) {
+ if (end_ptr_long == str+length) { /* integer string */
+ if (lval) {
+ *lval = local_lval;
+ }
+ return IS_LONG;
}
- return IS_LONG;
+ } else {
+ end_ptr_long=NULL;
}
if (conv_base==16) { /* hex string, under UNIX strtod() messes it up */
@@ -87,40 +91,52 @@ static inline int is_numeric_string(char *str, int length, long *lval, double *d
}
errno=0;
- local_dval = strtod(str, &end_ptr);
- if (errno!=ERANGE && end_ptr == str+length) { /* floating point string */
- if (! zend_finite(local_dval)) {
- /* "inf","nan" and maybe other weird ones */
- return 0;
- }
+ local_dval = strtod(str, &end_ptr_double);
+ if (errno!=ERANGE) {
+ if (end_ptr_double == str+length) { /* floating point string */
+ if (! zend_finite(local_dval)) {
+ /* "inf","nan" and maybe other weird ones */
+ return 0;
+ }
- if (dval) {
- *dval = local_dval;
- }
+ if (dval) {
+ *dval = local_dval;
+ }
#if 0&&WITH_BCMATH
- if (length>16) {
- register char *ptr=str, *end=str+length;
-
- while (ptr<end) {
- switch(*ptr++) {
- case 'e':
- case 'E':
- /* scientific notation, not handled by the BC library */
- return IS_DOUBLE;
- break;
- default:
- break;
+ if (length>16) {
+ register char *ptr=str, *end=str+length;
+
+ while (ptr<end) {
+ switch(*ptr++) {
+ case 'e':
+ case 'E':
+ /* scientific notation, not handled by the BC library */
+ return IS_DOUBLE;
+ break;
+ default:
+ break;
+ }
}
+ return FLAG_IS_BC;
+ } else {
+ return IS_DOUBLE;
}
- return FLAG_IS_BC;
- } else {
- return IS_DOUBLE;
- }
#else
- return IS_DOUBLE;
+ return IS_DOUBLE;
#endif
+ }
+ } else {
+ end_ptr_double=NULL;
+ }
+ if (allow_errors) {
+ if (end_ptr_double>end_ptr_long && dval) {
+ *dval = local_dval;
+ return IS_DOUBLE;
+ } else if (end_ptr_long && lval) {
+ *lval = local_lval;
+ return IS_LONG;
+ }
}
-
return 0;
}