Import correctly working strtold from David M. Gay.

* libc/stdlib/Makefile.am (GENERAL_SOURCES): Add strtodg.c and
	strtorx.c.
	* libc/stdlib/Makefile.in: Regenerate.
	* libc/stdlib/strtodg.c: New file implementing generic string to long
	double conversion.
	* libc/stdlib/strtorx.c: New file, implementing IEEE format string to
	long double conversion.
	* libc/stdlib/mprec.h (_strtodg_r): Declare.
	(_strtorx_r): Declare.
	* libc/stdlib/gdtoa.h (__UShort): Define.
	* libc/stdlib/strtold.c (__flt_rounds): Define for i386 and x86_64
	target.
	(FLT_ROUNDS): Define, as 0 on platforms missing a __flt_rounds
	function.
	(_strtold_r): Converted from strtold.  Call _strtorx_r on targets
	supporting distinct long doubles.
	(strtold): Just call _strtold_r.
	* libc/include/stdlib.h (_strtold_r): Declare.
	* libc/stdlib/ldtoa.c (_strtold): Comment out.  Explain why.
	* libc/stdio/vfscanf.c (__SVFSCANF_R): Call _strtold_r instead of
	_strtold.
	* libc/machine/powerpc/vfscanf.c (__svfscanf_r): Ditto.

	* common.din (strtold): Drop redirection to _strtold.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2015-11-20 18:14:58 +01:00
parent 51bf1b81f3
commit fbace81684
14 changed files with 1371 additions and 21 deletions

View File

@ -1,3 +1,28 @@
2015-11-20 Corinna Vinschen <corinna@vinschen.de>
* libc/stdlib/Makefile.am (GENERAL_SOURCES): Add strtodg.c and
strtorx.c.
* libc/stdlib/Makefile.in: Regenerate.
* libc/stdlib/strtodg.c: New file implementing generic string to long
double conversion.
* libc/stdlib/strtorx.c: New file, implementing IEEE format string to
long double conversion.
* libc/stdlib/mprec.h (_strtodg_r): Declare.
(_strtorx_r): Declare.
* libc/stdlib/gdtoa.h (__UShort): Define.
* libc/stdlib/strtold.c (__flt_rounds): Define for i386 and x86_64
target.
(FLT_ROUNDS): Define, as 0 on platforms missing a __flt_rounds
function.
(_strtold_r): Converted from strtold. Call _strtorx_r on targets
supporting distinct long doubles.
(strtold): Just call _strtold_r.
* libc/include/stdlib.h (_strtold_r): Declare.
* libc/stdlib/ldtoa.c (_strtold): Comment out. Explain why.
* libc/stdio/vfscanf.c (__SVFSCANF_R): Call _strtold_r instead of
_strtold.
* libc/machine/powerpc/vfscanf.c (__svfscanf_r): Ditto.
2015-11-20 Corinna Vinschen <corinna@vinschen.de>
* libc/stdlib/strtod.c (match): Move from here...

View File

@ -274,6 +274,7 @@ _VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, int (*_compar)
/* On platforms where long double equals double. */
#ifdef _HAVE_LONG_DOUBLE
extern long double _strtold_r (struct _reent *, const char *__restrict, char **__restrict);
#if !defined(__STRICT_ANSI__) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
(defined(__cplusplus) && __cplusplus >= 201103L)

View File

@ -131,7 +131,6 @@ Supporting OS subroutines required:
#define _NO_LONGDBL
#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
#undef _NO_LONGDBL
extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
#endif
#define _NO_LONGLONG
@ -1211,7 +1210,7 @@ __svfscanf_r (rptr, fp, fmt0, ap)
#ifdef _NO_LONGDBL
res = _strtod_r (rptr, buf, NULL);
#else /* !_NO_LONGDBL */
res = _strtold (buf, NULL);
res = _strtold_r (rptr, buf, NULL);
#endif /* !_NO_LONGDBL */
if (flags & LONG)
{

View File

@ -170,7 +170,6 @@ Supporting OS subroutines required:
#define _NO_LONGDBL
#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
#undef _NO_LONGDBL
extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
#endif
#include "floatio.h"
@ -1596,12 +1595,13 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
sprintf (exp_start, "e%ld", new_exp);
}
/* Current _strtold routine is markedly slower than
/* FIXME: Is that still true?
Current _strtold routine is markedly slower than
_strtod_r. Only use it if we have a long double
result. */
#ifndef _NO_LONGDBL /* !_NO_LONGDBL */
if (flags & LONGDBL)
qres = _strtold (buf, NULL);
qres = _strtold_r (rptr, buf, NULL);
else
#endif
res = _strtod_r (rptr, buf, NULL);

View File

@ -53,7 +53,9 @@ GENERAL_SOURCES = \
reallocf.c \
sb_charsets.c \
strtod.c \
strtodg.c \
strtol.c \
strtorx.c \
strtoul.c \
utoa.c \
wcstod.c \

View File

@ -105,7 +105,8 @@ am__objects_2 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \
lib_a-rand.$(OBJEXT) lib_a-rand_r.$(OBJEXT) \
lib_a-realloc.$(OBJEXT) lib_a-reallocf.$(OBJEXT) \
lib_a-sb_charsets.$(OBJEXT) lib_a-strtod.$(OBJEXT) \
lib_a-strtol.$(OBJEXT) lib_a-strtoul.$(OBJEXT) \
lib_a-strtodg.$(OBJEXT) lib_a-strtol.$(OBJEXT) \
lib_a-strtorx.$(OBJEXT) lib_a-strtoul.$(OBJEXT) \
lib_a-utoa.$(OBJEXT) lib_a-wcstod.$(OBJEXT) \
lib_a-wcstol.$(OBJEXT) lib_a-wcstoul.$(OBJEXT) \
lib_a-wcstombs.$(OBJEXT) lib_a-wcstombs_r.$(OBJEXT) \
@ -157,9 +158,10 @@ am__objects_9 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \
itoa.lo labs.lo ldiv.lo ldtoa.lo malloc.lo mblen.lo mblen_r.lo \
mbstowcs.lo mbstowcs_r.lo mbtowc.lo mbtowc_r.lo mlock.lo \
mprec.lo mstats.lo quick_exit.lo rand.lo rand_r.lo realloc.lo \
reallocf.lo sb_charsets.lo strtod.lo strtol.lo strtoul.lo \
utoa.lo wcstod.lo wcstol.lo wcstoul.lo wcstombs.lo \
wcstombs_r.lo wctomb.lo wctomb_r.lo $(am__objects_8)
reallocf.lo sb_charsets.lo strtod.lo strtodg.lo strtol.lo \
strtorx.lo strtoul.lo utoa.lo wcstod.lo wcstol.lo wcstoul.lo \
wcstombs.lo wcstombs_r.lo wctomb.lo wctomb_r.lo \
$(am__objects_8)
am__objects_10 = cxa_atexit.lo cxa_finalize.lo drand48.lo ecvtbuf.lo \
efgcvt.lo erand48.lo jrand48.lo lcong48.lo lrand48.lo \
mrand48.lo msize.lo mtrim.lo nrand48.lo rand48.lo seed48.lo \
@ -361,8 +363,9 @@ GENERAL_SOURCES = __adjust.c __atexit.c __call_atexit.c __exp10.c \
ldtoa.c malloc.c mblen.c mblen_r.c mbstowcs.c mbstowcs_r.c \
mbtowc.c mbtowc_r.c mlock.c mprec.c mstats.c quick_exit.c \
rand.c rand_r.c realloc.c reallocf.c sb_charsets.c strtod.c \
strtol.c strtoul.c utoa.c wcstod.c wcstol.c wcstoul.c \
wcstombs.c wcstombs_r.c wctomb.c wctomb_r.c $(am__append_1)
strtodg.c strtol.c strtorx.c strtoul.c utoa.c wcstod.c \
wcstol.c wcstoul.c wcstombs.c wcstombs_r.c wctomb.c wctomb_r.c \
$(am__append_1)
@NEWLIB_NANO_MALLOC_FALSE@MALIGNR = malignr
@NEWLIB_NANO_MALLOC_TRUE@MALIGNR = nano-malignr
@NEWLIB_NANO_MALLOC_FALSE@MALLOPTR = malloptr
@ -895,12 +898,24 @@ lib_a-strtod.o: strtod.c
lib_a-strtod.obj: strtod.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtod.obj `if test -f 'strtod.c'; then $(CYGPATH_W) 'strtod.c'; else $(CYGPATH_W) '$(srcdir)/strtod.c'; fi`
lib_a-strtodg.o: strtodg.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtodg.o `test -f 'strtodg.c' || echo '$(srcdir)/'`strtodg.c
lib_a-strtodg.obj: strtodg.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtodg.obj `if test -f 'strtodg.c'; then $(CYGPATH_W) 'strtodg.c'; else $(CYGPATH_W) '$(srcdir)/strtodg.c'; fi`
lib_a-strtol.o: strtol.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtol.o `test -f 'strtol.c' || echo '$(srcdir)/'`strtol.c
lib_a-strtol.obj: strtol.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtol.obj `if test -f 'strtol.c'; then $(CYGPATH_W) 'strtol.c'; else $(CYGPATH_W) '$(srcdir)/strtol.c'; fi`
lib_a-strtorx.o: strtorx.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtorx.o `test -f 'strtorx.c' || echo '$(srcdir)/'`strtorx.c
lib_a-strtorx.obj: strtorx.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtorx.obj `if test -f 'strtorx.c'; then $(CYGPATH_W) 'strtorx.c'; else $(CYGPATH_W) '$(srcdir)/strtorx.c'; fi`
lib_a-strtoul.o: strtoul.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strtoul.o `test -f 'strtoul.c' || echo '$(srcdir)/'`strtoul.c

View File

@ -70,3 +70,5 @@ enum { /* FPI.rounding values: same as FLT_ROUNDS */
};
#endif /* GDTOA_H_INCLUDED */
typedef unsigned short __UShort;

View File

@ -3280,7 +3280,7 @@ bxit:
}
#if 0 /* Broken, unusable implementation of strtold */
/*
; ASCTOQ
@ -3644,7 +3644,7 @@ aexit:
return lenldstr;
}
#endif
/* y = largest integer not greater than x
* (truncated toward minus infinity)

View File

@ -404,6 +404,11 @@ int _EXFUN(gethex,(struct _reent *p, _CONST char **sp, _CONST struct FPI *fpi,
double _EXFUN(ratio,(_Bigint *a, _Bigint *b));
__ULong _EXFUN(any_on,(_Bigint *b, int k));
void _EXFUN(copybits,(__ULong *c, int n, _Bigint *b));
#if defined (_HAVE_LONG_DOUBLE) && !defined (_LDBL_EQ_DBL)
int _EXFUN(_strtorx_r,(struct _reent *, _CONST char *, char **, int, void *));
int _EXFUN(_strtodg_r,(struct _reent *p, _CONST char *s00, char **se, struct FPI *fpi, Long *exp, __ULong *bits));
#endif /* _HAVE_LONG_DOUBLE && !_LDBL_EQ_DBL */
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) || defined(_SMALL_HEXDIG)
unsigned char _EXFUN(__hexdig_fun,(unsigned char));
#endif /* !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && !defined(_SMALL_HEXDIG) */

1136
newlib/libc/stdlib/strtodg.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -32,17 +32,49 @@ POSSIBILITY OF SUCH DAMAGE.
#include "local.h"
#ifdef _HAVE_LONG_DOUBLE
extern long double _strtold (const char *, char **);
/* On platforms where long double is as wide as double. */
#if defined (__x86_64__) || defined (__i386__)
static const int map[] = {
1, /* round to nearest */
3, /* round to zero */
2, /* round to negative infinity */
0 /* round to positive infinity */
};
int
__flt_rounds(void)
{
int x;
/* Assume that the x87 and the SSE unit agree on the rounding mode. */
__asm("fnstcw %0" : "=m" (x));
return (map[(x >> 10) & 0x03]);
}
#define FLT_ROUNDS __flt_rounds()
#else
#define FLT_ROUNDS 0
#endif
long double
_strtold_r (struct _reent *ptr, const char *__restrict s00,
char **__restrict se)
{
#ifdef _LDBL_EQ_DBL
/* On platforms where long double is as wide as double. */
return _strtod_r (ptr, s00, se);
#else
long double result;
_strtorx_r (ptr, s00, se, FLT_ROUNDS, &result);
return result;
#endif
}
long double
strtold (const char *__restrict s00, char **__restrict se)
{
#ifdef _LDBL_EQ_DBL
return strtod(s00, se);
#else
return _strtold (s00, se);
#endif
return _strtold_r (_REENT, s00, se);
}
#endif /* _HAVE_LONG_DOUBLE */

View File

@ -0,0 +1,129 @@
/****************************************************************
The author of this software is David M. Gay.
Copyright (C) 1998, 2000 by Lucent Technologies
All Rights Reserved
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 and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
****************************************************************/
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
#include <_ansi.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "mprec.h"
#include "gdtoa.h"
#include "gd_qnan.h"
#ifdef _HAVE_LONG_DOUBLE
#undef _0
#undef _1
/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */
#ifdef IEEE_MC68k
#define _0 0
#define _1 1
#define _2 2
#define _3 3
#define _4 4
#endif
#ifdef IEEE_8087
#define _0 4
#define _1 3
#define _2 2
#define _3 1
#define _4 0
#endif
void
#ifdef KR_headers
ULtox(L, bits, exp, k) __UShort *L; __ULong *bits; Long exp; int k;
#else
ULtox(__UShort *L, __ULong *bits, Long exp, int k)
#endif
{
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
L[0] = L[1] = L[2] = L[3] = L[4] = 0;
break;
case STRTOG_Denormal:
L[_0] = 0;
goto normal_bits;
case STRTOG_Normal:
case STRTOG_NaNbits:
L[_0] = exp + 0x3fff + 63;
normal_bits:
L[_4] = (__UShort)bits[0];
L[_3] = (__UShort)(bits[0] >> 16);
L[_2] = (__UShort)bits[1];
L[_1] = (__UShort)(bits[1] >> 16);
break;
case STRTOG_Infinite:
L[_0] = 0x7fff;
L[_1] = L[_2] = L[_3] = L[_4] = 0;
break;
case STRTOG_NaN:
L[0] = ldus_QNAN0;
L[1] = ldus_QNAN1;
L[2] = ldus_QNAN2;
L[3] = ldus_QNAN3;
L[4] = ldus_QNAN4;
}
if (k & STRTOG_Neg)
L[_0] |= 0x8000;
}
int
#ifdef KR_headers
_strtorx_r(p, s, sp, rounding, L) struct _reent *p; const char *s; char **sp; int rounding; void *L;
#else
_strtorx_r(struct _reent *p, const char *s, char **sp, int rounding, void *L)
#endif
{
static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
FPI *fpi, fpi1;
__ULong bits[2];
Long exp;
int k;
fpi = &fpi0;
if (rounding != FPI_Round_near) {
fpi1 = fpi0;
fpi1.rounding = rounding;
fpi = &fpi1;
}
k = _strtodg_r(p, s, sp, fpi, &exp, bits);
ULtox((__UShort*)L, bits, exp, k);
return k;
}
#endif /* _HAVE_LONG_DOUBLE */

View File

@ -1,3 +1,7 @@
2015-11-20 Corinna Vinschen <corinna@vinschen.de>
* common.din (strtold): Drop redirection to _strtold.
2015-11-18 Corinna Vinschen <corinna@vinschen.de>
* sec_acl.cc (get_posix_access): Skip merging permissions if current

View File

@ -1199,7 +1199,7 @@ strtoimax = strtoll NOSIGFE
strtok NOSIGFE
strtok_r NOSIGFE
strtol NOSIGFE
strtold = _strtold SIGFE
strtold SIGFE
strtoll NOSIGFE
strtosigno NOSIGFE
strtoul NOSIGFE