xref: /haiku/src/system/libroot/posix/glibc/stdio-common/printf_fphex.c (revision d1716b277cbaf2b4265728d559b819d73330c1ef)
15af32e75SAxel Dörfler /* Print floating point number in hexadecimal notation according to ISO C99.
2294818c5SAlex Smith    Copyright (C) 1997-2002,2004,2006 Free Software Foundation, Inc.
35af32e75SAxel Dörfler    This file is part of the GNU C Library.
45af32e75SAxel Dörfler    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
55af32e75SAxel Dörfler 
65af32e75SAxel Dörfler    The GNU C Library is free software; you can redistribute it and/or
75af32e75SAxel Dörfler    modify it under the terms of the GNU Lesser General Public
85af32e75SAxel Dörfler    License as published by the Free Software Foundation; either
95af32e75SAxel Dörfler    version 2.1 of the License, or (at your option) any later version.
105af32e75SAxel Dörfler 
115af32e75SAxel Dörfler    The GNU C Library is distributed in the hope that it will be useful,
125af32e75SAxel Dörfler    but WITHOUT ANY WARRANTY; without even the implied warranty of
135af32e75SAxel Dörfler    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145af32e75SAxel Dörfler    Lesser General Public License for more details.
155af32e75SAxel Dörfler 
165af32e75SAxel Dörfler    You should have received a copy of the GNU Lesser General Public
175af32e75SAxel Dörfler    License along with the GNU C Library; if not, write to the Free
185af32e75SAxel Dörfler    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
195af32e75SAxel Dörfler    02111-1307 USA.  */
205af32e75SAxel Dörfler 
215af32e75SAxel Dörfler #include <ctype.h>
225af32e75SAxel Dörfler #include <ieee754.h>
235af32e75SAxel Dörfler #include <math.h>
245af32e75SAxel Dörfler #include <printf.h>
255af32e75SAxel Dörfler #include <stdlib.h>
265af32e75SAxel Dörfler #include <stdio.h>
275af32e75SAxel Dörfler #include <string.h>
285af32e75SAxel Dörfler #include <wchar.h>
295af32e75SAxel Dörfler #include "_itoa.h"
305af32e75SAxel Dörfler #include "_itowa.h"
315af32e75SAxel Dörfler #include <locale/localeinfo.h>
325af32e75SAxel Dörfler 
335af32e75SAxel Dörfler /* #define NDEBUG 1*/		/* Undefine this for debugging assertions.  */
345af32e75SAxel Dörfler #include <assert.h>
355af32e75SAxel Dörfler 
36*d1716b27SOliver Tappe int __printf_fphex (FILE *fp, const struct printf_info *info,
37*d1716b27SOliver Tappe 		const void *const *args);
38*d1716b27SOliver Tappe 
395af32e75SAxel Dörfler /* This defines make it possible to use the same code for GNU C library and
405af32e75SAxel Dörfler    the GNU I/O library.	 */
415af32e75SAxel Dörfler #ifdef USE_IN_LIBIO
425af32e75SAxel Dörfler # include <libioP.h>
435af32e75SAxel Dörfler # define PUT(f, s, n) _IO_sputn (f, s, n)
445af32e75SAxel Dörfler # define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
455af32e75SAxel Dörfler /* We use this file GNU C library and GNU I/O library.	So make
465af32e75SAxel Dörfler    names equal.	 */
475af32e75SAxel Dörfler # undef putc
485af32e75SAxel Dörfler # define putc(c, f) (wide \
495af32e75SAxel Dörfler 		     ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
505af32e75SAxel Dörfler # define size_t     _IO_size_t
515af32e75SAxel Dörfler # define FILE	     _IO_FILE
525af32e75SAxel Dörfler #else	/* ! USE_IN_LIBIO */
535af32e75SAxel Dörfler # define PUT(f, s, n) fwrite (s, 1, n, f)
545af32e75SAxel Dörfler # define PAD(f, c, n) __printf_pad (f, c, n)
555af32e75SAxel Dörfler ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c.  */
565af32e75SAxel Dörfler #endif	/* USE_IN_LIBIO */
575af32e75SAxel Dörfler 
585af32e75SAxel Dörfler /* Macros for doing the actual output.  */
595af32e75SAxel Dörfler 
605af32e75SAxel Dörfler #define outchar(ch)							      \
615af32e75SAxel Dörfler   do									      \
625af32e75SAxel Dörfler     {									      \
635af32e75SAxel Dörfler       register const int outc = (ch);					      \
645af32e75SAxel Dörfler       if (putc (outc, fp) == EOF)					      \
655af32e75SAxel Dörfler 	return -1;							      \
665af32e75SAxel Dörfler       ++done;								      \
675af32e75SAxel Dörfler     } while (0)
685af32e75SAxel Dörfler 
695af32e75SAxel Dörfler #define PRINT(ptr, wptr, len)						      \
705af32e75SAxel Dörfler   do									      \
715af32e75SAxel Dörfler     {									      \
725af32e75SAxel Dörfler       register size_t outlen = (len);					      \
735af32e75SAxel Dörfler       if (wide)								      \
745af32e75SAxel Dörfler 	while (outlen-- > 0)						      \
755af32e75SAxel Dörfler 	  outchar (*wptr++);						      \
765af32e75SAxel Dörfler       else								      \
775af32e75SAxel Dörfler 	while (outlen-- > 0)						      \
785af32e75SAxel Dörfler 	  outchar (*ptr++);						      \
795af32e75SAxel Dörfler     } while (0)
805af32e75SAxel Dörfler 
815af32e75SAxel Dörfler #define PADN(ch, len)							      \
825af32e75SAxel Dörfler   do									      \
835af32e75SAxel Dörfler     {									      \
845af32e75SAxel Dörfler       if (PAD (fp, ch, len) != len)					      \
855af32e75SAxel Dörfler 	return -1;							      \
865af32e75SAxel Dörfler       done += len;							      \
875af32e75SAxel Dörfler     }									      \
885af32e75SAxel Dörfler   while (0)
895af32e75SAxel Dörfler 
905af32e75SAxel Dörfler #ifndef MIN
915af32e75SAxel Dörfler # define MIN(a,b) ((a)<(b)?(a):(b))
925af32e75SAxel Dörfler #endif
935af32e75SAxel Dörfler 
945af32e75SAxel Dörfler 
95294818c5SAlex Smith 
96*d1716b27SOliver Tappe #if defined(__x86_64__) || defined(__INTEL__)
97294818c5SAlex Smith 
98294818c5SAlex Smith /* sysdeps/x86_64/fpu/printf_fphex.c */
99294818c5SAlex Smith 
100294818c5SAlex Smith #ifndef LONG_DOUBLE_DENORM_BIAS
101294818c5SAlex Smith # define LONG_DOUBLE_DENORM_BIAS (IEEE854_LONG_DOUBLE_BIAS - 1)
102294818c5SAlex Smith #endif
103294818c5SAlex Smith 
104294818c5SAlex Smith #define PRINT_FPHEX_LONG_DOUBLE \
105294818c5SAlex Smith do {									      \
106294818c5SAlex Smith       /* The "strange" 80 bit format on ix86 and m68k has an explicit	      \
107294818c5SAlex Smith 	 leading digit in the 64 bit mantissa.  */			      \
108294818c5SAlex Smith       unsigned long long int num;					      \
109294818c5SAlex Smith 									      \
110294818c5SAlex Smith 									      \
111294818c5SAlex Smith       num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32	      \
112294818c5SAlex Smith 	     | fpnum.ldbl.ieee.mantissa1);				      \
113294818c5SAlex Smith 									      \
114294818c5SAlex Smith       zero_mantissa = num == 0;						      \
115294818c5SAlex Smith 									      \
116294818c5SAlex Smith       if (sizeof (unsigned long int) > 6)				      \
117294818c5SAlex Smith 	{								      \
118294818c5SAlex Smith 	  numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,		      \
119294818c5SAlex Smith 			       info->spec == 'A');			      \
120294818c5SAlex Smith 	  wnumstr = _itowa_word (num,					      \
121294818c5SAlex Smith 				 wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),\
122294818c5SAlex Smith 				 16, info->spec == 'A');		      \
123294818c5SAlex Smith 	}								      \
124294818c5SAlex Smith       else								      \
125294818c5SAlex Smith 	{								      \
126294818c5SAlex Smith 	  numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A');\
127294818c5SAlex Smith 	  wnumstr = _itowa (num,					      \
128294818c5SAlex Smith 			    wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),    \
129294818c5SAlex Smith 			    16, info->spec == 'A');			      \
130294818c5SAlex Smith 	}								      \
131294818c5SAlex Smith 									      \
132294818c5SAlex Smith       /* Fill with zeroes.  */						      \
133294818c5SAlex Smith       while (numstr > numbuf + (sizeof numbuf - 64 / 4))		      \
134294818c5SAlex Smith 	{								      \
135294818c5SAlex Smith 	  *--numstr = '0';						      \
136294818c5SAlex Smith 	  *--wnumstr = L'0';						      \
137294818c5SAlex Smith 	}								      \
138294818c5SAlex Smith 									      \
139294818c5SAlex Smith       /* We use a full nibble for the leading digit.  */		      \
140294818c5SAlex Smith       leading = *numstr++;						      \
141294818c5SAlex Smith 									      \
142294818c5SAlex Smith       /* We have 3 bits from the mantissa in the leading nibble.	      \
143294818c5SAlex Smith 	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
144294818c5SAlex Smith       exponent = fpnum.ldbl.ieee.exponent;				      \
145294818c5SAlex Smith 									      \
146294818c5SAlex Smith       if (exponent == 0)						      \
147294818c5SAlex Smith 	{								      \
148294818c5SAlex Smith 	  if (zero_mantissa)						      \
149294818c5SAlex Smith 	    expnegative = 0;						      \
150294818c5SAlex Smith 	  else								      \
151294818c5SAlex Smith 	    {								      \
152294818c5SAlex Smith 	      /* This is a denormalized number.  */			      \
153294818c5SAlex Smith 	      expnegative = 1;						      \
154294818c5SAlex Smith 	      /* This is a hook for the m68k long double format, where the    \
155294818c5SAlex Smith 		 exponent bias is the same for normalized and denormalized    \
156294818c5SAlex Smith 		 numbers.  */						      \
157294818c5SAlex Smith 	      exponent = LONG_DOUBLE_DENORM_BIAS + 3;			      \
158294818c5SAlex Smith 	    }								      \
159294818c5SAlex Smith 	}								      \
160294818c5SAlex Smith       else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3)		      \
161294818c5SAlex Smith 	{								      \
162294818c5SAlex Smith 	  expnegative = 0;						      \
163294818c5SAlex Smith 	  exponent -= IEEE854_LONG_DOUBLE_BIAS + 3;			      \
164294818c5SAlex Smith 	}								      \
165294818c5SAlex Smith       else								      \
166294818c5SAlex Smith 	{								      \
167294818c5SAlex Smith 	  expnegative = 1;						      \
168294818c5SAlex Smith 	  exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3));	      \
169294818c5SAlex Smith 	}								      \
170294818c5SAlex Smith } while (0)
171294818c5SAlex Smith 
172*d1716b27SOliver Tappe #endif	/* __x86_64__ || __INTEL__ */
173294818c5SAlex Smith 
174294818c5SAlex Smith 
1755af32e75SAxel Dörfler int
1765af32e75SAxel Dörfler __printf_fphex (FILE *fp,
1775af32e75SAxel Dörfler 		const struct printf_info *info,
1785af32e75SAxel Dörfler 		const void *const *args)
1795af32e75SAxel Dörfler {
1805af32e75SAxel Dörfler   /* The floating-point value to output.  */
1815af32e75SAxel Dörfler   union
1825af32e75SAxel Dörfler     {
1835af32e75SAxel Dörfler       union ieee754_double dbl;
1845af32e75SAxel Dörfler       union ieee854_long_double ldbl;
1855af32e75SAxel Dörfler     }
1865af32e75SAxel Dörfler   fpnum;
1875af32e75SAxel Dörfler 
1885af32e75SAxel Dörfler   /* Locale-dependent representation of decimal point.	*/
1895af32e75SAxel Dörfler   const char *decimal;
1905af32e75SAxel Dörfler   wchar_t decimalwc;
1915af32e75SAxel Dörfler 
1925af32e75SAxel Dörfler   /* "NaN" or "Inf" for the special cases.  */
1935af32e75SAxel Dörfler   const char *special = NULL;
1945af32e75SAxel Dörfler   const wchar_t *wspecial = NULL;
1955af32e75SAxel Dörfler 
1965af32e75SAxel Dörfler   /* Buffer for the generated number string for the mantissa.  The
1975af32e75SAxel Dörfler      maximal size for the mantissa is 128 bits.  */
1985af32e75SAxel Dörfler   char numbuf[32];
199*d1716b27SOliver Tappe   char *numstr="";
2005af32e75SAxel Dörfler   char *numend;
2015af32e75SAxel Dörfler   wchar_t wnumbuf[32];
202*d1716b27SOliver Tappe   wchar_t *wnumstr=L"";
2035af32e75SAxel Dörfler   wchar_t *wnumend;
2045af32e75SAxel Dörfler   int negative;
2055af32e75SAxel Dörfler 
2065af32e75SAxel Dörfler   /* The maximal exponent of two in decimal notation has 5 digits.  */
2075af32e75SAxel Dörfler   char expbuf[5];
2085af32e75SAxel Dörfler   char *expstr;
2095af32e75SAxel Dörfler   wchar_t wexpbuf[5];
2105af32e75SAxel Dörfler   wchar_t *wexpstr;
211*d1716b27SOliver Tappe   int expnegative = 0;
212*d1716b27SOliver Tappe   int exponent = 0;
2135af32e75SAxel Dörfler 
2145af32e75SAxel Dörfler   /* Non-zero is mantissa is zero.  */
215*d1716b27SOliver Tappe   int zero_mantissa = 1;
2165af32e75SAxel Dörfler 
2175af32e75SAxel Dörfler   /* The leading digit before the decimal point.  */
218*d1716b27SOliver Tappe   char leading = '0';
2195af32e75SAxel Dörfler 
2205af32e75SAxel Dörfler   /* Precision.  */
2215af32e75SAxel Dörfler   int precision = info->prec;
2225af32e75SAxel Dörfler 
2235af32e75SAxel Dörfler   /* Width.  */
2245af32e75SAxel Dörfler   int width = info->width;
2255af32e75SAxel Dörfler 
2265af32e75SAxel Dörfler   /* Number of characters written.  */
2275af32e75SAxel Dörfler   int done = 0;
2285af32e75SAxel Dörfler 
2295af32e75SAxel Dörfler   /* Nonzero if this is output on a wide character stream.  */
2305af32e75SAxel Dörfler   int wide = info->wide;
2315af32e75SAxel Dörfler 
2325af32e75SAxel Dörfler 
2335af32e75SAxel Dörfler   /* Figure out the decimal point character.  */
2345af32e75SAxel Dörfler   if (info->extra == 0)
2355af32e75SAxel Dörfler     {
2365af32e75SAxel Dörfler       decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
2375af32e75SAxel Dörfler       decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
2385af32e75SAxel Dörfler     }
2395af32e75SAxel Dörfler   else
2405af32e75SAxel Dörfler     {
2415af32e75SAxel Dörfler       decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
2425af32e75SAxel Dörfler       decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
2435af32e75SAxel Dörfler 				    _NL_MONETARY_DECIMAL_POINT_WC);
2445af32e75SAxel Dörfler     }
2455af32e75SAxel Dörfler   /* The decimal point character must never be zero.  */
2465af32e75SAxel Dörfler   assert (*decimal != '\0' && decimalwc != L'\0');
2475af32e75SAxel Dörfler 
2485af32e75SAxel Dörfler 
2495af32e75SAxel Dörfler   /* Fetch the argument value.	*/
2505af32e75SAxel Dörfler #ifndef __NO_LONG_DOUBLE_MATH
2515af32e75SAxel Dörfler   if (info->is_long_double && sizeof (long double) > sizeof (double))
2525af32e75SAxel Dörfler     {
2535af32e75SAxel Dörfler       fpnum.ldbl.d = *(const long double *) args[0];
2545af32e75SAxel Dörfler 
2555af32e75SAxel Dörfler       /* Check for special values: not a number or infinity.  */
2565af32e75SAxel Dörfler       if (__isnanl (fpnum.ldbl.d))
2575af32e75SAxel Dörfler 	{
2585af32e75SAxel Dörfler 	  if (isupper (info->spec))
2595af32e75SAxel Dörfler 	    {
2605af32e75SAxel Dörfler 	      special = "NAN";
2615af32e75SAxel Dörfler 	      wspecial = L"NAN";
2625af32e75SAxel Dörfler 	    }
2635af32e75SAxel Dörfler 	  else
2645af32e75SAxel Dörfler 	    {
2655af32e75SAxel Dörfler 	      special = "nan";
2665af32e75SAxel Dörfler 	      wspecial = L"nan";
2675af32e75SAxel Dörfler 	    }
2685af32e75SAxel Dörfler 	  negative = 0;
2695af32e75SAxel Dörfler 	}
2705af32e75SAxel Dörfler       else
2715af32e75SAxel Dörfler 	{
2725af32e75SAxel Dörfler 	  if (__isinfl (fpnum.ldbl.d))
2735af32e75SAxel Dörfler 	    {
2745af32e75SAxel Dörfler 	      if (isupper (info->spec))
2755af32e75SAxel Dörfler 		{
2765af32e75SAxel Dörfler 		  special = "INF";
2775af32e75SAxel Dörfler 		  wspecial = L"INF";
2785af32e75SAxel Dörfler 		}
2795af32e75SAxel Dörfler 	      else
2805af32e75SAxel Dörfler 		{
2815af32e75SAxel Dörfler 		  special = "inf";
2825af32e75SAxel Dörfler 		  wspecial = L"inf";
2835af32e75SAxel Dörfler 		}
2845af32e75SAxel Dörfler 	    }
2855af32e75SAxel Dörfler 
2865af32e75SAxel Dörfler 	  negative = signbit (fpnum.ldbl.d);
2875af32e75SAxel Dörfler 	}
2885af32e75SAxel Dörfler     }
2895af32e75SAxel Dörfler   else
2905af32e75SAxel Dörfler #endif	/* no long double */
2915af32e75SAxel Dörfler     {
2925af32e75SAxel Dörfler       fpnum.dbl.d = *(const double *) args[0];
2935af32e75SAxel Dörfler 
2945af32e75SAxel Dörfler       /* Check for special values: not a number or infinity.  */
2955af32e75SAxel Dörfler       if (__isnan (fpnum.dbl.d))
2965af32e75SAxel Dörfler 	{
2975af32e75SAxel Dörfler 	  if (isupper (info->spec))
2985af32e75SAxel Dörfler 	    {
2995af32e75SAxel Dörfler 	      special = "NAN";
3005af32e75SAxel Dörfler 	      wspecial = L"NAN";
3015af32e75SAxel Dörfler 	    }
3025af32e75SAxel Dörfler 	  else
3035af32e75SAxel Dörfler 	    {
3045af32e75SAxel Dörfler 	      special = "nan";
3055af32e75SAxel Dörfler 	      wspecial = L"nan";
3065af32e75SAxel Dörfler 	    }
3075af32e75SAxel Dörfler 	  negative = 0;
3085af32e75SAxel Dörfler 	}
3095af32e75SAxel Dörfler       else
3105af32e75SAxel Dörfler 	{
3115af32e75SAxel Dörfler 	  if (__isinf (fpnum.dbl.d))
3125af32e75SAxel Dörfler 	    {
3135af32e75SAxel Dörfler 	      if (isupper (info->spec))
3145af32e75SAxel Dörfler 		{
3155af32e75SAxel Dörfler 		  special = "INF";
3165af32e75SAxel Dörfler 		  wspecial = L"INF";
3175af32e75SAxel Dörfler 		}
3185af32e75SAxel Dörfler 	      else
3195af32e75SAxel Dörfler 		{
3205af32e75SAxel Dörfler 		  special = "inf";
3215af32e75SAxel Dörfler 		  wspecial = L"inf";
3225af32e75SAxel Dörfler 		}
3235af32e75SAxel Dörfler 	    }
3245af32e75SAxel Dörfler 
3255af32e75SAxel Dörfler 	  negative = signbit (fpnum.dbl.d);
3265af32e75SAxel Dörfler 	}
3275af32e75SAxel Dörfler     }
3285af32e75SAxel Dörfler 
3295af32e75SAxel Dörfler   if (special)
3305af32e75SAxel Dörfler     {
3315af32e75SAxel Dörfler       int width = info->width;
3325af32e75SAxel Dörfler 
3335af32e75SAxel Dörfler       if (negative || info->showsign || info->space)
3345af32e75SAxel Dörfler 	--width;
3355af32e75SAxel Dörfler       width -= 3;
3365af32e75SAxel Dörfler 
3375af32e75SAxel Dörfler       if (!info->left && width > 0)
3385af32e75SAxel Dörfler 	PADN (' ', width);
3395af32e75SAxel Dörfler 
3405af32e75SAxel Dörfler       if (negative)
3415af32e75SAxel Dörfler 	outchar ('-');
3425af32e75SAxel Dörfler       else if (info->showsign)
3435af32e75SAxel Dörfler 	outchar ('+');
3445af32e75SAxel Dörfler       else if (info->space)
3455af32e75SAxel Dörfler 	outchar (' ');
3465af32e75SAxel Dörfler 
3475af32e75SAxel Dörfler       PRINT (special, wspecial, 3);
3485af32e75SAxel Dörfler 
3495af32e75SAxel Dörfler       if (info->left && width > 0)
3505af32e75SAxel Dörfler 	PADN (' ', width);
3515af32e75SAxel Dörfler 
3525af32e75SAxel Dörfler       return done;
3535af32e75SAxel Dörfler     }
3545af32e75SAxel Dörfler 
3555af32e75SAxel Dörfler   if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
3565af32e75SAxel Dörfler     {
3575af32e75SAxel Dörfler       /* We have 52 bits of mantissa plus one implicit digit.  Since
3585af32e75SAxel Dörfler 	 52 bits are representable without rest using hexadecimal
3595af32e75SAxel Dörfler 	 digits we use only the implicit digits for the number before
3605af32e75SAxel Dörfler 	 the decimal point.  */
3615af32e75SAxel Dörfler       unsigned long long int num;
3625af32e75SAxel Dörfler 
3635af32e75SAxel Dörfler       num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
3645af32e75SAxel Dörfler 	     | fpnum.dbl.ieee.mantissa1);
3655af32e75SAxel Dörfler 
3665af32e75SAxel Dörfler       zero_mantissa = num == 0;
3675af32e75SAxel Dörfler 
3685af32e75SAxel Dörfler       if (sizeof (unsigned long int) > 6)
3695af32e75SAxel Dörfler 	{
3705af32e75SAxel Dörfler 	  wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
3715af32e75SAxel Dörfler 				 info->spec == 'A');
3725af32e75SAxel Dörfler 	  numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
3735af32e75SAxel Dörfler 			       info->spec == 'A');
3745af32e75SAxel Dörfler 	}
3755af32e75SAxel Dörfler       else
3765af32e75SAxel Dörfler 	{
3775af32e75SAxel Dörfler 	  wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
3785af32e75SAxel Dörfler 			    info->spec == 'A');
3795af32e75SAxel Dörfler 	  numstr = _itoa (num, numbuf + sizeof numbuf, 16,
3805af32e75SAxel Dörfler 			  info->spec == 'A');
3815af32e75SAxel Dörfler 	}
3825af32e75SAxel Dörfler 
3835af32e75SAxel Dörfler       /* Fill with zeroes.  */
3845af32e75SAxel Dörfler       while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
3855af32e75SAxel Dörfler 	{
3865af32e75SAxel Dörfler 	  *--wnumstr = L'0';
3875af32e75SAxel Dörfler 	  *--numstr = '0';
3885af32e75SAxel Dörfler 	}
3895af32e75SAxel Dörfler 
3905af32e75SAxel Dörfler       leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
3915af32e75SAxel Dörfler 
3925af32e75SAxel Dörfler       exponent = fpnum.dbl.ieee.exponent;
3935af32e75SAxel Dörfler 
3945af32e75SAxel Dörfler       if (exponent == 0)
3955af32e75SAxel Dörfler 	{
3965af32e75SAxel Dörfler 	  if (zero_mantissa)
3975af32e75SAxel Dörfler 	    expnegative = 0;
3985af32e75SAxel Dörfler 	  else
3995af32e75SAxel Dörfler 	    {
4005af32e75SAxel Dörfler 	      /* This is a denormalized number.  */
4015af32e75SAxel Dörfler 	      expnegative = 1;
4025af32e75SAxel Dörfler 	      exponent = IEEE754_DOUBLE_BIAS - 1;
4035af32e75SAxel Dörfler 	    }
4045af32e75SAxel Dörfler 	}
4055af32e75SAxel Dörfler       else if (exponent >= IEEE754_DOUBLE_BIAS)
4065af32e75SAxel Dörfler 	{
4075af32e75SAxel Dörfler 	  expnegative = 0;
4085af32e75SAxel Dörfler 	  exponent -= IEEE754_DOUBLE_BIAS;
4095af32e75SAxel Dörfler 	}
4105af32e75SAxel Dörfler       else
4115af32e75SAxel Dörfler 	{
4125af32e75SAxel Dörfler 	  expnegative = 1;
4135af32e75SAxel Dörfler 	  exponent = -(exponent - IEEE754_DOUBLE_BIAS);
4145af32e75SAxel Dörfler 	}
4155af32e75SAxel Dörfler     }
4165af32e75SAxel Dörfler #ifdef PRINT_FPHEX_LONG_DOUBLE
4175af32e75SAxel Dörfler   else
4185af32e75SAxel Dörfler     PRINT_FPHEX_LONG_DOUBLE;
4195af32e75SAxel Dörfler #endif
4205af32e75SAxel Dörfler 
4215af32e75SAxel Dörfler   /* Look for trailing zeroes.  */
4225af32e75SAxel Dörfler   if (! zero_mantissa)
4235af32e75SAxel Dörfler     {
424294818c5SAlex Smith       wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
425294818c5SAlex Smith       numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
4265af32e75SAxel Dörfler       while (wnumend[-1] == L'0')
4275af32e75SAxel Dörfler 	{
4285af32e75SAxel Dörfler 	  --wnumend;
4295af32e75SAxel Dörfler 	  --numend;
4305af32e75SAxel Dörfler 	}
4315af32e75SAxel Dörfler 
4325af32e75SAxel Dörfler       if (precision == -1)
4335af32e75SAxel Dörfler 	precision = numend - numstr;
4345af32e75SAxel Dörfler       else if (precision < numend - numstr
4355af32e75SAxel Dörfler 	       && (numstr[precision] > '8'
4365af32e75SAxel Dörfler 		   || (('A' < '0' || 'a' < '0')
4375af32e75SAxel Dörfler 		       && numstr[precision] < '0')
4385af32e75SAxel Dörfler 		   || (numstr[precision] == '8'
4395af32e75SAxel Dörfler 		       && (precision + 1 < numend - numstr
4405af32e75SAxel Dörfler 			   /* Round to even.  */
4415af32e75SAxel Dörfler 			   || (precision > 0
4425af32e75SAxel Dörfler 			       && ((numstr[precision - 1] & 1)
4435af32e75SAxel Dörfler 				   ^ (isdigit (numstr[precision - 1]) == 0)))
4445af32e75SAxel Dörfler 			   || (precision == 0
4455af32e75SAxel Dörfler 			       && ((leading & 1)
4465af32e75SAxel Dörfler 				   ^ (isdigit (leading) == 0)))))))
4475af32e75SAxel Dörfler 	{
4485af32e75SAxel Dörfler 	  /* Round up.  */
4495af32e75SAxel Dörfler 	  int cnt = precision;
4505af32e75SAxel Dörfler 	  while (--cnt >= 0)
4515af32e75SAxel Dörfler 	    {
4525af32e75SAxel Dörfler 	      char ch = numstr[cnt];
4535af32e75SAxel Dörfler 	      /* We assume that the digits and the letters are ordered
4545af32e75SAxel Dörfler 		 like in ASCII.  This is true for the rest of GNU, too.  */
4555af32e75SAxel Dörfler 	      if (ch == '9')
4565af32e75SAxel Dörfler 		{
4575af32e75SAxel Dörfler 		  wnumstr[cnt] = (wchar_t) info->spec;
4585af32e75SAxel Dörfler 		  numstr[cnt] = info->spec;	/* This is tricky,
4595af32e75SAxel Dörfler 		  				   think about it!  */
4605af32e75SAxel Dörfler 		  break;
4615af32e75SAxel Dörfler 		}
4625af32e75SAxel Dörfler 	      else if (tolower (ch) < 'f')
4635af32e75SAxel Dörfler 		{
4645af32e75SAxel Dörfler 		  ++numstr[cnt];
4655af32e75SAxel Dörfler 		  ++wnumstr[cnt];
4665af32e75SAxel Dörfler 		  break;
4675af32e75SAxel Dörfler 		}
4685af32e75SAxel Dörfler 	      else
4695af32e75SAxel Dörfler 		{
4705af32e75SAxel Dörfler 		  numstr[cnt] = '0';
4715af32e75SAxel Dörfler 		  wnumstr[cnt] = L'0';
4725af32e75SAxel Dörfler 		}
4735af32e75SAxel Dörfler 	    }
4745af32e75SAxel Dörfler 	  if (cnt < 0)
4755af32e75SAxel Dörfler 	    {
4765af32e75SAxel Dörfler 	      /* The mantissa so far was fff...f  Now increment the
4775af32e75SAxel Dörfler 		 leading digit.  Here it is again possible that we
4785af32e75SAxel Dörfler 		 get an overflow.  */
4795af32e75SAxel Dörfler 	      if (leading == '9')
4805af32e75SAxel Dörfler 		leading = info->spec;
4815af32e75SAxel Dörfler 	      else if (tolower (leading) < 'f')
4825af32e75SAxel Dörfler 		++leading;
4835af32e75SAxel Dörfler 	      else
4845af32e75SAxel Dörfler 		{
485294818c5SAlex Smith 		  leading = '1';
4865af32e75SAxel Dörfler 		  if (expnegative)
4875af32e75SAxel Dörfler 		    {
488294818c5SAlex Smith 		      exponent -= 4;
489294818c5SAlex Smith 		      if (exponent <= 0)
490294818c5SAlex Smith 			{
491294818c5SAlex Smith 			  exponent = -exponent;
4925af32e75SAxel Dörfler 			  expnegative = 0;
4935af32e75SAxel Dörfler 			}
494294818c5SAlex Smith 		    }
4955af32e75SAxel Dörfler 		  else
4965af32e75SAxel Dörfler 		    exponent += 4;
4975af32e75SAxel Dörfler 		}
4985af32e75SAxel Dörfler 	    }
4995af32e75SAxel Dörfler 	}
5005af32e75SAxel Dörfler     }
5015af32e75SAxel Dörfler   else
5025af32e75SAxel Dörfler     {
5035af32e75SAxel Dörfler       if (precision == -1)
5045af32e75SAxel Dörfler 	precision = 0;
5055af32e75SAxel Dörfler       numend = numstr;
5065af32e75SAxel Dörfler       wnumend = wnumstr;
5075af32e75SAxel Dörfler     }
5085af32e75SAxel Dörfler 
5095af32e75SAxel Dörfler   /* Now we can compute the exponent string.  */
5105af32e75SAxel Dörfler   expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
5115af32e75SAxel Dörfler   wexpstr = _itowa_word (exponent,
5125af32e75SAxel Dörfler 			 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
5135af32e75SAxel Dörfler 
5145af32e75SAxel Dörfler   /* Now we have all information to compute the size.  */
5155af32e75SAxel Dörfler   width -= ((negative || info->showsign || info->space)
5165af32e75SAxel Dörfler 	    /* Sign.  */
5175af32e75SAxel Dörfler 	    + 2    + 1 + 0 + precision + 1 + 1
5185af32e75SAxel Dörfler 	    /* 0x    h   .   hhh         P   ExpoSign.  */
5195af32e75SAxel Dörfler 	    + ((expbuf + sizeof expbuf) - expstr));
5205af32e75SAxel Dörfler 	    /* Exponent.  */
5215af32e75SAxel Dörfler 
522294818c5SAlex Smith   /* Count the decimal point.
523294818c5SAlex Smith      A special case when the mantissa or the precision is zero and the `#'
524294818c5SAlex Smith      is not given.  In this case we must not print the decimal point.  */
5255af32e75SAxel Dörfler   if (precision > 0 || info->alt)
5265af32e75SAxel Dörfler     width -= wide ? 1 : strlen (decimal);
5275af32e75SAxel Dörfler 
528294818c5SAlex Smith   if (!info->left && info->pad != '0' && width > 0)
5295af32e75SAxel Dörfler     PADN (' ', width);
5305af32e75SAxel Dörfler 
5315af32e75SAxel Dörfler   if (negative)
5325af32e75SAxel Dörfler     outchar ('-');
5335af32e75SAxel Dörfler   else if (info->showsign)
5345af32e75SAxel Dörfler     outchar ('+');
5355af32e75SAxel Dörfler   else if (info->space)
5365af32e75SAxel Dörfler     outchar (' ');
5375af32e75SAxel Dörfler 
5385af32e75SAxel Dörfler   outchar ('0');
5395af32e75SAxel Dörfler   if ('X' - 'A' == 'x' - 'a')
5405af32e75SAxel Dörfler     outchar (info->spec + ('x' - 'a'));
5415af32e75SAxel Dörfler   else
5425af32e75SAxel Dörfler     outchar (info->spec == 'A' ? 'X' : 'x');
543294818c5SAlex Smith 
544294818c5SAlex Smith   if (!info->left && info->pad == '0' && width > 0)
545294818c5SAlex Smith     PADN ('0', width);
546294818c5SAlex Smith 
5475af32e75SAxel Dörfler   outchar (leading);
5485af32e75SAxel Dörfler 
5495af32e75SAxel Dörfler   if (precision > 0 || info->alt)
5505af32e75SAxel Dörfler     {
5515af32e75SAxel Dörfler       const wchar_t *wtmp = &decimalwc;
5525af32e75SAxel Dörfler       PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
5535af32e75SAxel Dörfler     }
5545af32e75SAxel Dörfler 
5555af32e75SAxel Dörfler   if (precision > 0)
5565af32e75SAxel Dörfler     {
5575af32e75SAxel Dörfler       ssize_t tofill = precision - (numend - numstr);
5585af32e75SAxel Dörfler       PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
5595af32e75SAxel Dörfler       if (tofill > 0)
5605af32e75SAxel Dörfler 	PADN ('0', tofill);
5615af32e75SAxel Dörfler     }
5625af32e75SAxel Dörfler 
5635af32e75SAxel Dörfler   if ('P' - 'A' == 'p' - 'a')
5645af32e75SAxel Dörfler     outchar (info->spec + ('p' - 'a'));
5655af32e75SAxel Dörfler   else
5665af32e75SAxel Dörfler     outchar (info->spec == 'A' ? 'P' : 'p');
5675af32e75SAxel Dörfler 
5685af32e75SAxel Dörfler   outchar (expnegative ? '-' : '+');
5695af32e75SAxel Dörfler 
5705af32e75SAxel Dörfler   PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
5715af32e75SAxel Dörfler 
5725af32e75SAxel Dörfler   if (info->left && info->pad != '0' && width > 0)
5735af32e75SAxel Dörfler     PADN (info->pad, width);
5745af32e75SAxel Dörfler 
5755af32e75SAxel Dörfler   return done;
5765af32e75SAxel Dörfler }
577