diff --git a/Makefile b/Makefile index ce60f097..af6f85d6 100644 --- a/Makefile +++ b/Makefile @@ -231,8 +231,8 @@ bindistdir: $(BINDISTFILES) done all-recursive clean-recursive distclean-recursive bakclean-recursive \ -install-recursive uninstall-recursive install-lib-recursive \ -install-include-recursive install-man-recursive uninstall-lib-recursive \ +install-recursive uninstall-recursive \ +install-include-recursive install-man-recursive \ uninstall-include-recursive uninstall-man-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ echo $@ | grep -q install; \ @@ -249,6 +249,19 @@ uninstall-include-recursive uninstall-man-recursive: || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" +install-lib-recursive uninstall-lib-recursive: + echo $@ | grep -q install; \ + if test $$? = 0 -a "${CROSS}" = yes -a "$(DESTDIR)${prefix}" = "/usr"; then \ + echo "attempting to install on host; aborting" >&2; \ + exit 1; \ + fi; \ + list='$(LIBDIRS)'; \ + for subdir in $$list; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + $(MAKE) -C $$target $$subdir || exit 1; \ + done + install-headers-recursive: if test "${CROSS}" = yes -a "$(DESTDIR)${prefix}" = "/usr"; then \ echo "attempting to install on host; aborting" >&2; \ diff --git a/argp/Makefile b/argp/Makefile index 971b6f61..1ce7af36 100644 --- a/argp/Makefile +++ b/argp/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony # FIXME: stratcliff still missing because of missing mman.h. diff --git a/conf/Makefile b/conf/Makefile index 9eb0854e..f0708f73 100644 --- a/conf/Makefile +++ b/conf/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/crypt/Makefile b/crypt/Makefile index f89ac7af..00af4032 100644 --- a/crypt/Makefile +++ b/crypt/Makefile @@ -28,7 +28,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = cert md5_1 md5_2 ufc diff --git a/crypt/examples/Makefile b/crypt/examples/Makefile index ed021f31..3023ed5c 100644 --- a/crypt/examples/Makefile +++ b/crypt/examples/Makefile @@ -22,7 +22,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/dirent/Makefile b/dirent/Makefile index b93a15ef..f6b48cf3 100644 --- a/dirent/Makefile +++ b/dirent/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = list opendir seekdir diff --git a/gmp/Makefile b/gmp/Makefile index 1047a8d0..711eb0b8 100644 --- a/gmp/Makefile +++ b/gmp/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/include/Makefile b/include/Makefile index 2a064254..cf3a5bc1 100644 --- a/include/Makefile +++ b/include/Makefile @@ -28,7 +28,6 @@ all-here: features.h linker.h syscall-list.h include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules GENSYS = AWK=$(AWK) $(csrcdir)/gensys diff --git a/include/arpa/Makefile b/include/arpa/Makefile index ee2b830f..e659191e 100644 --- a/include/arpa/Makefile +++ b/include/arpa/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/bits/Makefile b/include/bits/Makefile index 758537e4..1035108d 100644 --- a/include/bits/Makefile +++ b/include/bits/Makefile @@ -27,7 +27,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/bits/types/Makefile b/include/bits/types/Makefile index 37332514..27e4c01a 100644 --- a/include/bits/types/Makefile +++ b/include/bits/types/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/mint/Makefile b/include/mint/Makefile index 5ff054a6..05a23aea 100644 --- a/include/mint/Makefile +++ b/include/mint/Makefile @@ -27,7 +27,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/mint/arch/Makefile b/include/mint/arch/Makefile index 084acda0..b4c5e8ca 100644 --- a/include/mint/arch/Makefile +++ b/include/mint/arch/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/net/Makefile b/include/net/Makefile index ea12bccc..bbe22b0c 100644 --- a/include/net/Makefile +++ b/include/net/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/netinet/Makefile b/include/netinet/Makefile index 264a565a..df5f390e 100644 --- a/include/netinet/Makefile +++ b/include/netinet/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/nfs/Makefile b/include/nfs/Makefile index 128d8194..24edb010 100644 --- a/include/nfs/Makefile +++ b/include/nfs/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/protocols/Makefile b/include/protocols/Makefile index ce70b7a1..6658231b 100644 --- a/include/protocols/Makefile +++ b/include/protocols/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/rpc/Makefile b/include/rpc/Makefile index a7fe7c37..1e029e98 100644 --- a/include/rpc/Makefile +++ b/include/rpc/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/rpcsvc/Makefile b/include/rpcsvc/Makefile index d7dd1fe6..ce9ca45f 100644 --- a/include/rpcsvc/Makefile +++ b/include/rpcsvc/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/include/sys/Makefile b/include/sys/Makefile index dac2bd36..06b7fca4 100644 --- a/include/sys/Makefile +++ b/include/sys/Makefile @@ -25,7 +25,6 @@ all-here: include $(top_srcdir)/phony -dont_install_libs = yes include $(top_srcdir)/rules includefiles = $(filter %.h, $(MISCFILES)) diff --git a/login/Makefile b/login/Makefile index 84399190..decaa07b 100644 --- a/login/Makefile +++ b/login/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = utmp diff --git a/mintlib/Makefile b/mintlib/Makefile index 1313a1a4..a8ce1a0a 100644 --- a/mintlib/Makefile +++ b/mintlib/Makefile @@ -24,7 +24,6 @@ default: all all-here: syscalls.h -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = assert assert-perr atexit ctype ctype1 dirent mallocbug seekdir \ diff --git a/misc/Makefile b/misc/Makefile index 6841549f..a1052c84 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = dirname efgcvt fdset tsearch diff --git a/multibyte/Makefile b/multibyte/Makefile index bb413e37..0cb86849 100644 --- a/multibyte/Makefile +++ b/multibyte/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony # FIXME: stratcliff still missing because of missing mman.h. diff --git a/posix/Makefile b/posix/Makefile index f86b84c8..01125ce3 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony # FIXME: The test runp fails with an illegal instruction. We omit diff --git a/pwdgrp/Makefile b/pwdgrp/Makefile index 2ce5917d..8099417f 100644 --- a/pwdgrp/Makefile +++ b/pwdgrp/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = grp diff --git a/rules b/rules index 842ba06c..ffe46ca6 100644 --- a/rules +++ b/rules @@ -26,11 +26,6 @@ install-recursive uninstall: uninstall-recursive uninstall-include uninstall-lib uninstall-man -ifdef dont_install_libs -install-lib: - -else - baselibs = $(basename $(LIBS)) install-lib: @@ -54,7 +49,6 @@ uninstall-lib: echo " rm -f $(DESTDIR)$(libdir)/$(instdir)/$$p"; \ rm -f $(DESTDIR)$(libdir)/$(instdir)/$$p; \ done -endif check: check-recursive @@ -83,8 +77,8 @@ distdir: $(DISTFILES) distdir-local distdir-local: all-recursive clean-recursive bakclean-recursive check-recursive \ -install-recursive uninstall-recursive install-lib-recursive \ -install-include-recursive install-man-recursive uninstall-lib-recursive \ +install-recursive uninstall-recursive \ +install-include-recursive install-man-recursive \ uninstall-include-recursive uninstall-man-recursive dist-recursive: @set fnord $(MAKEFLAGS); amf=$$2; \ list='$(SUBDIRS)'; for subdir in $$list; do \ @@ -93,4 +87,3 @@ uninstall-include-recursive uninstall-man-recursive dist-recursive: (cd $$subdir && $(MAKE) -r $$target) \ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ done && test -z "$$fail" - diff --git a/shadow/Makefile b/shadow/Makefile index 2610fe4e..369fe9d7 100644 --- a/shadow/Makefile +++ b/shadow/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony check: diff --git a/signal/Makefile b/signal/Makefile index f02f0f5e..0088690c 100644 --- a/signal/Makefile +++ b/signal/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = signal sigset diff --git a/socket/Makefile b/socket/Makefile index 1101ebca..a8e186ac 100644 --- a/socket/Makefile +++ b/socket/Makefile @@ -33,7 +33,6 @@ include $(top_srcdir)/checkrules check-local: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/startup/Makefile b/startup/Makefile index b5bf0018..34342215 100644 --- a/startup/Makefile +++ b/startup/Makefile @@ -15,8 +15,6 @@ subdir = startup default: all -dont_install_libs = yes - include $(top_srcdir)/configvars include $(top_srcdir)/bindist diff --git a/stdiio/Makefile b/stdiio/Makefile index fc060def..5ecd4134 100644 --- a/stdiio/Makefile +++ b/stdiio/Makefile @@ -33,7 +33,6 @@ include $(top_srcdir)/checkrules all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/stdio/Makefile b/stdio/Makefile index 35b30447..db2c43cc 100644 --- a/stdio/Makefile +++ b/stdio/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 \ diff --git a/stdlib/Makefile b/stdlib/Makefile index 7f0b0503..4e73520c 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony # NOTE: The test "cc" should come first! diff --git a/stdlib/strtod.c b/stdlib/strtod.c index 3f7aa8ad..788bf32d 100644 --- a/stdlib/strtod.c +++ b/stdlib/strtod.c @@ -1,80 +1,48 @@ -/* Read decimal floating point numbers. - This file is part of the GNU C Library. - Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. - Contributed by Ulrich Drepper , 1995. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; if not, see - . */ - -/* Modified for MiNTLib by Guido Flohr . */ +/* + * strtod.c -- + * + * Source code for the "strtod" library procedure. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * RCS: @(#) $Id$ + * + * Originally Taken from http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8/missing/strtod.c + */ + +/* Modified for MiNTLib by Thorsten Otto. */ /* Configuration part. These macros are defined by `strtold.c', `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the `long double' and `float' versions of the reader. */ -#ifndef FLOAT -# define FLOAT double -# define FLT DBL -# ifdef USE_WIDE_CHAR -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define STRTOF __wcstod_l -# else -# define STRTOF wcstod -# endif -# else -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define STRTOF __strtod_l -# else -# define STRTOF strtod -# endif -# endif -# define MPN2FLOAT __mpn_construct_double -# define FLOAT_HUGE_VAL __builtin_inf() -# define FLOAT_NAN_VAL __builtin_nan("") -# define SET_MANTISSA(flt, mant) \ - do { union ieee754_double u; \ - u.d = (flt); \ - if ((mant & 0xfffffffffffffULL) == 0) \ - mant = 0x8000000000000ULL; \ - u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ - u.ieee.mantissa1 = (mant) & 0xffffffff; \ - (flt) = u.d; \ - } while (0) +#ifndef FLOAT_TYPE +#define FLOAT_TYPE 1 #endif /* End of configuration part. */ - + +#include #include #include #include #include -#ifndef __MINT__ -# include "../locale/localeinfo.h" -#endif -#include "math_private.h" -#include -#include - -/* The gmp headers need some configuration frobs. */ -#define HAVE_ALLOCA 1 +#include -#include -#include -#include -#include -#include "fpioconst.h" - -#define NDEBUG 1 -#include +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif /* We use this code also for the extended locale handling where the @@ -82,1378 +50,431 @@ used. To access the values we have to redefine the _NL_CURRENT macro. */ #ifdef USE_IN_EXTENDED_LOCALE_MODEL -# undef _NL_CURRENT -# define _NL_CURRENT(category, item) \ +#undef _NL_CURRENT +#define _NL_CURRENT(category, item) \ (current->values[_NL_ITEM_INDEX (item)].string) -# define LOCALE_PARAM_DECL , __locale_t loc -# define LOCALE_PARAM , loc +#define LOCALE_PARAM_DECL , __locale_t loc +#define LOCALE_PARAM , loc #else -# define LOCALE_PARAM_DECL -# define LOCALE_PARAM +#define LOCALE_PARAM_DECL +#define LOCALE_PARAM #endif #ifndef __MINT__ -# if defined _LIBC || defined HAVE_WCHAR_H -# include -# endif +#if defined _LIBC || defined HAVE_WCHAR_H +#include +#endif #else -# define __strtoull_internal(s, p, b, f) strtoull (s, p, b) -# define __strncasecmp strncasecmp -# define wchar_t char +#define __strtoull_internal(s, p, b, f) strtoull (s, p, b) +#define __strncasecmp strncasecmp #endif #ifdef USE_WIDE_CHAR -# include -# define STRING_TYPE wchar_t -# define CHAR_TYPE wint_t -/* We should get wint_t from , but not all GCC versions define it - there. So define it ourselves if it remains undefined. */ -#ifndef _WINT_T - typedef unsigned int wint_t; +#include +#define STRING_TYPE wchar_t +#define CHAR_TYPE wchar_t +#define L_(Ch) L##Ch +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +#define ISSPACE(Ch) __iswspace_l ((Ch), loc) +#define ISDIGIT(Ch) __iswdigit_l ((Ch), loc) +#define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc) +#define TOLOWER(Ch) __towlower_l ((Ch), loc) +#define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc) +#define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) +#else +#define ISSPACE(Ch) iswspace (Ch) +#define ISDIGIT(Ch) iswdigit (Ch) +#define ISXDIGIT(Ch) iswxdigit (Ch) +#define TOLOWER(Ch) towlower (Ch) +#define STRNCASECMP(S1, S2, N) __wcsncasecmp ((S1), (S2), (N)) +#define STRTOULL(S, E, B) __wcstoull_internal ((S), (E), (B), 0) #endif -# define L_(Ch) L##Ch -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __iswspace_l ((Ch), loc) -# define ISDIGIT(Ch) __iswdigit_l ((Ch), loc) -# define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc) -# define TOLOWER(Ch) __towlower_l ((Ch), loc) -# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc) -# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) -# else -# define ISSPACE(Ch) iswspace (Ch) -# define ISDIGIT(Ch) iswdigit (Ch) -# define ISXDIGIT(Ch) iswxdigit (Ch) -# define TOLOWER(Ch) towlower (Ch) -# define STRNCASECMP(S1, S2, N) __wcsncasecmp ((S1), (S2), (N)) -# define STRTOULL(S, E, B) __wcstoull_internal ((S), (E), (B), 0) -# endif #else -# define STRING_TYPE char -# define CHAR_TYPE char -# define L_(Ch) Ch -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __isspace_l ((Ch), loc) -# define ISDIGIT(Ch) __isdigit_l ((Ch), loc) -# define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc) -# define TOLOWER(Ch) __tolower_l ((Ch), loc) -# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc) -# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) -# else -# define ISSPACE(Ch) isspace (Ch) -# define ISDIGIT(Ch) isdigit (Ch) -# define ISXDIGIT(Ch) isxdigit (Ch) -# define TOLOWER(Ch) tolower (Ch) -# define STRNCASECMP(S1, S2, N) __strncasecmp ((S1), (S2), (N)) -# define STRTOULL(S, E, B) __strtoull_internal ((S), (E), 0, (B)) -# endif +#define STRING_TYPE char +#define CHAR_TYPE unsigned char +#define L_(Ch) Ch +#ifdef USE_IN_EXTENDED_LOCALE_MODEL +#define ISSPACE(Ch) __isspace_l ((Ch), loc) +#define ISDIGIT(Ch) __isdigit_l ((Ch), loc) +#define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc) +#define TOLOWER(Ch) __tolower_l ((Ch), loc) +#define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc) +#define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) +#else +#define ISSPACE(Ch) ((Ch) == '\n' || (Ch) == '\r' || (Ch) == '\v' || (Ch) == '\f' || (Ch) == ' ') +#define ISDIGIT(Ch) ((Ch) >= '0' && (Ch) <= '9') +#define ISXDIGIT(Ch) isxdigit (Ch) +#define TOLOWER(Ch) tolower (Ch) +#define STRNCASECMP(S1, S2, N) __strncasecmp ((S1), (S2), (N)) +#define STRTOULL(S, E, B) __strtoull_internal ((S), (E), 0, (B)) +#endif #endif /* Constants we need from float.h; select the set for the FLOAT precision. */ -#define MANT_DIG PASTE(FLT,_MANT_DIG) -#define DIG PASTE(FLT,_DIG) -#define MAX_EXP PASTE(FLT,_MAX_EXP) -#define MIN_EXP PASTE(FLT,_MIN_EXP) -#define MAX_10_EXP PASTE(FLT,_MAX_10_EXP) -#define MIN_10_EXP PASTE(FLT,_MIN_10_EXP) +#if FLOAT_TYPE == 0 +/* Convert a multi-precision integer of the needed number of bits (24 for + float) and an integral power of two to a `float' in IEEE754 single- + precision format. */ + +# define FLOAT float + +# define FC(x) x ## F +# define MANT_DIG __FLT_MANT_DIG__ +# define DIG __FLT_DIG__ +# define MAX_EXP __FLT_MAX_EXP__ +# define MIN_EXP __FLT_MIN_EXP__ +# define MAX_10_EXP __FLT_MAX_10_EXP__ +# define MIN_10_EXP __FLT_MIN_10_EXP__ +# define FLOAT_HUGE_VAL __builtin_inff() +# define FLOAT_NAN_VAL __builtin_nanf("") +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtof_l +# else +# define STRTOF strtof +# endif +# define SET_NAN_MANTISSA(flt, mant) \ + do { union ieee754_float u; \ + u.f = (flt); \ + if ((mant & 0x7fffff) == 0) \ + mant = 0x400000; \ + u.ieee.mantissa = (mant) & 0x7fffff; \ + (flt) = u.f; \ + } while (0) +#elif FLOAT_TYPE == 1 || __DBL_MANT_DIG__ == __LDBL_MANT_DIG__ -/* Extra macros required to get FLT expanded before the pasting. */ -#define PASTE(a,b) PASTE1(a,b) -#define PASTE1(a,b) a##b +# define FLOAT double -/* Function to construct a floating point number from an MP integer - containing the fraction bits, a base 2 exponent, and a sign flag. */ -extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative); - -/* Definitions according to limb size used. */ -#if BITS_PER_MP_LIMB == 32 -# define MAX_DIG_PER_LIMB 9 -# define MAX_FAC_PER_LIMB 1000000000UL -#elif BITS_PER_MP_LIMB == 64 -# define MAX_DIG_PER_LIMB 19 -# define MAX_FAC_PER_LIMB 10000000000000000000UL +# define FC(x) x +# define MANT_DIG __DBL_MANT_DIG__ +# define DIG __DBL_DIG__ +# define MAX_EXP __DBL_MAX_EXP__ +# define MIN_EXP __DBL_MIN_EXP__ +# define MAX_10_EXP __DBL_MAX_10_EXP__ +# define MIN_10_EXP __DBL_MIN_10_EXP__ +# define FLOAT_HUGE_VAL __builtin_inf() +# define FLOAT_NAN_VAL __builtin_nan("") +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtod_l +# else +# define STRTOF strtod +# endif +#define SET_NAN_MANTISSA(flt, mant) \ + do { union ieee754_double u; \ + u.d = (flt); \ + if ((mant & 0xfffffffffffffULL) == 0) \ + mant = 0x8000000000000ULL; \ + u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ + u.ieee.mantissa1 = (mant) & 0xffffffff; \ + (flt) = u.d; \ + } while (0) +#elif FLOAT_TYPE == 2 + +# define FLOAT long double + +# define FC(x) x ## L +# define MANT_DIG __LDBL_MANT_DIG__ +# define DIG __LDBL_DIG__ +# define MAX_EXP __LDBL_MAX_EXP__ +# define MIN_EXP __LDBL_MIN_EXP__ +# define MAX_10_EXP __LDBL_MAX_10_EXP__ +# define MIN_10_EXP __LDBL_MIN_10_EXP__ +# define FLOAT_HUGE_VAL __builtin_infl() +# define FLOAT_NAN_VAL __builtin_nanl("") +# ifdef USE_IN_EXTENDED_LOCALE_MODEL +# define STRTOF __strtold_l +# else +# define STRTOF strtold +# endif +# define SET_NAN_MANTISSA(flt, mant) \ + do { union ieee854_long_double u; \ + u.d = (flt); \ + if ((mant & 0x7fffffffffffffffULL) == 0) \ + mant = 0x4000000000000000ULL; \ + u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000; \ + u.ieee.mantissa1 = (mant) & 0xffffffff; \ + (flt) = u.d; \ + } while (0) #else -# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for" +# error "unsupported float" #endif - -/* Local data structure. */ -static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] = -{ 0, 10, 100, - 1000, 10000, 100000, - 1000000, 10000000, 100000000, - 1000000000 -#if BITS_PER_MP_LIMB > 32 - , 10000000000U, 100000000000U, - 1000000000000U, 10000000000000U, 100000000000000U, - 1000000000000000U, 10000000000000000U, 100000000000000000U, - 1000000000000000000U, 10000000000000000000U -#endif -#if BITS_PER_MP_LIMB > 64 - #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB -#endif -}; - -#ifndef howmany -#define howmany(x,y) (((x)+((y)-1))/(y)) -#endif -#define SWAP(x, y) ({ typeof(x) _tmp = x; x = y; y = _tmp; }) - -#ifndef __MSHORT__ -#define NDIG (MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG) -#define HEXNDIG ((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG) +#if MANT_DIG >= 31 +typedef unsigned long long mant_t; +#elif __INT_MAX__ >= 0x7fffffffL +typedef unsigned int mant_t; #else -#define NDIG \ -((long) ((long) MAX_10_EXP - (long) MIN_10_EXP + 2L * (long) MANT_DIG)) -#define HEXNDIG \ -((long) (((long) MAX_EXP - (long) MIN_EXP + 7L) / 8L * 2L * (long) MANT_DIG)) +typedef unsigned long mant_t; #endif -#define RETURN_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB) - -#define RETURN(val,end) \ - do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end); \ - return val; } while (0) -/* Maximum size necessary for mpn integers to hold floating point numbers. */ -#define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \ - + 2) -/* Declare an mpn integer variable that big. */ -#define MPN_VAR(name) mp_limb_t name[MPNSIZE]; mp_size_t name##size -/* Copy an mpn integer value. */ -#define MPN_ASSIGN(dst, src) \ - memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t)) -#ifdef __MINT__ -static __inline const STRING_TYPE* -correctly_grouped_prefix (const STRING_TYPE* begin, const STRING_TYPE* end, - wchar_t thousands, const char* grouping) -{ - if (grouping == NULL) - return end; - while (begin < end && *begin != thousands) - ++begin; - return begin; -} +static FLOAT const powersOf10[] = { /* Table giving binary powers of 10. Entry */ + FC(1.0e1), /* is 10^2^i. Used to convert decimal */ + FC(1.0e2), /* exponents into floating-point numbers. */ + FC(1.0e4), + FC(1.0e8), + FC(1.0e16), + FC(1.0e32), +#if MAX_10_EXP >= 64 + FC(1.0e64), + FC(1.0e128), + FC(1.0e256), #endif - -/* Return a floating point number of the needed type according to the given - multi-precision number after possible rounding. */ -static inline FLOAT -round_and_return (mp_limb_t *retval, int exponent, int negative, - mp_limb_t round_limb, mp_size_t round_bit, int more_bits) -{ - if (exponent < MIN_EXP - 1) - { - mp_size_t shift = MIN_EXP - 1 - exponent; - - if (shift > MANT_DIG) - { - __set_errno (EDOM); - return 0.0; - } - - more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0; - if (shift == MANT_DIG) - /* This is a special case to handle the very seldom case where - the mantissa will be empty after the shift. */ - { - int i; - - round_limb = retval[RETURN_LIMB_SIZE - 1]; - round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; - for (i = 0; i < RETURN_LIMB_SIZE; ++i) - more_bits |= retval[i] != 0; - MPN_ZERO (retval, RETURN_LIMB_SIZE); - } - else if (shift >= BITS_PER_MP_LIMB) - { - int i; - - round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB]; - round_bit = (shift - 1) % BITS_PER_MP_LIMB; - for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i) - more_bits |= retval[i] != 0; - more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) - != 0); - - (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB], - RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB), - shift % BITS_PER_MP_LIMB); - MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)], - shift / BITS_PER_MP_LIMB); - } - else if (shift > 0) - { - round_limb = retval[0]; - round_bit = shift - 1; - (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift); - } - /* This is a hook for the m68k long double format, where the - exponent bias is the same for normalized and denormalized - numbers. */ -#ifndef DENORM_EXP -# define DENORM_EXP (MIN_EXP - 2) +#if MAX_10_EXP >= 512 + FC(1.0e512), + FC(1.0e1024), + FC(1.0e2048), + FC(1.0e4096), #endif - exponent = DENORM_EXP; - } - - if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0 - && (more_bits || (retval[0] & 1) != 0 - || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0)) - { - mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1); - - if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) || - ((MANT_DIG % BITS_PER_MP_LIMB) != 0 && - (retval[RETURN_LIMB_SIZE - 1] - & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0)) - { - ++exponent; - (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1); - retval[RETURN_LIMB_SIZE - 1] - |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB); - } - else if (exponent == DENORM_EXP - && (retval[RETURN_LIMB_SIZE - 1] - & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) - != 0) - /* The number was denormalized but now normalized. */ - exponent = MIN_EXP - 1; - } - - if (exponent > MAX_EXP) - return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; - - return MPN2FLOAT (retval, exponent, negative); -} - - -/* Read a multi-precision integer starting at STR with exactly DIGCNT digits - into N. Return the size of the number limbs in NSIZE at the first - character od the string that is not part of the integer as the function - value. If the EXPONENT is small enough to be taken as an additional - factor for the resulting number (see code) multiply by it. */ -static inline const STRING_TYPE * -str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize, - int *exponent) -{ - /* Number of digits for actual limb. */ - int cnt = 0; - mp_limb_t low = 0; - mp_limb_t start; - - *nsize = 0; - assert (digcnt > 0); - do - { - if (cnt == MAX_DIG_PER_LIMB) - { - if (*nsize == 0) - { - n[0] = low; - *nsize = 1; - } - else - { - mp_limb_t cy; - cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB); - cy += __mpn_add_1 (n, n, *nsize, low); - if (cy != 0) - { - n[*nsize] = cy; - ++(*nsize); - } - } - cnt = 0; - low = 0; - } - - /* There might be thousands separators or radix characters in - the string. But these all can be ignored because we know the - format of the number is correct and we have an exact number - of characters to read. */ - while (*str < L_('0') || *str > L_('9')) - ++str; - low = low * 10 + *str++ - L_('0'); - ++cnt; - } - while (--digcnt > 0); - - if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB) - { - low *= _tens_in_limb[*exponent]; - start = _tens_in_limb[cnt + *exponent]; - *exponent = 0; - } - else - start = _tens_in_limb[cnt]; - - if (*nsize == 0) - { - n[0] = low; - *nsize = 1; - } - else - { - mp_limb_t cy; - cy = __mpn_mul_1 (n, n, *nsize, start); - cy += __mpn_add_1 (n, n, *nsize, low); - if (cy != 0) - n[(*nsize)++] = cy; - } - - return str; -} - - -/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits - with the COUNT most significant bits of LIMB. - - Tege doesn't like this function so I have to write it here myself. :) - --drepper */ -static inline void -__mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count, - mp_limb_t limb) -{ - if (count == BITS_PER_MP_LIMB) - { - /* Optimize the case of shifting by exactly a word: - just copy words, with no actual bit-shifting. */ - mp_size_t i; - for (i = size - 1; i > 0; --i) - ptr[i] = ptr[i - 1]; - ptr[0] = limb; - } - else - { - (void) __mpn_lshift (ptr, ptr, size, count); - ptr[0] |= limb >> (BITS_PER_MP_LIMB - count); - } -} - +}; #define INTERNAL(x) INTERNAL1(x) #define INTERNAL1(x) __##x##_internal -FLOAT -INTERNAL (STRTOF) (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group LOCALE_PARAM_DECL); - -#ifndef __MINT__ -/* This file defines a function to check for correct grouping. */ -# include "grouping.h" -#endif - - -/* Return a floating point number with the value of the given string NPTR. - Set *ENDPTR to the character after the last used one. If the number is - smaller than the smallest representable number, set `errno' to ERANGE and - return 0.0. If the number is too big to be represented, set `errno' to - ERANGE and return HUGE_VAL with the appropriate sign. */ -FLOAT -INTERNAL (STRTOF) (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group LOCALE_PARAM_DECL) +FLOAT INTERNAL (STRTOF) (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group LOCALE_PARAM_DECL); + +/* + *---------------------------------------------------------------------- + * + * strtod -- + * + * This procedure converts a floating-point number from an ASCII + * decimal representation to internal double-precision format. + * + * Results: + * The return value is the double-precision floating-point + * representation of the characters in string. If endPtr isn't + * NULL, then *endPtr is filled in with the address of the + * next character after the last one that was part of the + * floating-point number. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +/* A decimal ASCII floating-point number, + * optionally preceded by white space. + * Must have form "-I.FE-X", where I is the + * integer part of the mantissa, F is the + * fractional part of the mantissa, and X + * is the exponent. Either of the signs + * may be "+", "-", or omitted. Either I + * or F may be omitted, or both. The decimal + * point isn't necessary unless F is present. + * The "E" may actually be an "e". E and X + * may both be omitted (but not just one). + */ +FLOAT INTERNAL (STRTOF) (const STRING_TYPE *string, STRING_TYPE **endptr, int group LOCALE_PARAM_DECL) { - int negative; /* The sign of the number. */ - MPN_VAR (num); /* MP representation of the number. */ - int exponent; /* Exponent of the number. */ - - /* Numbers starting `0X' or `0x' have to be processed with base 16. */ -#ifndef __MSHORT__ - int base = 10; -#else - long int base = 10; -#endif - - /* When we have to compute fractional digits we form a fraction with a - second multi-precision number (and we sometimes need a second for - temporary results). */ - MPN_VAR (den); - - /* Representation for the return value. */ - mp_limb_t retval[RETURN_LIMB_SIZE]; - /* Number of bits currently in result value. */ - int bits; - - /* Running pointer after the last character processed in the string. */ - const STRING_TYPE *cp, *tp; - /* Start of significant part of the number. */ - const STRING_TYPE *startp, *start_of_digits; - /* Points at the character following the integer and fractional digits. */ - const STRING_TYPE *expp; - /* Total number of digit and number of digits in integer part. */ -#ifndef __MSHORT__ - int dig_no, int_no, lead_zero; -#else - long int dig_no, int_no, lead_zero; -#endif - /* Contains the last character read. */ - CHAR_TYPE c; - - /* The radix character of the current locale. */ - wchar_t decimal; - /* The thousands character of the current locale. */ - wchar_t thousands = L'\0'; - /* The numeric grouping specification of the current locale, - in the format described in . */ - const char *grouping; - -#ifdef USE_IN_EXTENDED_LOCALE_MODEL - struct locale_data *current = loc->__locales[LC_NUMERIC]; -#endif - -#ifndef __MINT__ - if (group) - { - grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); - if (*grouping <= 0 || *grouping == CHAR_MAX) - grouping = NULL; - else - { - /* Figure out the thousands separator character. */ - thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)); - if (thousands == WEOF) - thousands = L'\0'; - if (thousands == L'\0') - grouping = NULL; - } - } - else -#endif - grouping = NULL; - -#ifndef __MINT__ - /* Find the locale's decimal point character. */ - decimal = __btowc (*_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT)); - if (decimal == WEOF) -#endif - decimal = L'.'; - assert (decimal != L'\0'); - - /* Prepare number representation. */ - exponent = 0; - negative = 0; - bits = 0; - - /* Parse string to get maximal legal prefix. We need the number of - characters of the integer part, the fractional part and the exponent. */ - cp = nptr - 1; - /* Ignore leading white space. */ - do - c = *++cp; - while (ISSPACE (c)); - - /* Get sign of the result. */ - if (c == L_('-')) - { - negative = 1; - c = *++cp; - } - else if (c == L_('+')) - c = *++cp; - - /* Return 0.0 if no legal string is found. - No character is used even if a sign was found. */ - if ((c < L_('0') || c > L_('9')) - && ((wchar_t) c != decimal || cp[1] < L_('0') || cp[1] > L_('9'))) - { - int matched = 0; - /* Check for `INF' or `INFINITY'. */ - if (TOLOWER (c) == L_('i') - && ((STRNCASECMP (cp, L_("inf"), 3) == 0 && (matched = 3)) - || (STRNCASECMP (cp, L_("infinity"), 8) == 0 && (matched = 8)))) - { - /* Return +/- infinity. */ - if (endptr != NULL) - *endptr = (STRING_TYPE *) (cp + matched); - - return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; - } - - if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0) - { - /* Return NaN. */ - FLOAT retval = FLOAT_NAN_VAL; - - cp += 3; - - /* Match `(n-char-sequence-digit)'. */ - if (*cp == L_('(')) - { - const STRING_TYPE *startp = cp; - do - ++cp; - while ((*cp >= L_('0') && *cp <= L_('9')) - || (TOLOWER (*cp) >= L_('a') && TOLOWER (*cp) <= L_('z')) - || *cp == L_('_')); - - if (*cp != L_(')')) - /* The closing brace is missing. Only match the NAN - part. */ - cp = startp; - else - { - /* This is a system-dependent way to specify the - bitmask used for the NaN. We expect it to be - a number which is put in the mantissa of the - number. */ - STRING_TYPE *endp; - unsigned long long int mant; - - mant = STRTOULL (startp + 1, &endp, 0); - if (endp == cp) - SET_MANTISSA (retval, mant); - } - } - - if (endptr != NULL) - *endptr = (STRING_TYPE *) cp; - - return retval; - } - - /* It is really a text we do not recognize. */ - RETURN (0.0, nptr); - } - - /* First look whether we are faced with a hexadecimal number. */ - if (c == L_('0') && TOLOWER (cp[1]) == L_('x')) - { - /* Okay, it is a hexa-decimal number. Remember this and skip - the characters. BTW: hexadecimal numbers must not be - grouped. */ - base = 16; - cp += 2; - c = *cp; - grouping = NULL; - } - - /* Record the start of the digits, in case we will check their grouping. */ - start_of_digits = startp = cp; - - /* Ignore leading zeroes. This helps us to avoid useless computations. */ - while (c == L_('0') || (thousands != L'\0' && (wchar_t) c == thousands)) - c = *++cp; - - /* If no other digit but a '0' is found the result is 0.0. - Return current read pointer. */ - if ((c < L_('0') || c > L_('9')) && - (base == 16 && (c < TOLOWER (L_('a')) || c > TOLOWER (L_('f')))) && - (wchar_t) c != decimal && - (base == 16 && (cp == start_of_digits || TOLOWER (c) != L_('p'))) && - (base != 16 && TOLOWER (c) != L_('e'))) - { - tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); - /* If TP is at the start of the digits, there was no correctly - grouped prefix of the string; so no number found. */ - RETURN (0.0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp); - } - - /* Remember first significant digit and read following characters until the - decimal point, exponent character or any non-FP number character. */ - startp = cp; - dig_no = 0; - while (dig_no < (base == 16 ? HEXNDIG : NDIG) || - /* If parsing grouping info, keep going past useful digits - so we can check all the grouping separators. */ - grouping) - { - if ((c >= L_('0') && c <= L_('9')) - || (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f'))) - ++dig_no; - else if (thousands == L'\0' || (wchar_t) c != thousands) - /* Not a digit or separator: end of the integer part. */ - break; - c = *++cp; - } - - if (grouping && dig_no > 0) - { - /* Check the grouping of the digits. */ - tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping); - if (cp != tp) - { - /* Less than the entire string was correctly grouped. */ - - if (tp == start_of_digits) - /* No valid group of numbers at all: no valid number. */ - RETURN (0.0, nptr); - - if (tp < startp) - /* The number is validly grouped, but consists - only of zeroes. The whole value is zero. */ - RETURN (0.0, tp); - - /* Recompute DIG_NO so we won't read more digits than - are properly grouped. */ - cp = tp; - dig_no = 0; - for (tp = startp; tp < cp; ++tp) - if (*tp >= L_('0') && *tp <= L_('9')) - ++dig_no; - - int_no = dig_no; - lead_zero = 0; - - goto number_parsed; - } - } - - if (dig_no >= (base == 16 ? HEXNDIG : NDIG)) - /* Too many digits to be representable. Assigning this to EXPONENT - allows us to read the full number but return HUGE_VAL after parsing. */ - exponent = MAX_10_EXP; - - /* We have the number digits in the integer part. Whether these are all or - any is really a fractional digit will be decided later. */ - int_no = dig_no; - lead_zero = int_no == 0 ? -1 : 0; - - /* Read the fractional digits. A special case are the 'american style' - numbers like `16.' i.e. with decimal but without trailing digits. */ - if ((wchar_t) c == decimal) - { - c = *++cp; - while ((c >= L_('0') && c <= L_('9')) || - (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f'))) + int sign; + int expSign; + FLOAT fraction; + FLOAT dblExp; + const FLOAT *d; + const STRING_TYPE *p; + CHAR_TYPE c; + int exp; /* Exponent read from "EX" field. */ + int fracExp; /* Exponent that derives from the fractional + * part. Under normal circumstatnces, it is + * the negative of the number of digits in F. + * However, if I is very long, the last digits + * of I get dropped (otherwise a long I with a + * large negative exponent could cause an + * unnecessary overflow on I alone). In this + * case, fracExp is incremented one for each + * dropped digit. */ + int mantSize; /* Number of digits in mantissa. */ + int decPt; /* Number of mantissa digits BEFORE decimal + * point. */ + const char *pExp; /* Temporarily holds location of exponent + * in string. */ + /* + * Strip off leading blanks and check for a sign. + */ + p = string; + while (ISSPACE(*p)) { - if (c != L_('0') && lead_zero == -1) - lead_zero = dig_no - int_no; - ++dig_no; - c = *++cp; + p += 1; } - } - - /* Remember start of exponent (if any). */ - expp = cp; - - /* Read exponent. */ - if ((base == 16 && TOLOWER (c) == L_('p')) - || (base != 16 && TOLOWER (c) == L_('e'))) - { - int exp_negative = 0; - - c = *++cp; - if (c == L_('-')) + if (*p == '-') { - exp_negative = 1; - c = *++cp; - } - else if (c == L_('+')) - c = *++cp; - - if (c >= L_('0') && c <= L_('9')) + sign = TRUE; + p += 1; + } else { - int exp_limit; - - /* Get the exponent limit. */ - if (base == 16) - exp_limit = (exp_negative ? - -MIN_EXP + MANT_DIG - 4 * int_no : - MAX_EXP - 4 * int_no + lead_zero); - else - exp_limit = (exp_negative ? - -MIN_10_EXP + MANT_DIG - int_no : - MAX_10_EXP - int_no + lead_zero); - - do - { - exponent *= 10; - - if (exponent > exp_limit) - /* The exponent is too large/small to represent a valid - number. */ + if (*p == '+') { - FLOAT result; - - /* We have to take care for special situation: a joker - might have written "0.0e100000" which is in fact - zero. */ - if (lead_zero == -1) - result = negative ? -0.0 : 0.0; - else - { - /* Overflow or underflow. */ - __set_errno (ERANGE); - result = (exp_negative ? 0.0 : - negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL); - } - - /* Accept all following digits as part of the exponent. */ - do - ++cp; - while (*cp >= L_('0') && *cp <= L_('9')); - - RETURN (result, cp); - /* NOTREACHED */ + p += 1; } - - exponent += c - L_('0'); - c = *++cp; - } - while (c >= L_('0') && c <= L_('9')); - - if (exp_negative) - exponent = -exponent; - } - else - cp = expp; - } - - /* We don't want to have to work with trailing zeroes after the radix. */ - if (dig_no > int_no) - { - while (expp[-1] == L_('0')) - { - --expp; - --dig_no; - } - assert (dig_no >= int_no); - } - - number_parsed: - - /* The whole string is parsed. Store the address of the next character. */ - if (endptr) - *endptr = (STRING_TYPE *) cp; - - if (dig_no == 0) - return negative ? -0.0 : 0.0; - - if (lead_zero) - { - /* Find the decimal point */ - while ((wchar_t) *startp != decimal) - ++startp; - startp += lead_zero + 1; - exponent -= base == 16 ? 4 * lead_zero : lead_zero; - dig_no -= lead_zero; - } - - /* If the BASE is 16 we can use a simpler algorithm. */ - if (base == 16) - { - static const int nbits[16] = { 0, 1, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4 }; - int idx = (MANT_DIG - 1) / BITS_PER_MP_LIMB; - int pos = (MANT_DIG - 1) % BITS_PER_MP_LIMB; - mp_limb_t val; - - while (!ISXDIGIT (*startp)) - ++startp; - if (ISDIGIT (*startp)) - val = *startp++ - L_('0'); - else - val = 10 + TOLOWER (*startp++) - L_('a'); - bits = nbits[val]; - - if (pos + 1 >= 4 || pos + 1 >= bits) - { - /* We don't have to care for wrapping. This is the normal - case so we add the first clause in the `if' expression as - an optimization. It is a compile-time constant and so does - not cost anything. */ - retval[idx] = val << (pos - bits + 1); - pos -= bits; + sign = FALSE; } - else - { - retval[idx--] = val >> (bits - pos - 1); - retval[idx] = val << (BITS_PER_MP_LIMB - (bits - pos - 1)); - pos = BITS_PER_MP_LIMB - 1 - (bits - pos - 1); - } - - while (--dig_no > 0 && idx >= 0) + /* + * Count the number of digits in the mantissa (including the decimal + * point), and also locate the decimal point. + */ + decPt = -1; + for (mantSize = 0;; mantSize += 1) { - while (!ISXDIGIT (*startp)) - ++startp; - if (ISDIGIT (*startp)) - val = *startp++ - L_('0'); - else - val = 10 + TOLOWER (*startp++) - L_('a'); - - if (pos + 1 >= 4) - { - retval[idx] |= val << (pos - 4 + 1); - pos -= 4; - } - else - { - retval[idx--] |= val >> (4 - pos - 1); - val <<= BITS_PER_MP_LIMB - (4 - pos - 1); - if (idx < 0) - return round_and_return (retval, exponent, negative, val, - BITS_PER_MP_LIMB - 1, dig_no > 0); - - retval[idx] = val; - pos = BITS_PER_MP_LIMB - 1 - (4 - pos - 1); - } - } - - /* We ran out of digits. */ - MPN_ZERO (retval, idx); - - return round_and_return (retval, exponent, negative, 0, 0, 0); - } - - /* Now we have the number of digits in total and the integer digits as well - as the exponent and its sign. We can decide whether the read digits are - really integer digits or belong to the fractional part; i.e. we normalize - 123e-2 to 1.23. */ - { - register int incr = (exponent < 0 ? MAX (-int_no, exponent) - : MIN (dig_no - int_no, exponent)); - int_no += incr; - exponent -= incr; - } - - if (int_no + exponent > MAX_10_EXP + 1) - { - __set_errno (ERANGE); - return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; - } - - if (exponent < MIN_10_EXP - (DIG + 1)) - { - __set_errno (ERANGE); - return 0.0; - } - - if (int_no > 0) - { - /* Read the integer part as a multi-precision number to NUM. */ - startp = str_to_mpn (startp, int_no, num, &numsize, &exponent); - - if (exponent > 0) - { - /* We now multiply the gained number by the given power of ten. */ - mp_limb_t *psrc = num; - mp_limb_t *pdest = den; - int expbit = 1; - const struct mp_power *ttab = &_fpioconst_pow10[0]; - - do - { - if ((exponent & expbit) != 0) + c = *p; + if (!ISDIGIT(c)) { - size_t size = ttab->arraysize - _FPIO_CONST_OFFSET; - mp_limb_t cy; - exponent ^= expbit; - - /* FIXME: not the whole multiplication has to be - done. If we have the needed number of bits we - only need the information whether more non-zero - bits follow. */ - if (numsize >= ttab->arraysize - _FPIO_CONST_OFFSET) - cy = __mpn_mul (pdest, psrc, numsize, - &__tens[ttab->arrayoff - + _FPIO_CONST_OFFSET], - size); - else - cy = __mpn_mul (pdest, &__tens[ttab->arrayoff - + _FPIO_CONST_OFFSET], - size, psrc, numsize); - numsize += size; - if (cy == 0) - --numsize; - SWAP (psrc, pdest); + if (c != '.' || decPt >= 0) + { + break; + } + decPt = mantSize; } - expbit <<= 1; - ++ttab; - } - while (exponent != 0); - - if (psrc == den) - memcpy (num, den, numsize * sizeof (mp_limb_t)); + p += 1; } - - /* Determine how many bits of the result we already have. */ - count_leading_zeros (bits, num[numsize - 1]); - bits = numsize * BITS_PER_MP_LIMB - bits; - - /* Now we know the exponent of the number in base two. - Check it against the maximum possible exponent. */ - if (bits > MAX_EXP) + /* + * Now suck up the digits in the mantissa. Use two integers to + * collect 9 digits each (this is faster than using floating-point). + * If the mantissa has more than 18 digits, ignore the extras, since + * they can't affect the value anyway. + */ + + pExp = p; + p -= mantSize; + if (decPt < 0) { - __set_errno (ERANGE); - return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; - } - - /* We have already the first BITS bits of the result. Together with - the information whether more non-zero bits follow this is enough - to determine the result. */ - if (bits > MANT_DIG) + decPt = mantSize; + } else { - int i; - const mp_size_t least_idx = (bits - MANT_DIG) / BITS_PER_MP_LIMB; - const mp_size_t least_bit = (bits - MANT_DIG) % BITS_PER_MP_LIMB; - const mp_size_t round_idx = least_bit == 0 ? least_idx - 1 - : least_idx; - const mp_size_t round_bit = least_bit == 0 ? BITS_PER_MP_LIMB - 1 - : least_bit - 1; - - if (least_bit == 0) - memcpy (retval, &num[least_idx], - RETURN_LIMB_SIZE * sizeof (mp_limb_t)); - else - { - for (i = least_idx; i < numsize - 1; ++i) - retval[i - least_idx] = (num[i] >> least_bit) - | (num[i + 1] - << (BITS_PER_MP_LIMB - least_bit)); - if (i - least_idx < RETURN_LIMB_SIZE) - retval[RETURN_LIMB_SIZE - 1] = num[i] >> least_bit; - } - - /* Check whether any limb beside the ones in RETVAL are non-zero. */ - for (i = 0; num[i] == 0; ++i) - ; - - return round_and_return (retval, bits - 1, negative, - num[round_idx], round_bit, - int_no < dig_no || i < round_idx); - /* NOTREACHED */ + mantSize -= 1; /* One of the digits was the point. */ } - else if (dig_no == int_no) + fracExp = decPt - mantSize; + if (mantSize == 0) { - const mp_size_t target_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; - const mp_size_t is_bit = (bits - 1) % BITS_PER_MP_LIMB; - - if (target_bit == is_bit) - { - memcpy (&retval[RETURN_LIMB_SIZE - numsize], num, - numsize * sizeof (mp_limb_t)); - /* FIXME: the following loop can be avoided if we assume a - maximal MANT_DIG value. */ - MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize); - } - else if (target_bit > is_bit) - { - (void) __mpn_lshift (&retval[RETURN_LIMB_SIZE - numsize], - num, numsize, target_bit - is_bit); - /* FIXME: the following loop can be avoided if we assume a - maximal MANT_DIG value. */ - MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize); - } - else - { - mp_limb_t cy; - assert (numsize < RETURN_LIMB_SIZE); - - cy = __mpn_rshift (&retval[RETURN_LIMB_SIZE - numsize], - num, numsize, is_bit - target_bit); - retval[RETURN_LIMB_SIZE - numsize - 1] = cy; - /* FIXME: the following loop can be avoided if we assume a - maximal MANT_DIG value. */ - MPN_ZERO (retval, RETURN_LIMB_SIZE - numsize - 1); - } - - return round_and_return (retval, bits - 1, negative, 0, 0, 0); - /* NOTREACHED */ - } - - /* Store the bits we already have. */ - memcpy (retval, num, numsize * sizeof (mp_limb_t)); -#if RETURN_LIMB_SIZE > 1 - if (numsize < RETURN_LIMB_SIZE) - retval[numsize] = 0; -#endif - } - - /* We have to compute at least some of the fractional digits. */ - { - /* We construct a fraction and the result of the division gives us - the needed digits. The denominator is 1.0 multiplied by the - exponent of the lowest digit; i.e. 0.123 gives 123 / 1000 and - 123e-6 gives 123 / 1000000. */ - - int expbit; - int cnt; - int neg_exp; - int more_bits; - mp_limb_t cy; - mp_limb_t *psrc = den; - mp_limb_t *pdest = num; - const struct mp_power *ttab = &_fpioconst_pow10[0]; - - assert (dig_no > int_no && exponent <= 0); - - - /* For the fractional part we need not process too many digits. One - decimal digits gives us log_2(10) ~ 3.32 bits. If we now compute - ceil(BITS / 3) =: N - digits we should have enough bits for the result. The remaining - decimal digits give us the information that more bits are following. - This can be used while rounding. (One added as a safety margin.) */ - if (dig_no - int_no > (MANT_DIG - bits + 2) / 3 + 1) - { - dig_no = int_no + (MANT_DIG - bits + 2) / 3 + 1; - more_bits = 1; - } - else - more_bits = 0; - - neg_exp = dig_no - int_no - exponent; - - /* Construct the denominator. */ - densize = 0; - expbit = 1; - do - { - if ((neg_exp & expbit) != 0) - { - mp_limb_t cy; - neg_exp ^= expbit; - - if (densize == 0) - { - densize = ttab->arraysize - _FPIO_CONST_OFFSET; - memcpy (psrc, &__tens[ttab->arrayoff + _FPIO_CONST_OFFSET], - densize * sizeof (mp_limb_t)); - } - else - { - cy = __mpn_mul (pdest, &__tens[ttab->arrayoff - + _FPIO_CONST_OFFSET], - ttab->arraysize - _FPIO_CONST_OFFSET, - psrc, densize); - densize += ttab->arraysize - _FPIO_CONST_OFFSET; - if (cy == 0) - --densize; - SWAP (psrc, pdest); - } - } - expbit <<= 1; - ++ttab; - } - while (neg_exp != 0); - - if (psrc == num) - memcpy (den, num, densize * sizeof (mp_limb_t)); - - /* Read the fractional digits from the string. */ - (void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent); - - - /* We now have to shift both numbers so that the highest bit in the - denominator is set. In the same process we copy the numerator to - a high place in the array so that the division constructs the wanted - digits. This is done by a "quasi fix point" number representation. - - num: ddddddddddd . 0000000000000000000000 - |--- m ---| - den: ddddddddddd n >= m - |--- n ---| - */ - - count_leading_zeros (cnt, den[densize - 1]); - - if (cnt > 0) - { - /* Don't call `mpn_shift' with a count of zero since the specification - does not allow this. */ - (void) __mpn_lshift (den, den, densize, cnt); - cy = __mpn_lshift (num, num, numsize, cnt); - if (cy != 0) - num[numsize++] = cy; - } - - /* Now we are ready for the division. But it is not necessary to - do a full multi-precision division because we only need a small - number of bits for the result. So we do not use __mpn_divmod - here but instead do the division here by hand and stop whenever - the needed number of bits is reached. The code itself comes - from the GNU MP Library by Torbj\"orn Granlund. */ - - exponent = bits; - - switch (densize) - { - case 1: + fraction = 0.0; + p = string; + goto done; + } else { - mp_limb_t d, n, quot; - int used = 0; - - n = num[0]; - d = den[0]; - assert (numsize == 1 && n < d); - - do - { - udiv_qrnnd (quot, n, n, 0, d); + long frac1; + mant_t frac2; -#define got_limb \ - if (bits == 0) \ - { \ - register int cnt; \ - if (quot == 0) \ - cnt = BITS_PER_MP_LIMB; \ - else \ - count_leading_zeros (cnt, quot); \ - exponent -= cnt; \ - if (BITS_PER_MP_LIMB - cnt > MANT_DIG) \ - { \ - used = MANT_DIG + cnt; \ - retval[0] = quot >> (BITS_PER_MP_LIMB - used); \ - bits = MANT_DIG + 1; \ - } \ - else \ - { \ - /* Note that we only clear the second element. */ \ - /* The conditional is determined at compile time. */ \ - if (RETURN_LIMB_SIZE > 1) \ - retval[1] = 0; \ - retval[0] = quot; \ - bits = -cnt; \ - } \ - } \ - else if (bits + BITS_PER_MP_LIMB <= MANT_DIG) \ - __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, BITS_PER_MP_LIMB, \ - quot); \ - else \ - { \ - used = MANT_DIG - bits; \ - if (used > 0) \ - __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, quot); \ - } \ - bits += BITS_PER_MP_LIMB - - got_limb; - } - while (bits <= MANT_DIG); - - return round_and_return (retval, exponent - 1, negative, - quot, BITS_PER_MP_LIMB - 1 - used, - more_bits || n != 0); - } - case 2: - { - mp_limb_t d0, d1, n0, n1; - mp_limb_t quot = 0; - int used = 0; - - d0 = den[0]; - d1 = den[1]; - - if (numsize < densize) - { - if (num[0] >= d1) - { - /* The numerator of the number occupies fewer bits than - the denominator but the one limb is bigger than the - high limb of the numerator. */ - n1 = 0; - n0 = num[0]; - } - else + frac1 = 0; + for (; mantSize > 9; mantSize -= 1) { - if (bits <= 0) - exponent -= BITS_PER_MP_LIMB; - else - { - if (bits + BITS_PER_MP_LIMB <= MANT_DIG) - __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, - BITS_PER_MP_LIMB, 0); - else + c = *p; + p += 1; + if (c == '.') { - used = MANT_DIG - bits; - if (used > 0) - __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); + c = *p; + p += 1; } - bits += BITS_PER_MP_LIMB; - } - n1 = num[0]; - n0 = 0; + frac1 = 10 * frac1 + (c - '0'); } - } - else - { - n1 = num[1]; - n0 = num[0]; - } - - while (bits <= MANT_DIG) - { - mp_limb_t r; - - if (n1 == d1) + frac2 = 0; + for (; mantSize > 0; mantSize -= 1) { - /* QUOT should be either 111..111 or 111..110. We need - special treatment of this rare case as normal division - would give overflow. */ - quot = ~(mp_limb_t) 0; - - r = n0 + d1; - if (r < d1) /* Carry in the addition? */ - { - add_ssaaaa (n1, n0, r - d0, 0, 0, d0); - goto have_quot; - } - n1 = d0 - (d0 != 0); - n0 = -d0; - } - else - { - udiv_qrnnd (quot, r, n1, n0, d1); - umul_ppmm (n1, n0, d0, quot); - } - - q_test: - if (n1 > r || (n1 == r && n0 > 0)) - { - /* The estimated QUOT was too large. */ - --quot; - - sub_ddmmss (n1, n0, n1, n0, 0, d0); - r += d1; - if (r >= d1) /* If not carry, test QUOT again. */ - goto q_test; + c = *p; + p += 1; + if (c == '.') + { + c = *p; + p += 1; + } + frac2 = 10 * frac2 + (c - '0'); } - sub_ddmmss (n1, n0, r, 0, n1, n0); - - have_quot: - got_limb; - } - - return round_and_return (retval, exponent - 1, negative, - quot, BITS_PER_MP_LIMB - 1 - used, - more_bits || n1 != 0 || n0 != 0); + fraction = (1.0e9 * frac1) + frac2; } - default: + /* + * Skim off the exponent. + */ + exp = 0; + expSign = FALSE; + p = pExp; + if (*p == 'E' || *p == 'e') { - int i; - mp_limb_t cy, dX, d1, n0, n1; - mp_limb_t quot = 0; - int used = 0; - - dX = den[densize - 1]; - d1 = den[densize - 2]; - - /* The division does not work if the upper limb of the two-limb - numerator is greater than the denominator. */ - if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0) - num[numsize++] = 0; - - if (numsize < densize) - { - mp_size_t empty = densize - numsize; - - if (bits <= 0) + p += 1; + if (*p == '-') { - register int i; - for (i = numsize; i > 0; --i) - num[i + empty] = num[i - 1]; - MPN_ZERO (num, empty + 1); - exponent -= empty * BITS_PER_MP_LIMB; - } - else + expSign = TRUE; + p += 1; + } else { - if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG) - { - /* We make a difference here because the compiler - cannot optimize the `else' case that good and - this reflects all currently used FLOAT types - and GMP implementations. */ - register int i; -#if RETURN_LIMB_SIZE <= 2 - assert (empty == 1); - __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, - BITS_PER_MP_LIMB, 0); -#else - for (i = RETURN_LIMB_SIZE; i > empty; --i) - retval[i] = retval[i - empty]; -#endif -#if RETURN_LIMB_SIZE > 1 - retval[1] = 0; -#endif - for (i = numsize; i > 0; --i) - num[i + empty] = num[i - 1]; - MPN_ZERO (num, empty + 1); - } - else - { - used = MANT_DIG - bits; - if (used >= BITS_PER_MP_LIMB) + if (*p == '+') { - register int i; - (void) __mpn_lshift (&retval[used - / BITS_PER_MP_LIMB], - retval, RETURN_LIMB_SIZE, - used % BITS_PER_MP_LIMB); - for (i = used / BITS_PER_MP_LIMB; i >= 0; --i) - retval[i] = 0; + p += 1; } - else if (used > 0) - __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0); - } - bits += empty * BITS_PER_MP_LIMB; } - } - else - { - int i; - assert (numsize == densize); - for (i = numsize; i > 0; --i) - num[i] = num[i - 1]; - } - - den[densize] = 0; - n0 = num[densize]; - - while (bits <= MANT_DIG) - { - if (n0 == dX) - /* This might over-estimate QUOT, but it's probably not - worth the extra code here to find out. */ - quot = ~(mp_limb_t) 0; - else + for (;;) { - mp_limb_t r; - - udiv_qrnnd (quot, r, n0, num[densize - 1], dX); - umul_ppmm (n1, n0, d1, quot); - - while (n1 > r || (n1 == r && n0 > num[densize - 2])) - { - --quot; - r += dX; - if (r < dX) /* I.e. "carry in previous addition?" */ - break; - n1 -= n0 < d1; - n0 -= d1; - } + c = *p; + if (!ISDIGIT(c)) + break; + exp = exp * 10 + (*p - '0'); + p += 1; + if (exp > MAX_10_EXP) + { + /* Accept all following digits as part of the exponent. */ + for (;;) + { + c = *p; + if (!ISDIGIT(c)) + break; + } + errno = ERANGE; + if (endptr != NULL) + { + *endptr = (STRING_TYPE *) p; + } + return sign ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; + } } - - /* Possible optimization: We already have (q * n0) and (1 * n1) - after the calculation of QUOT. Taking advantage of this, we - could make this loop make two iterations less. */ - - cy = __mpn_submul_1 (num, den, densize + 1, quot); - - if (num[densize] != cy) + } + if (expSign) + { + exp = fracExp - exp; + } else + { + exp = fracExp + exp; + } + /* + * Generate a floating-point number that represents the exponent. + * Do this by processing the exponent one bit at a time to combine + * many powers of 2 of 10. Then combine the exponent with the + * fraction. + */ + + if (exp < 0) + { + expSign = TRUE; + exp = -exp; + } else + { + expSign = FALSE; + } + dblExp = 1.0; + for (d = powersOf10; exp != 0; exp >>= 1, d += 1) + { + if (exp & 01) { - cy = __mpn_add_n (num, num, den, densize); - assert (cy != 0); - --quot; + dblExp *= *d; } - n0 = num[densize] = num[densize - 1]; - for (i = densize - 1; i > 0; --i) - num[i] = num[i - 1]; - - got_limb; - } - - for (i = densize; num[i] == 0 && i >= 0; --i) - ; - return round_and_return (retval, exponent - 1, negative, - quot, BITS_PER_MP_LIMB - 1 - used, - more_bits || i >= 0); } - } - } - - /* NOTREACHED */ + if (expSign) + { + fraction /= dblExp; + } else + { + fraction *= dblExp; + } + done: + if (endptr != NULL) + { + *endptr = (STRING_TYPE *) p; + } + if (sign) + { + return -fraction; + } + return fraction; } - + /* External user entry point. */ FLOAT @@ -1462,5 +483,5 @@ weak_function #endif STRTOF (const STRING_TYPE *nptr, STRING_TYPE **endptr LOCALE_PARAM_DECL) { - return INTERNAL (STRTOF) (nptr, endptr, 0 LOCALE_PARAM); + return INTERNAL (STRTOF) (nptr, endptr, 0 LOCALE_PARAM); } diff --git a/stdlib/strtof.c b/stdlib/strtof.c index 5a5eae85..934f1d63 100644 --- a/stdlib/strtof.c +++ b/stdlib/strtof.c @@ -1,23 +1,5 @@ /* The actual implementation for all floating point sizes is in strtod.c. These macros tell it to produce the `float' version, `strtof'. */ -#define FLOAT float -#define FLT FLT -#ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define STRTOF __strtof_l -#else -# define STRTOF strtof -#endif -#define MPN2FLOAT __mpn_construct_float -#define FLOAT_HUGE_VAL __builtin_inff() -#define FLOAT_NAN_VAL __builtin_nanf("") -#define SET_MANTISSA(flt, mant) \ - do { union ieee754_float u; \ - u.f = (flt); \ - if ((mant & 0x7fffff) == 0) \ - mant = 0x400000; \ - u.ieee.mantissa = (mant) & 0x7fffff; \ - (flt) = u.f; \ - } while (0) - +#define FLOAT_TYPE 0 #include "strtod.c" diff --git a/stdlib/strtold.c b/stdlib/strtold.c index a2152785..54db0ca3 100644 --- a/stdlib/strtold.c +++ b/stdlib/strtold.c @@ -8,26 +8,7 @@ /* The actual implementation for all floating point sizes is in strtod.c. These macros tell it to produce the `long double' version, `strtold'. */ -# define FLOAT long double -# define FLT LDBL -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define STRTOF __strtold_l -# else -# define STRTOF strtold -# endif -# define MPN2FLOAT __mpn_construct_long_double -# define FLOAT_HUGE_VAL __builtin_infl() -# define FLOAT_NAN_VAL __builtin_nanl("") -# define SET_MANTISSA(flt, mant) \ - do { union ieee854_long_double u; \ - u.d = (flt); \ - if ((mant & 0x7fffffffffffffffULL) == 0) \ - mant = 0x4000000000000000ULL; \ - u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000; \ - u.ieee.mantissa1 = (mant) & 0xffffffff; \ - (flt) = u.d; \ - } while (0) - +# define FLOAT_TYPE 2 # include "strtod.c" #else diff --git a/stdlib/test-strtod.c b/stdlib/test-strtod.c index 821be7cf..bcceb6c4 100644 --- a/stdlib/test-strtod.c +++ b/stdlib/test-strtod.c @@ -21,115 +21,124 @@ #include #include +#include "strtod.c" + struct ltest - { - const char *str; /* Convert this. */ - double expect; /* To get this. */ - char left; /* With this left over. */ - int err; /* And this in errno. */ - }; -static const struct ltest tests[] = - { - { "12.345", 12.345, '\0', 0 }, - { "12.345e19", 12.345e19, '\0', 0 }, - { "-.1e+9", -.1e+9, '\0', 0 }, - { ".125", .125, '\0', 0 }, - { "1e20", 1e20, '\0', 0 }, - { "0e-19", 0, '\0', 0 }, - { "4\00012", 4.0, '\0', 0 }, - { "5.9e-76", 5.9e-76, '\0', 0 }, - { NULL, 0, '\0', 0 } - }; - -static void expand (char *dst, int c); -static int long_dbl (void); - -int -main (int argc, char ** argv) { - char buf[100]; - register const struct ltest *lt; - char *ep; - int status = 0; - int save_errno; - - for (lt = tests; lt->str != NULL; ++lt) - { - double d; - - __set_errno (0); - d = strtod(lt->str, &ep); - save_errno = errno; - printf ("strtod (\"%s\") test %u", - lt->str, (unsigned int) (lt - tests)); - if (d == lt->expect && *ep == lt->left && save_errno == lt->err) - puts ("\tOK"); - else + const char *str; /* Convert this. */ + FLOAT expect; /* To get this. */ + char left; /* With this left over. */ + int err; /* And this in errno. */ +}; + +static const struct ltest tests[] = { + { "12.345", 12.345, '\0', 0 }, + { "12.345e19", 12.345e19, '\0', 0 }, + { "-.1e+9", -.1e+9, '\0', 0 }, + { ".125", .125, '\0', 0 }, + { "1e20", 1e20, '\0', 0 }, + { "0e-19", 0, '\0', 0 }, + { "4\00012", 4.0, '\0', 0 }, + { "5.9e-76", 5.9e-76, '\0', 0 }, + { "1.0", 1.0, '\0', 0 }, + { "1.", 1.0, '\0', 0 }, + { "0.1", 0.1, '\0', 0 }, + { ".1", 0.1, '\0', 0 }, + { "0.000000000000000000000000000000000000783475", 7.834750e-37, '\0', 0 }, + { NULL, 0, '\0', 0 } +}; + + +static unsigned int testnum; + +static void expand(char *dst, int c) +{ + if (isprint(c)) { - puts ("\tBAD"); - if (d != lt->expect) - printf (" returns %.60g, expected %.60g\n", d, lt->expect); - if (lt->left != *ep) - { - char exp1[5], exp2[5]; - expand (exp1, *ep); - expand (exp2, lt->left); - printf (" leaves '%s', expected '%s'\n", exp1, exp2); - } - if (save_errno != lt->err) - printf (" errno %d (%s) instead of %d (%s)\n", - save_errno, strerror (save_errno), - lt->err, strerror (lt->err)); - status = 1; - } - } + dst[0] = c; + dst[1] = '\0'; + } else + (void) sprintf(dst, "%#.3o", (unsigned int) c); +} - sprintf (buf, "%f", strtod ("-0.0", NULL)); - if (strcmp (buf, "-0.000000") != 0) - { - printf (" strtod (\"-0.0\', NULL) returns \"%s\"\n", buf); - status = 1; - } +static int long_dbl(void) +{ + /* Regenerate this string using - status |= long_dbl (); + echo '(2^53-1)*2^(1024-53)' | bc | sed 's/\([^\]*\)\\*$/ "\1"/' - exit (status ? EXIT_FAILURE : EXIT_SUCCESS); -} + */ + static const char longestdbl[] = + "17976931348623157081452742373170435679807056752584499659891747680315" + "72607800285387605895586327668781715404589535143824642343213268894641" + "82768467546703537516986049910576551282076245490090389328944075868508" + "45513394230458323690322294816580855933212334827479782620414472316873" + "8177180919299881250404026184124858368"; + double d = STRTOF(longestdbl, NULL); -static void -expand (dst, c) - char *dst; - register int c; -{ - if (isprint (c)) - { - dst[0] = c; - dst[1] = '\0'; - } - else - (void) sprintf (dst, "%#.3o", (unsigned int) c); + printf("strtod (\"%s\", NULL) = %g test %u", longestdbl, d, testnum); + + if (d != + 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000) + { + puts("\tBAD"); + return 1; + } + + puts("\tOK"); + return 0; } -static int -long_dbl (void) +int main(int argc, char **argv) { - /* Regenerate this string using - - echo '(2^53-1)*2^(1024-53)' | bc | sed 's/\([^\]*\)\\*$/ "\1"/' + char buf[100]; + const struct ltest *lt; + char *ep; + int status = 0; + int save_errno; - */ - static const char longestdbl[] = - "17976931348623157081452742373170435679807056752584499659891747680315" - "72607800285387605895586327668781715404589535143824642343213268894641" - "82768467546703537516986049910576551282076245490090389328944075868508" - "45513394230458323690322294816580855933212334827479782620414472316873" - "8177180919299881250404026184124858368"; - double d = strtod (longestdbl, NULL); + for (lt = tests; lt->str != NULL; ++lt) + { + double d; + + errno = 0; + d = STRTOF(lt->str, &ep); + save_errno = errno; + printf("strtod (\"%s\") test %u", lt->str, testnum); + testnum++; + if (d == lt->expect && *ep == lt->left && save_errno == lt->err) + { + puts("\tOK"); + } else + { + puts("\tBAD"); + if (d != lt->expect) + printf(" returns %.60g, expected %.60g\n", d, lt->expect); + if (lt->left != *ep) + { + char exp1[5], + exp2[5]; + + expand(exp1, *ep); + expand(exp2, lt->left); + printf(" leaves '%s', expected '%s'\n", exp1, exp2); + } + if (save_errno != lt->err) + printf(" errno %d (%s) instead of %d (%s)\n", + save_errno, strerror(save_errno), lt->err, strerror(lt->err)); + status = 1; + } + } - printf ("strtod (\"%s\", NULL) = %g\n", longestdbl, d); + sprintf(buf, "%f", STRTOF("-0.0", NULL)); + if (strcmp(buf, "-0.000000") != 0) + { + printf(" strtod (\"-0.0\', NULL) returns \"%s\"\n", buf); + status = 1; + } - if (d != 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000) - return 1; + status |= long_dbl(); + testnum++; - return 0; + exit(status ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/string/Makefile b/string/Makefile index ed550fd2..5cd17ca9 100644 --- a/string/Makefile +++ b/string/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony # FIXME: stratcliff still missing because of missing mman.h. diff --git a/sunrpc/Makefile b/sunrpc/Makefile index 18694453..a1a583cc 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -32,7 +32,6 @@ else all-here: rpcgen rpcinfo endif -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony include $(srcdir)/RPCSVCCFILES include $(srcdir)/RPCGENCFILES diff --git a/syscall/Makefile b/syscall/Makefile index 745b0a46..cbef3b12 100644 --- a/syscall/Makefile +++ b/syscall/Makefile @@ -26,7 +26,6 @@ gen_objs += syscallparser.c all-here: syscalls.stmp -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony # FIXME: Tests still missing. diff --git a/sysvipc/Makefile b/sysvipc/Makefile index d97d061c..d161a103 100644 --- a/sysvipc/Makefile +++ b/sysvipc/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/termios/Makefile b/termios/Makefile index b9098f1a..46dd5869 100644 --- a/termios/Makefile +++ b/termios/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony install-include: diff --git a/time/Makefile b/time/Makefile index 231a56b1..aa3713b2 100644 --- a/time/Makefile +++ b/time/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = clock getdate posixtz strptime time diff --git a/tz/Makefile b/tz/Makefile index 5f512edc..3b8c151a 100644 --- a/tz/Makefile +++ b/tz/Makefile @@ -22,8 +22,6 @@ srcdir = . top_srcdir = .. subdir = tz -dont_install_libs = yes - include $(top_srcdir)/configvars default: all diff --git a/unix/Makefile b/unix/Makefile index 252f5f37..cabb3462 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -26,7 +26,6 @@ default: all all-here: -dont_install_libs = yes include $(top_srcdir)/rules $(top_srcdir)/phony TESTS = fdset open opendir select stat time utime vfork