diff options
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | include/m_string.h | 6 | ||||
-rw-r--r-- | include/my_global.h | 14 | ||||
-rw-r--r-- | libmysql/Makefile.shared | 2 | ||||
-rw-r--r-- | sql/gstream.cc | 2 | ||||
-rw-r--r-- | sql/init.cc | 3 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 2 | ||||
-rw-r--r-- | sql/item_sum.h | 4 | ||||
-rw-r--r-- | sql/sql_analyse.cc | 2 | ||||
-rw-r--r-- | strings/Makefile.am | 6 | ||||
-rw-r--r-- | strings/atof.c | 207 | ||||
-rw-r--r-- | strings/ctype-simple.c | 6 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 6 | ||||
-rw-r--r-- | strings/strtod.c | 140 |
15 files changed, 166 insertions, 238 deletions
diff --git a/configure.in b/configure.in index e607f87747b..3eb1befb29e 100644 --- a/configure.in +++ b/configure.in @@ -1825,7 +1825,7 @@ AC_CHECK_FUNCS(alarm bmove \ strtol strtoul strtoll strtoull snprintf tempnam thr_setconcurrency \ gethostbyaddr_r gethostbyname_r getpwnam \ bfill bzero bcmp strstr strpbrk strerror \ - tell atod memcpy memmove \ + tell isinf memcpy memmove \ setupterm strcasecmp sighold vidattr lrand48 localtime_r gmtime_r \ sigset sigthreadmask pthread_sigmask pthread_setprio pthread_setprio_np \ pthread_setschedparam pthread_attr_setprio pthread_attr_setschedparam \ diff --git a/include/m_string.h b/include/m_string.h index d72342fb3c1..ac2aae37704 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -201,7 +201,7 @@ extern int strcmp(const char *, const char *); extern size_t strlen(const char *); #endif #endif -#ifndef HAVE_STRNLEN +#ifndef HAVE_STRNLEN extern uint strnlen(const char *s, uint n); #endif @@ -215,7 +215,9 @@ extern char *strstr(const char *, const char *); #endif extern int is_prefix(const char *, const char *); -/* Conversion rutins */ +/* Conversion routines */ +double my_strtod(const char *str, char **end); +double my_atof(const char *nptr); #ifdef USE_MY_ITOA extern char *my_itoa(int val,char *dst,int radix); diff --git a/include/my_global.h b/include/my_global.h index c9660d4d649..41e3636116a 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -522,7 +522,7 @@ typedef SOCKET_SIZE_TYPE size_socket; #define FN_EXTCHAR '.' #define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */ #define FN_CURLIB '.' /* ./ is used as abbrev for current dir */ -#define FN_PARENTDIR ".." /* Parentdirectory; Must be a string */ +#define FN_PARENTDIR ".." /* Parent directory; Must be a string */ #define FN_DEVCHAR ':' #ifndef FN_LIBCHAR @@ -581,14 +581,6 @@ typedef SOCKET_SIZE_TYPE size_socket; /* Some defines of functions for portability */ -#ifndef HAVE_ATOD -#define atod atof -#endif -#ifdef USE_MY_ATOF -#define atof my_atof -extern void init_my_atof(void); -extern double my_atof(const char*); -#endif #undef remove /* Crashes MySQL on SCO 5.0.0 */ #ifndef __WIN__ #ifdef OS2 @@ -677,6 +669,10 @@ extern double my_atof(const char*); #define FLT_MAX ((float)3.40282346638528860e+38) #endif +#ifndef HAVE_ISINF +#define isinf(X) 0 +#endif + /* Max size that must be added to a so that we know Size to make adressable obj. diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 1cffae4dc56..678abc91859 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -32,7 +32,7 @@ target_sources = libmysql.c password.c manager.c \ get_password.c errmsg.c mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \ - strmake.lo strend.lo \ + strmake.lo strend.lo strtod.lo \ strnlen.lo strfill.lo is_prefix.lo \ int2str.lo str2int.lo strinstr.lo strcont.lo \ strcend.lo bcmp.lo ctype-latin1.lo \ diff --git a/sql/gstream.cc b/sql/gstream.cc index a97ed9cae03..17b85af22bd 100644 --- a/sql/gstream.cc +++ b/sql/gstream.cc @@ -101,7 +101,7 @@ int GTextReadStream::get_next_number(double *d) char *endptr; - *d = strtod(cur, &endptr); + *d = my_strtod(cur, &endptr); if (endptr) { diff --git a/sql/init.cc b/sql/init.cc index 033dfd72843..084db57f8aa 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -34,9 +34,6 @@ void unireg_init(ulong options) current_pid=(ulong) getpid(); /* Save for later ref */ init_time(); /* Init time-functions (read zone) */ -#ifdef USE_MY_ATOF - init_my_atof(); /* use our atof */ -#endif #ifndef EMBEDDED_LIBRARY my_abort_hook=unireg_abort; /* Abort with close of databases */ #endif diff --git a/sql/item.h b/sql/item.h index 7b5c506079d..6487c8d8391 100644 --- a/sql/item.h +++ b/sql/item.h @@ -441,7 +441,7 @@ class Item_real :public Item public: const double value; // Item_real() :value(0) {} - Item_real(const char *str_arg,uint length) :value(atof(str_arg)) + Item_real(const char *str_arg,uint length) :value(my_atof(str_arg)) { name=(char*) str_arg; decimals=(uint8) nr_of_decimals(str_arg); diff --git a/sql/item_func.cc b/sql/item_func.cc index f90fcd5149e..42f0e64c71b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2255,7 +2255,7 @@ double user_var_entry::val(my_bool *null_value) case INT_RESULT: return (double) *(longlong*) value; case STRING_RESULT: - return atof(value); // This is null terminated + return my_atof(value); // This is null terminated case ROW_RESULT: DBUG_ASSERT(1); // Impossible break; diff --git a/sql/item_sum.h b/sql/item_sum.h index dc84e4d4ab7..1435128af33 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -735,7 +735,7 @@ class Item_func_group_concat : public Item_sum enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} const char *func_name() const { return "group_concat"; } - enum Type type() const { return SUM_FUNC_ITEM; } + enum Type type() const { return SUM_FUNC_ITEM; } virtual Item_result result_type () const { return STRING_RESULT; } void clear(); bool add(); @@ -747,7 +747,7 @@ class Item_func_group_concat : public Item_sum double val() { String *res; res=val_str(&str_value); - return res ? atof(res->c_ptr()) : 0.0; + return res ? my_atof(res->c_ptr()) : 0.0; } longlong val_int() { diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 9e73e06d9c6..3c9563165fe 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -225,7 +225,7 @@ bool test_if_number(NUM_INFO *info, const char *str, uint str_len) info->decimals++; if (str == end) { - info->dval = atod(begin); + info->dval = my_atof(begin); return 1; } } diff --git a/strings/Makefile.am b/strings/Makefile.am index 61219c8abb9..89f32ac6b40 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -22,19 +22,19 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s -CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c +CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c else #no assembler ASRCS = # These file MUST all be on the same line!! Otherwise automake # generats a very broken makefile -CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c +CSRCS = strxmov.c bmove_upp.c strappend.c strcont.c strend.c strfill.c strcend.c is_prefix.c strstr.c strinstr.c strmake.c strnmov.c strmov.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c my_strtoll10.c endif endif diff --git a/strings/atof.c b/strings/atof.c deleted file mode 100644 index 0e0aa598718..00000000000 --- a/strings/atof.c +++ /dev/null @@ -1,207 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - A quicker atof. About 2-10 times faster than standard atof on sparc. - This don't handle iee-options (NaN...) and the presission :s is a little - less for some high exponential numbers (+-1 at 14th place). - Returns 0.0 if overflow or wrong number. - Must be inited with init_my_atof to handle possibly overflows. -*/ - -#include <my_global.h> -#ifdef USE_MY_ATOF /* Skipp if we don't want it */ -#include <m_ctype.h> -#include <floatingpoint.h> -#include <signal.h> - -/* Read a double. If float is wrong return 0. - float ::= [space]* [sign] {digit}+ decimal-point {digit}+ [exponent] | - [sign] {digit}+ [decimal-point {digit}*] exponent | - [sign] {digit}+ decimal-point [{digit}*] exponent | - [sign] decimal-point {digit}* exponent | - exponent :: = exponent-marker [sign] {digit}+ - exponent-marker ::= E e - */ - - -#define is_exponent_marker(ch) (ch == 'E' || ch == 'e') - -static void my_atof_overflow _A((int sig,int code, struct sigcontext *scp, - char *addr)); -static int parse_sign _A((char **str)); -static void parse_float_number_part _A((char **str,double *number, int *length)); -static void parse_decimal_number_part _A((char **str,double *number)); -static int parse_int_number_part _A((char **str,uint *number)); - -static int volatile overflow,in_my_atof; -static sigfpe_handler_type old_overflow_handler; - -void init_my_atof() -{ - old_overflow_handler = (sigfpe_handler_type) - ieee_handler("get", "overflow", old_overflow_handler); - VOID(ieee_handler("set", "overflow", my_atof_overflow)); - return; -} - -static void my_atof_overflow(sig, code, scp, addr) -int sig; -int code; -struct sigcontext *scp; -char *addr; -{ - if (!in_my_atof) - old_overflow_handler(sig,code,scp,addr); - else - overflow=1; - return; -} - -double my_atof(src) -const char *src; -{ - int sign, exp_sign; /* is number negative (+1) or positive (-1) */ - int length_before_point; - double after_point; /* Number after decimal point and before exp */ - uint exponent; /* Exponent value */ - double exp_log,exp_val; - char *tmp_src; - double result_number; - - tmp_src = (char*) src; - while (isspace(tmp_src[0])) - tmp_src++; /* Skipp pre-space */ - sign = parse_sign(&tmp_src); - overflow=0; - in_my_atof=1; - parse_float_number_part(&tmp_src, &result_number, &length_before_point); - if (*tmp_src == '.') - { - tmp_src++; - parse_decimal_number_part(&tmp_src, &after_point); - result_number += after_point; - } - else if (length_before_point == 0) - { - in_my_atof=0; - return 0.0; - } - if (is_exponent_marker(*tmp_src)) - { - tmp_src++; - exp_sign = parse_sign(&tmp_src); - overflow|=parse_int_number_part(&tmp_src, &exponent); - - exp_log=10.0; exp_val=1.0; - for (;;) - { - if (exponent & 1) - { - exp_val*= exp_log; - exponent--; - } - if (!exponent) - break; - exp_log*=exp_log; - exponent>>=1; - } - if (exp_sign < 0) - result_number*=exp_val; - else - result_number/=exp_val; - } - if (sign > 0) - result_number= -result_number; - - in_my_atof=0; - if (overflow) - return 0.0; - return result_number; -} - - -static int parse_sign(str) -char **str; -{ - if (**str == '-') - { - (*str)++; - return 1; - } - if (**str == '+') - (*str)++; - return -1; -} - - /* Get number with may be separated with ',' */ - -static void parse_float_number_part(str, number, length) -char **str; -double *number; -int *length; -{ - *number = 0; - *length = 0; - - for (;;) - { - while (isdigit(**str)) - { - (*length)++; - *number = (*number * 10) + (**str - '0'); - (*str)++; - } - if (**str != ',') - return; /* Skipp possibly ',' */ - (*str)++; - } -} - -static void parse_decimal_number_part(str, number) -char **str; -double *number; -{ - double exp_log; - - *number = 0; - exp_log=1/10.0; - while (isdigit(**str)) - { - *number+= (**str - '0')*exp_log; - exp_log/=10; - (*str)++; - } -} - - /* Parses int suitably for exponent */ - -static int parse_int_number_part(str, number) -char **str; -uint *number; -{ - *number = 0; - while (isdigit(**str)) - { - if (*number >= ((uint) ~0)/10) - return 1; /* Don't overflow */ - *number = (*number * 10) + **str - '0'; - (*str)++; - } - return 0; -} - -#endif diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 6f77d6f3e16..c55d12fcd3c 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -684,7 +684,7 @@ noconv: double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), - char *str, uint length, + char *str, uint length, char **end, int *err) { char end_char; @@ -702,12 +702,12 @@ double my_strntod_8bit(CHARSET_INFO *cs __attribute__((unused)), #else if (length == INT_MAX32 || str[length] == 0) #endif - result= strtod(str, end); + result= my_strtod(str, end); else { end_char= str[length]; str[length]= 0; - result= strtod(str, end); + result= my_strtod(str, end); str[length]= end_char; /* Restore end char */ } *err= errno; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index a7a59fc50f7..94f0a1bb2a2 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -856,7 +856,7 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), if (length >= sizeof(buf)) length= sizeof(buf)-1; end= s+length; - + while ((cnv=cs->cset->mb_wc(cs,&wc,s,end)) > 0) { s+=cnv; @@ -865,9 +865,9 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), *b++= (char) wc; } *b= 0; - + errno= 0; - res=strtod(buf, endptr); + res=my_strtod(buf, endptr); *err= errno; if (endptr) *endptr=(char*) (*endptr-buf+nptr); diff --git a/strings/strtod.c b/strings/strtod.c new file mode 100644 index 00000000000..ea6acbac6c4 --- /dev/null +++ b/strings/strtod.c @@ -0,0 +1,140 @@ +/* + An alternative implementation of "strtod()" that is both + simplier, and thread-safe. + + From mit-threads as bundled with MySQL 3.22 + + SQL:2003 specifies a number as + +<signed numeric literal> ::= [ <sign> ] <unsigned numeric literal> + +<unsigned numeric literal> ::= + <exact numeric literal> + | <approximate numeric literal> + +<exact numeric literal> ::= + <unsigned integer> [ <period> [ <unsigned integer> ] ] + | <period> <unsigned integer> + +<approximate numeric literal> ::= <mantissa> E <exponent> + +<mantissa> ::= <exact numeric literal> + +<exponent> ::= <signed integer> + + So do we. + + */ + +#include "my_base.h" +#include "m_ctype.h" + +static double scaler10[] = { + 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 +}; +static double scaler1[] = { + 1.0, 10.0, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 +}; + +// let's use a static array for not to accumulate the error +static double pastpoint[] = { + 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, + 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19, + 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29, + 1e-30, 1e-31, 1e-32, 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 1e-39, + 1e-40, 1e-41, 1e-42, 1e-43, 1e-44, 1e-45, 1e-46, 1e-47, 1e-48, 1e-49, + 1e-50, 1e-51, 1e-52, 1e-53, 1e-54, 1e-55, 1e-56, 1e-57, 1e-58, 1e-59, +}; + +double my_strtod(const char *str, char **end) +{ + double result= 0.0; + int negative, ndigits; + const char *old_str; + + while (my_isspace(&my_charset_latin1, *str)) + str++; + + if ((negative= (*str == '-')) || *str=='+') + str++; + + old_str= str; + while (my_isdigit (&my_charset_latin1, *str)) + { + result= result*10.0 + (*str - '0'); + str++; + } + ndigits= str-old_str; + + if (*str == '.') + { + int n= 0; + str++; + old_str= str; + while (my_isdigit (&my_charset_latin1, *str)) + { + if (n < sizeof(pastpoint)/sizeof(pastpoint[0])) + { + result+= pastpoint[n] * (*str - '0'); + n++; + } + str++; + } + ndigits+= str-old_str; + if (!ndigits) str--; + } + if (ndigits && (*str=='e' || *str=='E')) + { + int exp= 0; + int neg= 0; + const char *old_str= str++; + + if ((neg= (*str == '-')) || *str == '+') + str++; + + if (!my_isdigit (&my_charset_latin1, *str)) + str= old_str; + else + { + double scaler= 1.0; + while (my_isdigit (&my_charset_latin1, *str)) + { + exp= exp*10 + *str - '0'; + str++; + } + if (exp >= 1000) + { + if (neg) + result= 0.0; + else + result= DBL_MAX; + goto done; + } + while (exp >= 100) + { + scaler*= 1.0e100; + exp-= 100; + } + scaler*= scaler10[exp/10]*scaler1[exp%10]; + if (neg) + result/= scaler; + else + result*= scaler; + } + } + +done: + if (end) + *end = (char *)str; + + if (isinf(result)) + result=DBL_MAX; + + return negative ? -result : result; +} + +double my_atof(const char *nptr) +{ + return (strtod(nptr, 0)); +} + |