diff options
-rw-r--r-- | client/mysql.cc | 4 | ||||
-rw-r--r-- | include/m_string.h | 2 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 3 | ||||
-rw-r--r-- | mysql-test/r/ps_1general.result | 1 | ||||
-rw-r--r-- | mysql-test/r/type_float.result | 34 | ||||
-rw-r--r-- | mysql-test/t/mysql_client_test.test | 7 | ||||
-rw-r--r-- | mysql-test/t/ps_1general.test | 1 | ||||
-rw-r--r-- | mysql-test/t/type_float.test | 26 | ||||
-rw-r--r-- | sql/field.cc | 14 | ||||
-rw-r--r-- | sql/item.cc | 11 | ||||
-rw-r--r-- | sql/item.h | 6 | ||||
-rw-r--r-- | sql/item_func.h | 7 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 3 | ||||
-rw-r--r-- | sql/item_sum.cc | 3 | ||||
-rw-r--r-- | sql/item_sum.h | 6 | ||||
-rw-r--r-- | sql/procedure.h | 11 | ||||
-rw-r--r-- | strings/ctype-simple.c | 27 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 9 | ||||
-rw-r--r-- | strings/strtod.c | 167 |
19 files changed, 239 insertions, 103 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 4004757359b..1bbab75434c 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2914,9 +2914,9 @@ com_status(String *buffer __attribute__((unused)), MYSQL_ROW cur=mysql_fetch_row(result); if (cur) { - tee_fprintf(stdout, "Server characterset:\t%s\n", cur[0] ? cur[2] : ""); + tee_fprintf(stdout, "Server characterset:\t%s\n", cur[2] ? cur[2] : ""); tee_fprintf(stdout, "Db characterset:\t%s\n", cur[3] ? cur[3] : ""); - tee_fprintf(stdout, "Client characterset:\t%s\n", cur[2] ? cur[0] : ""); + tee_fprintf(stdout, "Client characterset:\t%s\n", cur[0] ? cur[0] : ""); tee_fprintf(stdout, "Conn. characterset:\t%s\n", cur[1] ? cur[1] : ""); } mysql_free_result(result); diff --git a/include/m_string.h b/include/m_string.h index 97d34421537..d3465363beb 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -215,7 +215,7 @@ extern char *strstr(const char *, const char *); extern int is_prefix(const char *, const char *); /* Conversion routines */ -double my_strtod(const char *str, char **end); +double my_strtod(const char *str, char **end, int *error); double my_atof(const char *nptr); extern char *llstr(longlong value,char *buff); diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index af432f37868..8c484d2ddb1 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -444,6 +444,7 @@ while test $# -gt 0; do --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqldump.trace" EXTRA_MYSQLBINLOG_OPT="$EXTRA_MYSQLBINLOG_OPT \ --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlbinlog.trace" + EXTRA_MYSQL_CLIENT_TEST_OPT="--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysql_client_test.trace" ;; --fast) FAST_START=1 @@ -681,7 +682,7 @@ then EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --user=root" fi -MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent" +MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT" MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 2356989eaf6..ec4aa528a7f 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -1,5 +1,6 @@ drop table if exists t5, t6, t7, t8; drop database if exists mysqltest ; +drop database if exists client_test_db; test_sequence ------ basic tests ------ drop table if exists t1, t9 ; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 1f5a34917d7..c1cefe4b35d 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1,t2; SELECT 10,10.0,10.,.1e+2,100.0e-1; 10 10.0 10. .1e+2 100.0e-1 10 10.0 10 10 10 @@ -8,6 +8,15 @@ SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000; SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1; 1e1 1.e1 1.0e1 1e+1 1.e+1 1.0e+1 1e-1 1.e-1 1.0e-1 10 10 10 10 10 10 0.1 0.1 0.1 +SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01; +0.001e+1 0.001e-1 -0.001e+01 -0.001e-01 +0.01 0.0001 -0.01 -0.0001 +SELECT 123.23E+02,-123.23E-02,"123.23E+02"+0.0,"-123.23E-02"+0.0; +123.23E+02 -123.23E-02 "123.23E+02"+0.0 "-123.23E-02"+0.0 +12323 -1.2323 12323 -1.2323 +SELECT 2147483647E+02,21474836.47E+06; +2147483647E+02 21474836.47E+06 +214748364700 21474836470000 create table t1 (f1 float(24),f2 float(52)); show full columns from t1; Field Type Collation Null Key Default Extra Privileges Comment @@ -139,6 +148,9 @@ create table t1 (c20 char); insert into t1 values (5000.0); Warnings: Warning 1265 Data truncated for column 'c20' at row 1 +insert into t1 values (0.5e4); +Warnings: +Warning 1265 Data truncated for column 'c20' at row 1 drop table t1; create table t1 (f float(54)); ERROR 42000: Incorrect column specifier for column 'f' @@ -203,3 +215,23 @@ c 0.0002 2e-05 drop table t1; +CREATE TABLE t1 ( +reckey int unsigned NOT NULL, +recdesc varchar(50) NOT NULL, +PRIMARY KEY (reckey) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES (108, 'Has 108 as key'); +INSERT INTO t1 VALUES (109, 'Has 109 as key'); +select * from t1 where reckey=108; +reckey recdesc +108 Has 108 as key +select * from t1 where reckey=1.08E2; +reckey recdesc +108 Has 108 as key +select * from t1 where reckey=109; +reckey recdesc +109 Has 109 as key +select * from t1 where reckey=1.09E2; +reckey recdesc +109 Has 109 as key +drop table t1; diff --git a/mysql-test/t/mysql_client_test.test b/mysql-test/t/mysql_client_test.test index 86aecf43cbd..3639fc2e262 100644 --- a/mysql-test/t/mysql_client_test.test +++ b/mysql-test/t/mysql_client_test.test @@ -1,3 +1,10 @@ # We run with different binaries for normal and --embedded-server +# +# If this test fails with "command "$MYSQL_CLIENT_TEST" failed", +# you should either run mysql_client_test separartely against a running +# server or run mysql-test-run --debug mysql_client_test and check +# var/log/mysql_client_test.trace + --disable_result_log +--exec echo $MYSQL_CLIENT_TEST --exec $MYSQL_CLIENT_TEST diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test index 4ab81dfcac5..b3ce6d7fd82 100644 --- a/mysql-test/t/ps_1general.test +++ b/mysql-test/t/ps_1general.test @@ -11,6 +11,7 @@ --disable_warnings drop table if exists t5, t6, t7, t8; drop database if exists mysqltest ; +drop database if exists client_test_db; --enable_warnings --disable_query_log diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 5b106d242de..6e991dc53d4 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -3,7 +3,7 @@ # Numeric floating point. --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; --enable_warnings --replace_result e-0 e- e+0 e+ @@ -11,6 +11,9 @@ SELECT 10,10.0,10.,.1e+2,100.0e-1; --replace_result e-00 e-0 SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000; SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1; +SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01; +SELECT 123.23E+02,-123.23E-02,"123.23E+02"+0.0,"-123.23E-02"+0.0; +SELECT 2147483647E+02,21474836.47E+06; create table t1 (f1 float(24),f2 float(52)); show full columns from t1; @@ -83,6 +86,7 @@ drop table t1; # create table t1 (c20 char); insert into t1 values (5000.0); +insert into t1 values (0.5e4); drop table t1; # Errors @@ -120,3 +124,23 @@ create table t1 (c char(6)); insert into t1 values (2e5),(2e6),(2e-4),(2e-5); select * from t1; drop table t1; + +# +# Test of comparison of integer with float-in-range (Bug #7840) +# This is needed because some ODBC applications (like Foxpro) uses +# floats for everything. +# + +CREATE TABLE t1 ( + reckey int unsigned NOT NULL, + recdesc varchar(50) NOT NULL, + PRIMARY KEY (reckey) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +INSERT INTO t1 VALUES (108, 'Has 108 as key'); +INSERT INTO t1 VALUES (109, 'Has 109 as key'); +select * from t1 where reckey=108; +select * from t1 where reckey=1.08E2; +select * from t1 where reckey=109; +select * from t1 where reckey=1.09E2; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index fa0e202d513..ca923d723bc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -968,7 +968,9 @@ int Field_decimal::store(longlong nr) double Field_decimal::val_real(void) { int not_used; - return my_strntod(&my_charset_bin, ptr, field_length, NULL, ¬_used); + char *end_not_used; + return my_strntod(&my_charset_bin, ptr, field_length, &end_not_used, + ¬_used); } longlong Field_decimal::val_int(void) @@ -4360,8 +4362,9 @@ int Field_string::store(longlong nr) double Field_string::val_real(void) { int not_used; + char *end_not_used; CHARSET_INFO *cs=charset(); - return my_strntod(cs,ptr,field_length,(char**)0,¬_used); + return my_strntod(cs, ptr, field_length, &end_not_used, ¬_used); } @@ -4577,7 +4580,9 @@ double Field_varstring::val_real(void) int not_used; uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH; CHARSET_INFO *cs=charset(); - return my_strntod(cs, ptr+HA_KEY_BLOB_LENGTH, length, (char**)0, ¬_used); + char *end_not_used; + return my_strntod(cs, ptr+HA_KEY_BLOB_LENGTH, length, &end_not_used, + ¬_used); } @@ -4955,12 +4960,13 @@ double Field_blob::val_real(void) { int not_used; char *blob; + char *end_not_used; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) return 0.0; uint32 length=get_length(ptr); CHARSET_INFO *cs=charset(); - return my_strntod(cs,blob,length,(char**)0, ¬_used); + return my_strntod(cs,blob,length, &end_not_used, ¬_used); } diff --git a/sql/item.cc b/sql/item.cc index 4b3acbe5a3c..76cbaa99029 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1140,8 +1140,9 @@ double Item_param::val() case LONG_DATA_VALUE: { int dummy_err; + char *end_not_used; return my_strntod(str_value.charset(), (char*) str_value.ptr(), - str_value.length(), (char**) 0, &dummy_err); + str_value.length(), &end_not_used, &dummy_err); } case TIME_VALUE: /* @@ -2585,10 +2586,12 @@ double Item_cache_str::val() DBUG_ASSERT(fixed == 1); int err; if (value) + { + char *end_not_used; return my_strntod(value->charset(), (char*) value->ptr(), - value->length(), (char**) 0, &err); - else - return (double)0; + value->length(), &end_not_used, &err); + } + return (double)0; } diff --git a/sql/item.h b/sql/item.h index dd06d4ce61a..97e2b0c0945 100644 --- a/sql/item.h +++ b/sql/item.h @@ -719,8 +719,9 @@ public: { DBUG_ASSERT(fixed == 1); int err; + char *end_not_used; return my_strntod(str_value.charset(), (char*) str_value.ptr(), - str_value.length(), (char**) 0, &err); + str_value.length(), &end_not_used, &err); } longlong val_int() { @@ -1044,9 +1045,10 @@ public: double val() { int err; + char *end_not_used; return (null_value ? 0.0 : my_strntod(str_value.charset(), (char*) str_value.ptr(), - str_value.length(),NULL,&err)); + str_value.length(), &end_not_used, &err)); } longlong val_int() { diff --git a/sql/item_func.h b/sql/item_func.h index 8a5347d675e..2738c7419ca 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -828,8 +828,11 @@ public: double val() { int err; - String *res; res=val_str(&str_value); - return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(),0,&err) : 0.0; + String *res; + char *end_not_used; + res=val_str(&str_value); + return res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(), + &end_not_used, &err) : 0.0; } longlong val_int() { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index bbbcadbb071..8bd1da4e15f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -63,10 +63,11 @@ double Item_str_func::val() DBUG_ASSERT(fixed == 1); int err; char buff[64]; + char *end_not_used; String *res, tmp(buff,sizeof(buff), &my_charset_bin); res= val_str(&tmp); return res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(), - NULL, &err) : 0.0; + &end_not_used, &err) : 0.0; } longlong Item_str_func::val_int() diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 029a1fd6c48..6bd2cc00b3e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -471,13 +471,14 @@ double Item_sum_hybrid::val() { DBUG_ASSERT(fixed == 1); int err; + char *end_not_used; if (null_value) return 0.0; switch (hybrid_type) { case STRING_RESULT: String *res; res=val_str(&str_value); return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(), - (char**) 0, &err) : 0.0); + &end_not_used, &err) : 0.0); case INT_RESULT: if (unsigned_flag) return ulonglong2double(sum_int); diff --git a/sql/item_sum.h b/sql/item_sum.h index d1e82387944..dab136e4716 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -600,9 +600,11 @@ public: double val() { int err; - String *res; res=val_str(&str_value); + char *end_not_used; + String *res; + res=val_str(&str_value); return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(), - (char**) 0, &err) : 0.0; + &end_not_used, &err) : 0.0; } longlong val_int() { diff --git a/sql/procedure.h b/sql/procedure.h index 5365b2e1102..abe50bdc0a0 100644 --- a/sql/procedure.h +++ b/sql/procedure.h @@ -59,7 +59,11 @@ public: void set(double nr) { value=nr; } void set(longlong nr) { value=(double) nr; } void set(const char *str,uint length,CHARSET_INFO *cs) - { int err; value=my_strntod(cs,(char*) str,length,(char**)0,&err); } + { + int err; + char *end_not_used; + value= my_strntod(cs, (char*) str, length, &end_not_used, &err); + } double val() { return value; } longlong val_int() { return (longlong) value; } String *val_str(String *s) { s->set(value,decimals,default_charset()); return s; } @@ -99,9 +103,10 @@ public: double val() { int err; - CHARSET_INFO *cs=str_value.charset(); + CHARSET_INFO *cs= str_value.charset(); + char *end_not_used; return my_strntod(cs, (char*) str_value.ptr(), str_value.length(), - (char**) 0, &err); + &end_not_used, &err); } longlong val_int() { diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 1a09b16a264..c2a6aa4e17f 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -773,31 +773,10 @@ double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), char *str, uint length, char **end, int *err) { - char end_char; - double result; - - errno= 0; /* Safety */ - - /* - The following define is to avoid warnings from valgrind as str[length] - may not be defined (which is not fatal in real life) - */ - -#ifdef HAVE_purify if (length == INT_MAX32) -#else - if (length == INT_MAX32 || str[length] == 0) -#endif - result= my_strtod(str, end); - else - { - end_char= str[length]; - str[length]= 0; - result= my_strtod(str, end); - str[length]= end_char; /* Restore end char */ - } - *err= errno; - return result; + length= 65535; /* Should be big enough */ + *end= str + length; + return my_strtod(str, end, err); } diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index e92704b83d7..9c67d1b7846 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -946,13 +946,10 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), break; /* Can't be part of double */ *b++= (char) wc; } - *b= 0; - errno= 0; - res=my_strtod(buf, endptr); - *err= errno; - if (endptr) - *endptr=(char*) (*endptr-buf+nptr); + *endptr= b; + res= my_strtod(buf, endptr, err); + *endptr= nptr + (uint) (*endptr- buf); return res; } diff --git a/strings/strtod.c b/strings/strtod.c index bc8105b8040..61f2c107abe 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -2,7 +2,7 @@ An alternative implementation of "strtod()" that is both simplier, and thread-safe. - From mit-threads as bundled with MySQL 3.23 + Original code from mit-threads as bundled with MySQL 3.23 SQL:2003 specifies a number as @@ -29,6 +29,8 @@ #include "my_base.h" /* Includes errno.h */ #include "m_ctype.h" +#define MAX_DBL_EXP 308 +#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; @@ -37,89 +39,157 @@ static double scaler1[] = { }; -double my_strtod(const char *str, char **end) +/* + Convert string to double (string doesn't have to be null terminated) + + SYNOPSIS + my_strtod() + str String to convert + end_ptr Pointer to pointer that points to end of string + Will be updated to point to end of double. + error Will contain error number in case of error (else 0) + + RETURN + value of str as double +*/ + +double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; - int negative, ndigits; - const char *old_str; + uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; + int exp= 0, digits_after_dec_point= 0; + const char *old_str, *end= *end_ptr, *start_of_number; + char next_char; my_bool overflow=0; + *error= 0; + if (str >= end) + goto done; + while (my_isspace(&my_charset_latin1, *str)) - str++; + { + if (++str == end) + goto done; + } + start_of_number= str; if ((negative= (*str == '-')) || *str=='+') - str++; + { + if (++str == end) + goto done; /* Could be changed to error */ + } + + /* Skip pre-zero for easier calculation of overflows */ + while (*str == '0') + { + if (++str == end) + goto done; + start_of_number= 0; /* Found digit */ + } old_str= str; - while (my_isdigit (&my_charset_latin1, *str)) + while ((next_char= *str) >= '0' && next_char <= '9') { - result= result*10.0 + (*str - '0'); - str++; + result= result*10.0 + (next_char - '0'); + if (++str == end) + { + next_char= 0; /* Found end of string */ + break; + } + start_of_number= 0; /* Found digit */ } - ndigits= str-old_str; + ndigits= (uint) (str-old_str); - if (*str == '.') + if (next_char == '.' && str < end-1) { - double p10=10; - str++; - old_str= str; - while (my_isdigit (&my_charset_latin1, *str)) + /* + Continue to add numbers after decimal point to the result, as if there + was no decimal point. We will later (in the exponent handling) shift + the number down with the required number of fractions. We do it this + way to be able to get maximum precision for numbers like 123.45E+02, + which are normal for some ODBC applications. + */ + old_str= ++str; + while (my_isdigit(&my_charset_latin1, (next_char= *str))) { - result+= (*str++ - '0')/p10; - p10*=10; + result= result*10.0 + (next_char - '0'); + digits_after_dec_point++; + if (++str == end) + { + next_char= 0; + break; + } } - ndigits+= str-old_str; - if (!ndigits) str--; + /* If we found just '+.' or '.' then point at first character */ + if (!(dec_digits= (uint) (str-old_str)) && start_of_number) + str= start_of_number; /* Point at '+' or '.' */ } - if (ndigits && (*str=='e' || *str=='E')) + if ((next_char == 'e' || next_char == 'E') && + dec_digits + ndigits != 0 && str < end-1) { - int exp= 0; - int neg= 0; const char *old_str= str++; - if ((neg= (*str == '-')) || *str == '+') + if ((neg_exp= (*str == '-')) || *str == '+') str++; - if (!my_isdigit (&my_charset_latin1, *str)) + if (str == end || !my_isdigit(&my_charset_latin1, *str)) str= old_str; else { - double scaler= 1.0; - while (my_isdigit (&my_charset_latin1, *str)) + do { - if (exp < 9999) /* protection against exp overflow */ - exp= exp*10 + *str - '0'; + if (exp < 9999) /* prot. against exp overfl. */ + exp= exp*10 + (*str - '0'); str++; - } - if (exp >= 1000) + } while (str < end && my_isdigit(&my_charset_latin1, *str)); + } + } + if ((exp= (neg_exp ? exp + digits_after_dec_point : + exp - digits_after_dec_point))) + { + double scaler; + if (exp < 0) + { + exp= -exp; + neg_exp= 1; /* neg_exp was 0 before */ + } + if (exp + ndigits >= MAX_DBL_EXP + 1 && result) + { + /* + This is not 100 % as we actually will give an owerflow for + 17E307 but not for 1.7E308 but lets cut some corners to make life + simpler + */ + if (exp + ndigits > MAX_DBL_EXP + 1 || + result >= MAX_RESULT_FOR_MAX_EXP) { - if (neg) - result= 0.0; - else + if (neg_exp) + result= 0.0; + else overflow= 1; goto done; } - while (exp >= 100) - { - scaler*= 1.0e100; - exp-= 100; - } - scaler*= scaler10[exp/10]*scaler1[exp%10]; - if (neg) - result/= scaler; - else - result*= scaler; } + scaler= 1.0; + while (exp >= 100) + { + scaler*= 1.0e100; + exp-= 100; + } + scaler*= scaler10[exp/10]*scaler1[exp%10]; + if (neg_exp) + result/= scaler; + else + result*= scaler; } done: - if (end) - *end = (char *)str; + *end_ptr= (char*) str; /* end of number */ if (overflow || isinf(result)) { result= DBL_MAX; - errno= EOVERFLOW; + *error= EOVERFLOW; } return negative ? -result : result; @@ -127,6 +197,7 @@ done: double my_atof(const char *nptr) { - return (my_strtod(nptr, 0)); + int error; + const char *end= nptr+65535; /* Should be enough */ + return (my_strtod(nptr, (char**) &end, &error)); } - |