This commit is contained in:
Zeev Suraski 2001-08-13 00:28:18 +00:00
parent e8f4e4660c
commit 8722b31d8a
3 changed files with 61 additions and 125 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;
}
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;
}
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 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;
}
}
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;
}