From 91ea72b7d26907ddbfc5a155752ec506d926c804 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 10 Mar 1999 16:08:03 +0000 Subject: Update. 1999-03-09 Andreas Schwab * stdio-common/printf_fphex.c: Move to ... * sysdeps/generic/printf_fphex.c: ... here. Fix exponent of extended precision number. * sysdeps/m68k/printf_fphex.c: New file. 1999-03-09 Andreas Schwab * manual/stdio.texi: Fix typos. --- ChangeLog | 11 + INSTALL | 31 +-- README | 4 +- manual/install.texi | 13 +- manual/stdio.texi | 6 +- stdio-common/printf_fphex.c | 458 ---------------------------------------- sysdeps/generic/printf_fphex.c | 464 +++++++++++++++++++++++++++++++++++++++++ sysdeps/m68k/printf_fphex.c | 2 + 8 files changed, 505 insertions(+), 484 deletions(-) delete mode 100644 stdio-common/printf_fphex.c create mode 100644 sysdeps/generic/printf_fphex.c create mode 100644 sysdeps/m68k/printf_fphex.c diff --git a/ChangeLog b/ChangeLog index d725cf7f23..94d260dfec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +1999-03-09 Andreas Schwab + + * stdio-common/printf_fphex.c: Move to ... + * sysdeps/generic/printf_fphex.c: ... here. Fix exponent of + extended precision number. + * sysdeps/m68k/printf_fphex.c: New file. + +1999-03-09 Andreas Schwab + + * manual/stdio.texi: Fix typos. + 1999-03-09 Ulrich Drepper * version.h (VERSION): Bump to 2.1.1. diff --git a/INSTALL b/INSTALL index f8ebfa81d5..255ba289dc 100644 --- a/INSTALL +++ b/INSTALL @@ -197,11 +197,11 @@ from underneath. If you are upgrading from a previous installation of glibc 2.0 or 2.1, `make install' will do the entire job. If you're upgrading from Linux libc5 or some other C library, you need to rename the old -`/usr/include' directory out of the way first, or you will end up with -a mixture of header files from both libraries, and you won't be able to -compile anything. You may also need to reconfigure GCC to work with -the new library. The easiest way to do that is to figure out the -compiler switches to make it work again +`/usr/include' directory out of the way before running `make install', +or you will end up with a mixture of header files from both libraries, +and you won't be able to compile anything. You may also need to +reconfigure GCC to work with the new library. The easiest way to do +that is to figure out the compiler switches to make it work again (`-Wl,-dynamic-linker=/lib/ld-linux.so.2' should work on Linux systems) and use them to recompile gcc. You can also edit the specs file (`/usr/lib/gcc-lib/TARGET/VERSION/specs'), but that is a bit of a black @@ -217,8 +217,8 @@ environment or preparing a binary distribution. may not want to run. `nscd' caches name service lookups; it can dramatically improve performance with NIS+, and may help with DNS as well. `utmpd' allows programs that use the old format for the `utmp' -file to coexist with new programs. For more information see the files -`nscd/README' and `login/README.utmpd'. +file to coexist with new programs. For more information see the file +`login/README.utmpd'. One auxiliary program, `/usr/libexec/pt_chown', is installed setuid `root'. This program is invoked by the `grantpt' function; it sets the @@ -246,16 +246,17 @@ build the GNU C library: bugs which only show up in big projects like GNU `libc'. Version 3.76.1 seems OK but some people have reported problems. - * EGCS 1.1.1, 1.1 or 1.0.3 + * EGCS 1.1.1, 1.1 or 1.0.3, or GCC 2.8.1 The GNU C library can only be compiled with the GNU C compiler family. As of the 2.1 release, EGCS 1.0.3 or higher is required. - GCC 2.8.1 cannot be used due to an incompatible implementation of - some internal compiler support routines; see the FAQ for details. - GCC 2.7.x is simply too buggy. You can use whatever compiler you - like to compile programs that use GNU libc, but be aware that both - GCC 2.7 and 2.8 have bugs in their floating-point support that may - be triggered by the math library. + GCC 2.8.1 can also be used (but see the FAQ for reasons why you + might not want to). Earlier versions simply are too buggy. + + You can use whatever compiler you like to compile programs that + use GNU libc, but be aware that both GCC 2.7 and 2.8 have bugs in + their floating-point support that may be triggered by the math + library. On Alpha machines you need at least EGCS 1.1.1. Earlier versions don't work reliably. @@ -279,7 +280,7 @@ build the GNU C library: For PPC you might need some patches even on top of the last binutils version. See the FAQ. - * GNU `texinfo' 3.11 + * GNU `texinfo' 3.12f To correctly translate and install the Texinfo documentation you need this version of the `texinfo' package. Earlier versions do diff --git a/README b/README index 72adb5eceb..fdbdff8ac6 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This directory contains the version 2.1 release of the GNU C Library. +This directory contains the version 2.1.1 release of the GNU C Library. Many bugs have been fixed since the last release. Some bugs surely remain. @@ -53,7 +53,7 @@ provides the Unix `crypt' function, plus some other entry points. Because of the United States export restriction on DES implementations, we are distributing this code separately from the rest of the C library. There is an extra distribution tar file just -for crypt; it is called `glibc-crypt-2.1.tar.gz'. You can just +for crypt; it is called `glibc-crypt-2.1.1.tar.gz'. You can just unpack the crypt distribution along with the rest of the C library and build; you can also build the library without getting crypt. Users outside the USA can get the crypt distribution via anonymous FTP from diff --git a/manual/install.texi b/manual/install.texi index 5ac0e785c3..013c1a34e4 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -276,14 +276,15 @@ have bugs which only show up in big projects like GNU @code{libc}. Version 3.76.1 seems OK but some people have reported problems. @item -EGCS 1.1.1, 1.1 or 1.0.3 +EGCS 1.1.1, 1.1 or 1.0.3, or GCC 2.8.1 The GNU C library can only be compiled with the GNU C compiler family. -As of the 2.1 release, EGCS 1.0.3 or higher is required. GCC 2.8.1 cannot -be used due to an incompatible implementation of some internal compiler -support routines; see the FAQ for details. GCC 2.7.x is simply too -buggy. You can use whatever compiler you like to compile programs that -use GNU libc, but be aware that both GCC 2.7 and 2.8 have bugs in their +As of the 2.1 release, EGCS 1.0.3 or higher is required. GCC 2.8.1 can +also be used (but see the FAQ for reasons why you might not want to). +Earlier versions simply are too buggy. + +You can use whatever compiler you like to compile programs that use GNU +libc, but be aware that both GCC 2.7 and 2.8 have bugs in their floating-point support that may be triggered by the math library. On Alpha machines you need at least EGCS 1.1.1. Earlier versions don't diff --git a/manual/stdio.texi b/manual/stdio.texi index 1b9679f3bb..3449a51d2b 100644 --- a/manual/stdio.texi +++ b/manual/stdio.texi @@ -1302,14 +1302,14 @@ exchanged as texts between different programs and/or machines. The numbers are represented is the form @w{[@code{-}]@code{0x}@var{h}@code{.}@var{hhh}@code{p}[@code{+}|@code{-}]@var{dd}}. At the left of the decimal-point character exactly one digit is print. -This character is only @code{0} is the number is denormalized. +This character is only @code{0} if the number is denormalized. Otherwise the value is unspecified; it is implemention dependent how many bits are used. The number of hexadecimal digits on the right side of the decimal-point character is equal to the precision. If the precision is zero it is determined to be large enough to provide an exact representation of the number (or it is large enough to distinguish two adjacent values if the @code{FLT_RADIX} is not a power of 2, -@pxref{Floating Point Parameters}) For the @samp{%a} conversion +@pxref{Floating Point Parameters}). For the @samp{%a} conversion lower-case characters are used to represent the hexadecimal number and the prefix and exponent sign are printed as @code{0x} and @code{p} respectively. Otherwise upper-case characters are used and @code{0X} @@ -1364,7 +1364,7 @@ is explicitly @code{0}, this suppresses the decimal point character entirely. For the @samp{%g} and @samp{%G} conversions, the precision specifies how many significant digits to print. Significant digits are the first digit before the decimal point, and all the digits after it. -If the precision @code{0} or not specified for @samp{%g} or @samp{%G}, +If the precision is @code{0} or not specified for @samp{%g} or @samp{%G}, it is treated like a value of @code{1}. If the value being printed cannot be expressed accurately in the specified number of digits, the value is rounded to the nearest number that fits. diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c deleted file mode 100644 index 660435f6b3..0000000000 --- a/stdio-common/printf_fphex.c +++ /dev/null @@ -1,458 +0,0 @@ -/* Print floating point number in hexadecimal notation according to - ISO C 9X. - Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 1997. - - 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; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "_itoa.h" -#include - -/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */ -#include - -/* This defines make it possible to use the same code for GNU C library and - the GNU I/O library. */ -#ifdef USE_IN_LIBIO -# include -# define PUT(f, s, n) _IO_sputn (f, s, n) -# define PAD(f, c, n) _IO_padn (f, c, n) -/* We use this file GNU C library and GNU I/O library. So make - names equal. */ -# undef putc -# define putc(c, f) _IO_putc_unlocked (c, f) -# define size_t _IO_size_t -# define FILE _IO_FILE -#else /* ! USE_IN_LIBIO */ -# define PUT(f, s, n) fwrite (s, 1, n, f) -# define PAD(f, c, n) __printf_pad (f, c, n) -ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ -#endif /* USE_IN_LIBIO */ - -/* Macros for doing the actual output. */ - -#define outchar(ch) \ - do \ - { \ - register const int outc = (ch); \ - if (putc (outc, fp) == EOF) \ - return -1; \ - ++done; \ - } while (0) - -#define PRINT(ptr, len) \ - do \ - { \ - int outlen = (len); \ - const char *cp = (ptr); \ - while (outlen-- > 0) \ - outchar (*cp++); \ - } while (0) - -#define PADN(ch, len) \ - do \ - { \ - if (PAD (fp, ch, len) != len) \ - return -1; \ - done += len; \ - } \ - while (0) - -#ifndef MIN -# define MIN(a,b) ((a)<(b)?(a):(b)) -#endif - - -int -__printf_fphex (FILE *fp, - const struct printf_info *info, - const void *const *args) -{ - /* The floating-point value to output. */ - union - { - union ieee754_double dbl; - union ieee854_long_double ldbl; - } - fpnum; - - /* Locale-dependent representation of decimal point. */ - wchar_t decimal; - - /* "NaN" or "Inf" for the special cases. */ - const char *special = NULL; - - /* Buffer for the generated number string for the mantissa. The - maximal size for the mantissa is 64 bits. */ - char numbuf[16]; - char *numstr; - char *numend; - int negative; - - /* The maximal exponent of two in decimal notation has 5 digits. */ - char expbuf[5]; - char *expstr; - int expnegative; - int exponent; - - /* Non-zero is mantissa is zero. */ - int zero_mantissa; - - /* The leading digit before the decimal point. */ - char leading; - - /* Precision. */ - int precision = info->prec; - - /* Width. */ - int width = info->width; - - /* Number of characters written. */ - int done = 0; - - - /* Figure out the decimal point character. */ - if (info->extra == 0) - { - mbstate_t state; - - memset (&state, '\0', sizeof (state)); - if (__mbrtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT), - strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT)), - &state) <= 0) - decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - } - else - { - mbstate_t state; - - memset (&state, '\0', sizeof (state)); - if (__mbrtowc (&decimal, _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT), - strlen (_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT)), - &state) <= 0) - decimal = (wchar_t) *_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); - } - /* Give default value. */ - if (decimal == L'\0') - decimal = L'.'; - - - /* Fetch the argument value. */ -#ifndef __NO_LONG_DOUBLE_MATH - if (info->is_long_double && sizeof (long double) > sizeof (double)) - { - fpnum.ldbl.d = *(const long double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (__isnanl (fpnum.ldbl.d)) - { - special = isupper (info->spec) ? "NAN" : "nan"; - negative = 0; - } - else - { - if (__isinfl (fpnum.ldbl.d)) - special = isupper (info->spec) ? "INF" : "inf"; - - negative = signbit (fpnum.ldbl.d); - } - } - else -#endif /* no long double */ - { - fpnum.dbl.d = *(const double *) args[0]; - - /* Check for special values: not a number or infinity. */ - if (__isnan (fpnum.dbl.d)) - { - special = isupper (info->spec) ? "NAN" : "nan"; - negative = 0; - } - else - { - if (__isinf (fpnum.dbl.d)) - special = isupper (info->spec) ? "INF" : "inf"; - - negative = signbit (fpnum.dbl.d); - } - } - - if (special) - { - int width = info->width; - - if (negative || info->showsign || info->space) - --width; - width -= 3; - - if (!info->left && width > 0) - PADN (' ', width); - - if (negative) - outchar ('-'); - else if (info->showsign) - outchar ('+'); - else if (info->space) - outchar (' '); - - PRINT (special, 3); - - if (info->left && width > 0) - PADN (' ', width); - - return done; - } - - /* We are handling here only 64 and 80 bit IEEE foating point - numbers. */ - if (info->is_long_double == 0 || sizeof (double) == sizeof (long double)) - { - /* We have 52 bits of mantissa plus one implicit digit. Since - 52 bits are representable without rest using hexadecimal - digits we use only the implicit digits for the number before - the decimal point. */ - unsigned long long int num; - - num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32 - | fpnum.dbl.ieee.mantissa1); - - zero_mantissa = num == 0; - - if (sizeof (unsigned long int) > 6) - numstr = _itoa_word (num, numbuf + sizeof numbuf, 16, - info->spec == 'A'); - else - numstr = _itoa (num, numbuf + sizeof numbuf, 16, - info->spec == 'A'); - - /* Fill with zeroes. */ - while (numstr > numbuf + (sizeof numbuf - 52 / 4)) - *--numstr = '0'; - - leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1'; - - exponent = fpnum.dbl.ieee.exponent; - - if (exponent == 0) - { - if (zero_mantissa) - expnegative = 0; - else - { - /* This is a denormalized number. */ - expnegative = 1; - exponent = -(1 - IEEE754_DOUBLE_BIAS); - } - } - else if (exponent >= IEEE754_DOUBLE_BIAS) - { - expnegative = 0; - exponent -= IEEE754_DOUBLE_BIAS; - } - else - { - expnegative = 1; - exponent = -(exponent - IEEE754_DOUBLE_BIAS); - } - } - else - { - /* The "strange" 80 bit format on ix86 and m68k has an explicit - leading digit in the 64 bit mantissa. */ - unsigned long long int num; - - assert (sizeof (long double) == 12); - - num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 - | fpnum.ldbl.ieee.mantissa1); - - zero_mantissa = num == 0; - - if (sizeof (unsigned long int) > 6) - numstr = _itoa_word (num, numbuf + sizeof numbuf, 16, - info->spec == 'A'); - else - numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A'); - - /* Fill with zeroes. */ - while (numstr > numbuf + (sizeof numbuf - 64 / 4)) - *--numstr = '0'; - - /* We use a full nibble for the leading digit. */ - leading = *numstr++; - - /* We have 3 bits from the mantissa in the leading nibble. - Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */ - exponent = fpnum.ldbl.ieee.exponent; - - if (exponent == 0) - { - if (zero_mantissa) - expnegative = 0; - else - { - /* This is a denormalized number. */ - expnegative = 1; - exponent = -(1 - (IEEE854_LONG_DOUBLE_BIAS + 3)); - } - } - else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3) - { - expnegative = 0; - exponent -= IEEE854_LONG_DOUBLE_BIAS + 2; - } - else - { - expnegative = 1; - exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3)); - } - } - - /* Look for trailing zeroes. */ - if (! zero_mantissa) - { - numend = numbuf + sizeof numbuf; - while (numend[-1] == '0') - --numend; - - if (precision == -1) - precision = numend - numstr; - else if (precision < numend - numstr - && (numstr[precision] > '8' - || (('A' < '0' || 'a' < '0') - && numstr[precision] < '0') - || (numstr[precision] == '8' - && (precision + 1 < numend - numstr - /* Round to even. */ - || (precision > 0 - && ((numstr[precision - 1] & 1) - ^ (isdigit (numstr[precision - 1]) == 0))) - || (precision == 0 - && ((leading & 1) - ^ (isdigit (leading) == 0))))))) - { - /* Round up. */ - int cnt = precision; - while (--cnt >= 0) - { - char ch = numstr[cnt]; - /* We assume that the digits and the letters are ordered - like in ASCII. This is true for the rest of GNU, too. */ - if (ch == '9') - { - numstr[cnt] = info->spec; /* This is tricky, - think about it! */ - break; - } - else if (tolower (ch) < 'f') - { - ++numstr[cnt]; - break; - } - else - numstr[cnt] = '0'; - } - if (cnt < 0) - { - /* The mantissa so far was fff...f Now increment the - leading digit. Here it is again possible that we - get an overflow. */ - if (leading == '9') - leading = info->spec; - else if (tolower (leading) < 'f') - ++leading; - else - { - leading = 1; - if (expnegative) - { - exponent += 4; - if (exponent >= 0) - expnegative = 0; - } - else - exponent += 4; - } - } - } - } - else - numend = numstr; - - /* Now we can compute the exponent string. */ - expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0); - - /* Now we have all information to compute the size. */ - width -= ((negative || info->showsign || info->space) - /* Sign. */ - + 2 + 1 + 1 + precision + 1 + 1 - /* 0x h . hhh P ExpoSign. */ - + ((expbuf + sizeof expbuf) - expstr)); - /* Exponent. */ - - /* A special case when the mantissa or the precision is zero and the `#' - is not given. In this case we must not print the decimal point. */ - if ((zero_mantissa || precision == 0) && !info->alt) - ++width; /* This nihilates the +1 for the decimal-point - character in the following equation. */ - - if (!info->left && width > 0) - PADN (' ', width); - - if (negative) - outchar ('-'); - else if (info->showsign) - outchar ('+'); - else if (info->space) - outchar (' '); - - outchar ('0'); - outchar (info->spec == 'A' ? 'X' : 'x'); - outchar (leading); - - if ((!zero_mantissa && precision > 0) || info->alt) - outchar (decimal); - - if (!zero_mantissa && precision > 0) - { - PRINT (numstr, MIN (numend - numstr, precision)); - if (precision > numend - numstr) - PADN ('0', precision - (numend - numstr)); - } - - if (info->left && info->pad == '0' && width > 0) - PADN ('0', width); - - outchar (info->spec == 'A' ? 'P' : 'p'); - - outchar (expnegative ? '-' : '+'); - - PRINT (expstr, (expbuf + sizeof expbuf) - expstr); - - if (info->left && info->pad != '0' && width > 0) - PADN (info->pad, width); - - return done; -} diff --git a/sysdeps/generic/printf_fphex.c b/sysdeps/generic/printf_fphex.c new file mode 100644 index 0000000000..00dd8eed1d --- /dev/null +++ b/sysdeps/generic/printf_fphex.c @@ -0,0 +1,464 @@ +/* Print floating point number in hexadecimal notation according to + ISO C 9X. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + 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; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "_itoa.h" +#include + +/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */ +#include + +/* This defines make it possible to use the same code for GNU C library and + the GNU I/O library. */ +#ifdef USE_IN_LIBIO +# include +# define PUT(f, s, n) _IO_sputn (f, s, n) +# define PAD(f, c, n) _IO_padn (f, c, n) +/* We use this file GNU C library and GNU I/O library. So make + names equal. */ +# undef putc +# define putc(c, f) _IO_putc_unlocked (c, f) +# define size_t _IO_size_t +# define FILE _IO_FILE +#else /* ! USE_IN_LIBIO */ +# define PUT(f, s, n) fwrite (s, 1, n, f) +# define PAD(f, c, n) __printf_pad (f, c, n) +ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */ +#endif /* USE_IN_LIBIO */ + +/* Macros for doing the actual output. */ + +#define outchar(ch) \ + do \ + { \ + register const int outc = (ch); \ + if (putc (outc, fp) == EOF) \ + return -1; \ + ++done; \ + } while (0) + +#define PRINT(ptr, len) \ + do \ + { \ + int outlen = (len); \ + const char *cp = (ptr); \ + while (outlen-- > 0) \ + outchar (*cp++); \ + } while (0) + +#define PADN(ch, len) \ + do \ + { \ + if (PAD (fp, ch, len) != len) \ + return -1; \ + done += len; \ + } \ + while (0) + +#ifndef MIN +# define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + + +int +__printf_fphex (FILE *fp, + const struct printf_info *info, + const void *const *args) +{ + /* The floating-point value to output. */ + union + { + union ieee754_double dbl; + union ieee854_long_double ldbl; + } + fpnum; + + /* Locale-dependent representation of decimal point. */ + wchar_t decimal; + + /* "NaN" or "Inf" for the special cases. */ + const char *special = NULL; + + /* Buffer for the generated number string for the mantissa. The + maximal size for the mantissa is 64 bits. */ + char numbuf[16]; + char *numstr; + char *numend; + int negative; + + /* The maximal exponent of two in decimal notation has 5 digits. */ + char expbuf[5]; + char *expstr; + int expnegative; + int exponent; + + /* Non-zero is mantissa is zero. */ + int zero_mantissa; + + /* The leading digit before the decimal point. */ + char leading; + + /* Precision. */ + int precision = info->prec; + + /* Width. */ + int width = info->width; + + /* Number of characters written. */ + int done = 0; + + + /* Figure out the decimal point character. */ + if (info->extra == 0) + { + mbstate_t state; + + memset (&state, '\0', sizeof (state)); + if (__mbrtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT), + strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT)), + &state) <= 0) + decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + } + else + { + mbstate_t state; + + memset (&state, '\0', sizeof (state)); + if (__mbrtowc (&decimal, _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT), + strlen (_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT)), + &state) <= 0) + decimal = (wchar_t) *_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); + } + /* Give default value. */ + if (decimal == L'\0') + decimal = L'.'; + + + /* Fetch the argument value. */ +#ifndef __NO_LONG_DOUBLE_MATH + if (info->is_long_double && sizeof (long double) > sizeof (double)) + { + fpnum.ldbl.d = *(const long double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnanl (fpnum.ldbl.d)) + { + special = isupper (info->spec) ? "NAN" : "nan"; + negative = 0; + } + else + { + if (__isinfl (fpnum.ldbl.d)) + special = isupper (info->spec) ? "INF" : "inf"; + + negative = signbit (fpnum.ldbl.d); + } + } + else +#endif /* no long double */ + { + fpnum.dbl.d = *(const double *) args[0]; + + /* Check for special values: not a number or infinity. */ + if (__isnan (fpnum.dbl.d)) + { + special = isupper (info->spec) ? "NAN" : "nan"; + negative = 0; + } + else + { + if (__isinf (fpnum.dbl.d)) + special = isupper (info->spec) ? "INF" : "inf"; + + negative = signbit (fpnum.dbl.d); + } + } + + if (special) + { + int width = info->width; + + if (negative || info->showsign || info->space) + --width; + width -= 3; + + if (!info->left && width > 0) + PADN (' ', width); + + if (negative) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + PRINT (special, 3); + + if (info->left && width > 0) + PADN (' ', width); + + return done; + } + + /* We are handling here only 64 and 80 bit IEEE foating point + numbers. */ + if (info->is_long_double == 0 || sizeof (double) == sizeof (long double)) + { + /* We have 52 bits of mantissa plus one implicit digit. Since + 52 bits are representable without rest using hexadecimal + digits we use only the implicit digits for the number before + the decimal point. */ + unsigned long long int num; + + num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32 + | fpnum.dbl.ieee.mantissa1); + + zero_mantissa = num == 0; + + if (sizeof (unsigned long int) > 6) + numstr = _itoa_word (num, numbuf + sizeof numbuf, 16, + info->spec == 'A'); + else + numstr = _itoa (num, numbuf + sizeof numbuf, 16, + info->spec == 'A'); + + /* Fill with zeroes. */ + while (numstr > numbuf + (sizeof numbuf - 52 / 4)) + *--numstr = '0'; + + leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1'; + + exponent = fpnum.dbl.ieee.exponent; + + if (exponent == 0) + { + if (zero_mantissa) + expnegative = 0; + else + { + /* This is a denormalized number. */ + expnegative = 1; + exponent = IEEE754_DOUBLE_BIAS - 1; + } + } + else if (exponent >= IEEE754_DOUBLE_BIAS) + { + expnegative = 0; + exponent -= IEEE754_DOUBLE_BIAS; + } + else + { + expnegative = 1; + exponent = -(exponent - IEEE754_DOUBLE_BIAS); + } + } + else + { + /* The "strange" 80 bit format on ix86 and m68k has an explicit + leading digit in the 64 bit mantissa. */ + unsigned long long int num; + + assert (sizeof (long double) == 12); + + num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32 + | fpnum.ldbl.ieee.mantissa1); + + zero_mantissa = num == 0; + + if (sizeof (unsigned long int) > 6) + numstr = _itoa_word (num, numbuf + sizeof numbuf, 16, + info->spec == 'A'); + else + numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A'); + + /* Fill with zeroes. */ + while (numstr > numbuf + (sizeof numbuf - 64 / 4)) + *--numstr = '0'; + + /* We use a full nibble for the leading digit. */ + leading = *numstr++; + + /* We have 3 bits from the mantissa in the leading nibble. + Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */ + exponent = fpnum.ldbl.ieee.exponent; + + if (exponent == 0) + { + if (zero_mantissa) + expnegative = 0; + else + { + /* This is a denormalized number. */ + expnegative = 1; + /* This is a hook for the m68k long double format, where the + exponent bias is the same for normalized and denormalized + numbers. */ +#ifndef LONG_DOUBLE_DENORM_BIAS +# define LONG_DOUBLE_DENORM_BIAS (IEEE854_LONG_DOUBLE_BIAS - 1) +#endif + exponent = LONG_DOUBLE_DENORM_BIAS + 3; + } + } + else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3) + { + expnegative = 0; + exponent -= IEEE854_LONG_DOUBLE_BIAS + 3; + } + else + { + expnegative = 1; + exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3)); + } + } + + /* Look for trailing zeroes. */ + if (! zero_mantissa) + { + numend = numbuf + sizeof numbuf; + while (numend[-1] == '0') + --numend; + + if (precision == -1) + precision = numend - numstr; + else if (precision < numend - numstr + && (numstr[precision] > '8' + || (('A' < '0' || 'a' < '0') + && numstr[precision] < '0') + || (numstr[precision] == '8' + && (precision + 1 < numend - numstr + /* Round to even. */ + || (precision > 0 + && ((numstr[precision - 1] & 1) + ^ (isdigit (numstr[precision - 1]) == 0))) + || (precision == 0 + && ((leading & 1) + ^ (isdigit (leading) == 0))))))) + { + /* Round up. */ + int cnt = precision; + while (--cnt >= 0) + { + char ch = numstr[cnt]; + /* We assume that the digits and the letters are ordered + like in ASCII. This is true for the rest of GNU, too. */ + if (ch == '9') + { + numstr[cnt] = info->spec; /* This is tricky, + think about it! */ + break; + } + else if (tolower (ch) < 'f') + { + ++numstr[cnt]; + break; + } + else + numstr[cnt] = '0'; + } + if (cnt < 0) + { + /* The mantissa so far was fff...f Now increment the + leading digit. Here it is again possible that we + get an overflow. */ + if (leading == '9') + leading = info->spec; + else if (tolower (leading) < 'f') + ++leading; + else + { + leading = 1; + if (expnegative) + { + exponent += 4; + if (exponent >= 0) + expnegative = 0; + } + else + exponent += 4; + } + } + } + } + else + numend = numstr; + + /* Now we can compute the exponent string. */ + expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0); + + /* Now we have all information to compute the size. */ + width -= ((negative || info->showsign || info->space) + /* Sign. */ + + 2 + 1 + 1 + precision + 1 + 1 + /* 0x h . hhh P ExpoSign. */ + + ((expbuf + sizeof expbuf) - expstr)); + /* Exponent. */ + + /* A special case when the mantissa or the precision is zero and the `#' + is not given. In this case we must not print the decimal point. */ + if ((zero_mantissa || precision == 0) && !info->alt) + ++width; /* This nihilates the +1 for the decimal-point + character in the following equation. */ + + if (!info->left && width > 0) + PADN (' ', width); + + if (negative) + outchar ('-'); + else if (info->showsign) + outchar ('+'); + else if (info->space) + outchar (' '); + + outchar ('0'); + outchar (info->spec == 'A' ? 'X' : 'x'); + outchar (leading); + + if ((!zero_mantissa && precision > 0) || info->alt) + outchar (decimal); + + if (!zero_mantissa && precision > 0) + { + PRINT (numstr, MIN (numend - numstr, precision)); + if (precision > numend - numstr) + PADN ('0', precision - (numend - numstr)); + } + + if (info->left && info->pad == '0' && width > 0) + PADN ('0', width); + + outchar (info->spec == 'A' ? 'P' : 'p'); + + outchar (expnegative ? '-' : '+'); + + PRINT (expstr, (expbuf + sizeof expbuf) - expstr); + + if (info->left && info->pad != '0' && width > 0) + PADN (info->pad, width); + + return done; +} diff --git a/sysdeps/m68k/printf_fphex.c b/sysdeps/m68k/printf_fphex.c new file mode 100644 index 0000000000..0e68b16b77 --- /dev/null +++ b/sysdeps/m68k/printf_fphex.c @@ -0,0 +1,2 @@ +#define LONG_DOUBLE_DENORM_BIAS IEEE854_LONG_DOUBLE_BIAS +#include -- cgit v1.2.3