2000-12-06 Jeff Johnston <jjohnstn@redhat.com>

* libc/stdlib/Makefile.am: Added ldtoa.c to list of sources.
        * libc/stdlib/Makefile.in: Regenerated.
        * libc/stdio/floatio.h: Added suitable MAXEXP for long double.
        * libc/stdio/vfieeefp.h: Added long double bit structures.
        * libc/stdio/vfprintf.c[WANT_IO_LONG_DBL]: Added long double support.
        [WANT_IO_LONG_DBL](isinfl, isnanl): New static long double routines.
        (exponent): Changed expbuf to reasonable maximum instead of MAXEXP.
        * libc/stdio/vfscanf.c[WANT_IO_LONG_DBL]: Added long double support.
        * libc/stdlib/ldtoa.c: New file containing _ldtoa_r and
        _strtold routines used for conversions between character
        and long double.
This commit is contained in:
Jeff Johnston 2000-12-06 23:50:11 +00:00
parent 81e615de98
commit 6bdac416e9
8 changed files with 3916 additions and 26 deletions

View File

@ -1,3 +1,17 @@
2000-12-06 Jeff Johnston <jjohnstn@redhat.com>
* libc/stdlib/Makefile.am: Added ldtoa.c to list of sources.
* libc/stdlib/Makefile.in: Regenerated.
* libc/stdio/floatio.h: Added suitable MAXEXP for long double.
* libc/stdio/vfieeefp.h: Added long double bit structures.
* libc/stdio/vfprintf.c[WANT_IO_LONG_DBL]: Added long double support.
[WANT_IO_LONG_DBL](isinfl, isnanl): New static long double routines.
(exponent): Changed expbuf to reasonable maximum instead of MAXEXP.
* libc/stdio/vfscanf.c[WANT_IO_LONG_DBL]: Added long double support.
* libc/stdlib/ldtoa.c: New file containing _ldtoa_r and
_strtold routines used for conversions between character
and long double.
Wed Dec 6 12:01:00 2000 Corinna Vinschen <vinschen@cygnus.com>
* libc/include/stdlib.h: Add declarations for `mkstemp' and `mktemp'.

View File

@ -21,7 +21,12 @@
* Floating point scanf/printf (input/output) definitions.
*/
#ifdef _NO_LONGDBL
/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
#define MAXEXP 308
#else /* !_NO_LONGDBL */
/* 15-bit exponent (Intel extended floating point) is 4932 decimal digits */
#define MAXEXP 4932
#endif /* !_NO_LONGDBL */
/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
#define MAXFRACT 39

View File

@ -57,6 +57,85 @@
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
#endif
#ifdef WANT_IO_LONG_DBL
/* If we are going to examine or modify specific bits in a long double using
the lword0 or lwordx macros, then we must wrap the long double inside
a union. This is necessary to avoid undefined behavior according to
the ANSI C spec. */
#ifdef IEEE_8087
#if LDBL_MANT_DIG == 24
struct ldieee
{
unsigned manh:23;
unsigned exp:8;
unsigned sign:1;
}
#elif LDBL_MANT_DIG == 53
struct ldieee
{
unsigned manl:20;
unsigned manh:32;
unsigned exp:11;
unsigned sign:1;
}
#elif LDBL_MANT_DIG == 64
struct ldieee
{
unsigned manl:32;
unsigned manh:32;
unsigned exp:15;
unsigned sign:1;
};
#elif LDBL_MANT_DIG > 64
struct ldieee
{
unsigned manl3:16;
unsigned manl2:32;
unsigned manl:32;
unsigned manh:32;
unsigned exp:15;
unsigned sign:1;
};
#endif /* LDBL_MANT_DIG */
#else /* !IEEE_8087 */
#if LDBL_MANT_DIG == 24
struct ldieee
{
unsigned sign:1;
unsigned exp:8;
unsigned manh:23;
}
#elif LDBL_MANT_DIG == 53
struct ldieee
{
unsigned sign:1;
unsigned exp:11;
unsigned manh:32;
unsigned manl:20;
}
#elif LDBL_MANT_DIG == 64
struct ldieee
{
unsigned sign:1;
unsigned exp:15;
unsigned manh:32;
unsigned manl:32;
}
#elif LDBL_MANT_DIG > 64
struct ldieee
{
unsigned sign:1;
unsigned exp:15;
unsigned manh:32;
unsigned manl:32;
unsigned manl2:32;
unsigned manl3;16;
};
#endif /* LDBL_MANT_DIG */
#endif /* !IEEE_8087 */
#endif /* WANT_IO_LONG_DBL */
/* If we are going to examine or modify specific bits in a double using
the word0 and/or word1 macros, then we must wrap the double inside
a union. This is necessary to avoid undefined behavior according to

View File

@ -174,6 +174,14 @@ static char *rcsid = "$Id$";
#include "fvwrite.h"
#include "vfieeefp.h"
/* Currently a test is made to see if long double processing is warranted.
This could be changed in the future should the _ldtoa_r code be
preferred over _dtoa_r. */
#define _NO_LONGDBL
#if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG)
#undef _NO_LONGDBL
#endif
/*
* Flush out all the vectors defined by the given uio,
* then reset it so that it can be reused.
@ -240,7 +248,14 @@ __sbprintf(fp, fmt, ap)
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
#define DEFPREC 6
#ifdef _NO_LONGDBL
static char *cvt _PARAMS((struct _reent *, double, int, int, char *, int *, int, int *));
#else
static char *cvt _PARAMS((struct _reent *, _LONG_DOUBLE, int, int, char *, int *, int, int *));
static int isinfl _PARAMS((_LONG_DOUBLE *));
static int isnanl _PARAMS((_LONG_DOUBLE *));
#endif
static int exponent _PARAMS((char *, int, int));
#else /* no FLOATING_POINT */
@ -263,7 +278,7 @@ static int exponent _PARAMS((char *, int, int));
#define ALT 0x001 /* alternate form */
#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
#define LADJUST 0x004 /* left adjustment */
#define LONGDBL 0x008 /* long double; unimplemented */
#define LONGDBL 0x008 /* long double */
#define LONGINT 0x010 /* long integer */
#define QUADINT 0x020 /* quad integer */
#define SHORTINT 0x040 /* short integer */
@ -301,9 +316,13 @@ _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
#ifdef FLOATING_POINT
char *decimal_point = localeconv()->decimal_point;
char softsign; /* temporary negative sign for floats */
double _double; /* double precision arguments %[eEfgG] */
#ifdef _NO_LONGDBL
double _fpvalue; /* floating point arguments %[eEfgG] */
#else
_LONG_DOUBLE _fpvalue; /* floating point arguments %[eEfgG] */
#endif
int expt; /* integer value of exponent */
int expsize; /* character count for expstr */
int expsize = 0; /* character count for expstr */
int ndig; /* actual number of digits returned by cvt */
char expstr[7]; /* buffer for exponent string */
#endif
@ -322,7 +341,7 @@ _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
int realsz; /* field size expanded by dprec */
int size; /* size of converted field or string */
char *xdigs; /* digits for [xX] conversion */
char *xdigs = NULL; /* digits for [xX] conversion */
#define NIOV 8
struct __suio uio; /* output information: summary */
struct __siov iov[NIOV];/* ... and individual io vectors */
@ -553,29 +572,55 @@ reswitch: switch (ch) {
prec = 1;
}
#ifdef _NO_LONGDBL
if (flags & LONGDBL) {
_double = (double) va_arg(ap, long double);
_fpvalue = (double) va_arg(ap, _LONG_DOUBLE);
} else {
_double = va_arg(ap, double);
_fpvalue = va_arg(ap, double);
}
/* do this before tricky precision changes */
if (isinf(_double)) {
if (_double < 0)
if (isinf(_fpvalue)) {
if (_fpvalue < 0)
sign = '-';
cp = "Inf";
size = 3;
break;
}
if (isnan(_double)) {
if (isnan(_fpvalue)) {
cp = "NaN";
size = 3;
break;
}
#else /* !_NO_LONGDBL */
if (flags & LONGDBL) {
_fpvalue = va_arg(ap, _LONG_DOUBLE);
} else {
_fpvalue = (_LONG_DOUBLE)va_arg(ap, double);
}
/* do this before tricky precision changes */
if (isinfl(&_fpvalue)) {
if (_fpvalue < 0)
sign = '-';
cp = "Inf";
size = 3;
break;
}
if (isnanl(&_fpvalue)) {
cp = "NaN";
size = 3;
break;
}
#endif /* !_NO_LONGDBL */
flags |= FPT;
cp = cvt(data, _double, prec, flags, &softsign,
cp = cvt(data, _fpvalue, prec, flags, &softsign,
&expt, ch, &ndig);
if (ch == 'g' || ch == 'G') {
if (expt <= -4 || expt > prec)
ch = (ch == 'g') ? 'e' : 'E';
@ -796,7 +841,7 @@ number: if ((dprec = prec) >= 0)
PRINT(cp, size);
} else { /* glue together f_p fragments */
if (ch >= 'f') { /* 'f' or 'g' */
if (_double == 0) {
if (_fpvalue == 0) {
/* kludge for __dtoa irregularity */
PRINT("0", 1);
if (expt < ndig || (flags & ALT) != 0) {
@ -826,7 +871,7 @@ number: if ((dprec = prec) >= 0)
ox[0] = *cp++;
ox[1] = '.';
PRINT(ox, 2);
if (_double) {
if (_fpvalue) {
PRINT(cp, ndig-1);
} else /* 0.[0..] */
/* __dtoa irregularity */
@ -857,19 +902,60 @@ error:
#ifdef FLOATING_POINT
#ifdef _NO_LONGDBL
extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
int, int *, int *, char **));
#else
extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
int, int *, int *, char **));
#undef word0
#define word0(x) ldword0(x)
static int
isinfl (value)
_LONG_DOUBLE *value;
{
struct ldieee *ldptr;
ldptr = (struct ldieee *)value;
if (ldptr->exp == 0x7fff && !(ldptr->manh & 0x7fffffff) && !ldptr->manl)
return 1;
return 0;
}
static int
isnanl (value)
_LONG_DOUBLE *value;
{
struct ldieee *ldptr;
ldptr = (struct ldieee *)value;
if (ldptr->exp == 0x7fff && ((ldptr->manh & 0x7fffffff) || ldptr->manl))
return 1;
return 0;
}
#endif
static char *
cvt(data, value, ndigits, flags, sign, decpt, ch, length)
struct _reent *data;
#ifdef _NO_LONGDBL
double value;
#else
_LONG_DOUBLE value;
#endif
int ndigits, flags, *decpt, ch, *length;
char *sign;
{
int mode, dsgn;
char *digits, *bp, *rve;
#ifdef _NO_LONGDBL
union double_union tmp;
#else
struct ldieee *ldptr;
#endif
if (ch == 'f') {
mode = 3; /* ndigits after the decimal point */
@ -884,13 +970,27 @@ cvt(data, value, ndigits, flags, sign, decpt, ch, length)
mode = 2; /* ndigits significant digits */
}
#ifdef _NO_LONGDBL
tmp.d = value;
if (word0(tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
value = -value;
*sign = '-';
} else
*sign = '\000';
digits = _dtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);
#else /* !_NO_LONGDBL */
ldptr = (struct ldieee *)&value;
if (ldptr->sign) { /* this will check for < 0 and -0.0 */
value = -value;
*sign = '-';
} else
*sign = '\000';
digits = _ldtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);
#endif /* !_NO_LONGDBL */
if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
bp = digits + ndigits;
if (ch == 'f') {
@ -913,7 +1013,7 @@ exponent(p0, exp, fmtch)
int exp, fmtch;
{
register char *p, *t;
char expbuf[MAXEXP];
char expbuf[40];
p = p0;
*p++ = fmtch;
@ -923,13 +1023,13 @@ exponent(p0, exp, fmtch)
}
else
*p++ = '+';
t = expbuf + MAXEXP;
t = expbuf + 40;
if (exp > 9) {
do {
*--t = to_char(exp % 10);
} while ((exp /= 10) > 9);
*--t = to_char(exp);
for (; t < expbuf + MAXEXP; *p++ = *t++);
for (; t < expbuf + 40; *p++ = *t++);
}
else {
*p++ = '0';

View File

@ -34,6 +34,17 @@
#endif
#ifdef FLOATING_POINT
#include <float.h>
/* Currently a test is made to see if long double processing is warranted.
This could be changed in the future should the _ldtoa_r code be
preferred over _dtoa_r. */
#define _NO_LONGDBL
#if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG)
#undef _NO_LONGDBL
extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr));
#endif
#include "floatio.h"
#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */
/* An upper bound for how long a long prints in decimal. 4 / 13 approximates
@ -48,7 +59,7 @@
*/
#define LONG 0x01 /* l: long or double */
#define LONGDBL 0x02 /* L: long double; unimplemented */
#define LONGDBL 0x02 /* L: long double */
#define SHORT 0x04 /* h: short */
#define SUPPRESS 0x08 /* suppress assignment */
#define POINTER 0x10 /* weird %p pointer (`fake hex') */
@ -372,7 +383,7 @@ __svfscanf (fp, fmt0, ap)
for (;;)
{
if ((n = fp->_r) < width)
if ((n = fp->_r) < (int)width)
{
sum += n;
width -= n;
@ -683,8 +694,9 @@ __svfscanf (fp, fmt0, ap)
However, ANSI / ISO C makes no such stipulation; we have to get
exact results even when there is an unreasonable amount of
leading zeroes. */
long leading_zeroes, zeroes, exp_adjust;
char *exp_start;
long leading_zeroes = 0;
long zeroes, exp_adjust;
char *exp_start = NULL;
#ifdef hardway
if (width == 0 || width > sizeof (buf) - 1)
width = sizeof (buf) - 1;
@ -808,7 +820,11 @@ __svfscanf (fp, fmt0, ap)
}
if ((flags & SUPPRESS) == 0)
{
#ifdef _NO_LONGDBL
double res;
#else /* !_NO_LONG_DBL */
long double res;
#endif /* !_NO_LONG_DBL */
long new_exp;
*p = 0;
@ -829,7 +845,11 @@ __svfscanf (fp, fmt0, ap)
exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1;
sprintf (exp_start, "e%ld", new_exp);
}
#ifdef _NO_LONG_DBL
res = atof (buf);
#else /* !_NO_LONG_DBL */
res = _strtold (buf, NULL);
#endif /* !_NO_LONG_DBL */
if (flags & LONG)
{
dp = va_arg (ap, double *);

View File

@ -34,6 +34,7 @@ lib_a_SOURCES = \
getopt.c \
labs.c \
ldiv.c \
ldtoa.c \
malign.c \
malloc.c \
mblen.c \
@ -157,6 +158,7 @@ doc: $(CHEWOUT_FILES)
CLEANFILES = $(CHEWOUT_FILES) *.ref
dtoa.o: dtoa.c mprec.h
ldtoa.o: ldtoa.c mprec.h
ecvtbuf.o: ecvtbuf.c mprec.h
mbtowc_r.o: mbtowc_r.c mbctype.h
$(COMPILE) -c -fshort-enums $(srcdir)/mbtowc_r.c -o $@

View File

@ -116,6 +116,7 @@ lib_a_SOURCES = \
getopt.c \
labs.c \
ldiv.c \
ldtoa.c \
malign.c \
malloc.c \
mblen.c \
@ -212,11 +213,12 @@ malloptr.o
lib_a_OBJECTS = __adjust.o __exp10.o __ten_mu.o abort.o abs.o assert.o \
atexit.o atof.o atoff.o atoi.o atol.o bsearch.o calloc.o div.o dtoa.o \
dtoastub.o ecvtbuf.o efgcvt.o environ.o envlock.o eprintf.o exit.o \
getenv.o getenv_r.o getopt.o labs.o ldiv.o malign.o malloc.o mblen.o \
mblen_r.o mbstowcs.o mbstowcs_r.o mbtowc.o mbtowc_r.o mlock.o mprec.o \
msize.o mstats.o mtrim.o putenv.o putenv_r.o qsort.o rand.o rand_r.o \
realloc.o setenv.o setenv_r.o strdup.o strdup_r.o strtod.o strtol.o \
strtoul.o system.o valloc.o wcstombs.o wcstombs_r.o wctomb.o wctomb_r.o
getenv.o getenv_r.o getopt.o labs.o ldiv.o ldtoa.o malign.o malloc.o \
mblen.o mblen_r.o mbstowcs.o mbstowcs_r.o mbtowc.o mbtowc_r.o mlock.o \
mprec.o msize.o mstats.o mtrim.o putenv.o putenv_r.o qsort.o rand.o \
rand_r.o realloc.o setenv.o setenv_r.o strdup.o strdup_r.o strtod.o \
strtol.o strtoul.o system.o valloc.o wcstombs.o wcstombs_r.o wctomb.o \
wctomb_r.o
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@ -226,7 +228,7 @@ DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
TAR = gtar
GZIP_ENV = --best
SOURCES = $(lib_a_SOURCES)
OBJECTS = $(lib_a_OBJECTS)
@ -312,7 +314,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
if test -f $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@ -436,6 +438,7 @@ doc: $(CHEWOUT_FILES)
cat $(srcdir)/stdlib.tex >> $(TARGETDOC)
dtoa.o: dtoa.c mprec.h
ldtoa.o: ldtoa.c mprec.h
ecvtbuf.o: ecvtbuf.c mprec.h
mbtowc_r.o: mbtowc_r.c mbctype.h
$(COMPILE) -c -fshort-enums $(srcdir)/mbtowc_r.c -o $@

3667
newlib/libc/stdlib/ldtoa.c Normal file

File diff suppressed because it is too large Load Diff