xref: /haiku/src/system/libroot/posix/glibc/stdio-common/printf_fphex.c (revision 6239b2a907c8efee7278d2a51b92acd073b26919)
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 
36d1716b27SOliver Tappe int __printf_fphex (FILE *fp, const struct printf_info *info,
37d1716b27SOliver Tappe 		const void *const *args);
38d1716b27SOliver 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 */
577e8263e5SAugustin Cavalier 
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
937e8263e5SAugustin Cavalier 
945af32e75SAxel Dörfler 
95294818c5SAlex Smith 
965ffbe7d7SAugustin Cavalier #if defined(__x86_64__) || defined(__i386__)
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++;						      \
141*6239b2a9SJérôme Duval       wnumstr++;							      \
142294818c5SAlex Smith 									      \
143294818c5SAlex Smith       /* We have 3 bits from the mantissa in the leading nibble.	      \
144294818c5SAlex Smith 	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
145294818c5SAlex Smith       exponent = fpnum.ldbl.ieee.exponent;				      \
146294818c5SAlex Smith 									      \
147294818c5SAlex Smith       if (exponent == 0)						      \
148294818c5SAlex Smith 	{								      \
149294818c5SAlex Smith 	  if (zero_mantissa)						      \
150294818c5SAlex Smith 	    expnegative = 0;						      \
151294818c5SAlex Smith 	  else								      \
152294818c5SAlex Smith 	    {								      \
153294818c5SAlex Smith 	      /* This is a denormalized number.  */			      \
154294818c5SAlex Smith 	      expnegative = 1;						      \
155294818c5SAlex Smith 	      /* This is a hook for the m68k long double format, where the    \
156294818c5SAlex Smith 		 exponent bias is the same for normalized and denormalized    \
157294818c5SAlex Smith 		 numbers.  */						      \
158294818c5SAlex Smith 	      exponent = LONG_DOUBLE_DENORM_BIAS + 3;			      \
159294818c5SAlex Smith 	    }								      \
160294818c5SAlex Smith 	}								      \
161294818c5SAlex Smith       else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3)		      \
162294818c5SAlex Smith 	{								      \
163294818c5SAlex Smith 	  expnegative = 0;						      \
164294818c5SAlex Smith 	  exponent -= IEEE854_LONG_DOUBLE_BIAS + 3;			      \
165294818c5SAlex Smith 	}								      \
166294818c5SAlex Smith       else								      \
167294818c5SAlex Smith 	{								      \
168294818c5SAlex Smith 	  expnegative = 1;						      \
169294818c5SAlex Smith 	  exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3));	      \
170294818c5SAlex Smith 	}								      \
171294818c5SAlex Smith } while (0)
172294818c5SAlex Smith 
1735ffbe7d7SAugustin Cavalier #endif	/* __x86_64__ || __i386__ */
174294818c5SAlex Smith 
175294818c5SAlex Smith 
1765af32e75SAxel Dörfler int
__printf_fphex(FILE * fp,const struct printf_info * info,const void * const * args)1775af32e75SAxel Dörfler __printf_fphex (FILE *fp,
1785af32e75SAxel Dörfler 		const struct printf_info *info,
1795af32e75SAxel Dörfler 		const void *const *args)
1805af32e75SAxel Dörfler {
1815af32e75SAxel Dörfler   /* The floating-point value to output.  */
1825af32e75SAxel Dörfler   union
1835af32e75SAxel Dörfler     {
1845af32e75SAxel Dörfler       union ieee754_double dbl;
1855af32e75SAxel Dörfler       union ieee854_long_double ldbl;
1865af32e75SAxel Dörfler     }
1875af32e75SAxel Dörfler   fpnum;
1885af32e75SAxel Dörfler 
1895af32e75SAxel Dörfler   /* Locale-dependent representation of decimal point.	*/
1905af32e75SAxel Dörfler   const char *decimal;
1915af32e75SAxel Dörfler   wchar_t decimalwc;
1925af32e75SAxel Dörfler 
1935af32e75SAxel Dörfler   /* "NaN" or "Inf" for the special cases.  */
1945af32e75SAxel Dörfler   const char *special = NULL;
1955af32e75SAxel Dörfler   const wchar_t *wspecial = NULL;
1965af32e75SAxel Dörfler 
1975af32e75SAxel Dörfler   /* Buffer for the generated number string for the mantissa.  The
1985af32e75SAxel Dörfler      maximal size for the mantissa is 128 bits.  */
1995af32e75SAxel Dörfler   char numbuf[32];
200d1716b27SOliver Tappe   char *numstr="";
2015af32e75SAxel Dörfler   char *numend;
2025af32e75SAxel Dörfler   wchar_t wnumbuf[32];
203d1716b27SOliver Tappe   wchar_t *wnumstr=L"";
2045af32e75SAxel Dörfler   wchar_t *wnumend;
2055af32e75SAxel Dörfler   int negative;
2065af32e75SAxel Dörfler 
2075af32e75SAxel Dörfler   /* The maximal exponent of two in decimal notation has 5 digits.  */
2085af32e75SAxel Dörfler   char expbuf[5];
2095af32e75SAxel Dörfler   char *expstr;
2105af32e75SAxel Dörfler   wchar_t wexpbuf[5];
2115af32e75SAxel Dörfler   wchar_t *wexpstr;
212d1716b27SOliver Tappe   int expnegative = 0;
213d1716b27SOliver Tappe   int exponent = 0;
2145af32e75SAxel Dörfler 
2155af32e75SAxel Dörfler   /* Non-zero is mantissa is zero.  */
216d1716b27SOliver Tappe   int zero_mantissa = 1;
2175af32e75SAxel Dörfler 
2185af32e75SAxel Dörfler   /* The leading digit before the decimal point.  */
219d1716b27SOliver Tappe   char leading = '0';
2205af32e75SAxel Dörfler 
2215af32e75SAxel Dörfler   /* Precision.  */
2225af32e75SAxel Dörfler   int precision = info->prec;
2235af32e75SAxel Dörfler 
2245af32e75SAxel Dörfler   /* Width.  */
2255af32e75SAxel Dörfler   int width = info->width;
2265af32e75SAxel Dörfler 
2275af32e75SAxel Dörfler   /* Number of characters written.  */
2285af32e75SAxel Dörfler   int done = 0;
2295af32e75SAxel Dörfler 
2305af32e75SAxel Dörfler   /* Nonzero if this is output on a wide character stream.  */
2315af32e75SAxel Dörfler   int wide = info->wide;
2325af32e75SAxel Dörfler 
2335af32e75SAxel Dörfler 
2345af32e75SAxel Dörfler   /* Figure out the decimal point character.  */
2355af32e75SAxel Dörfler   if (info->extra == 0)
2365af32e75SAxel Dörfler     {
2375af32e75SAxel Dörfler       decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
2385af32e75SAxel Dörfler       decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
2395af32e75SAxel Dörfler     }
2405af32e75SAxel Dörfler   else
2415af32e75SAxel Dörfler     {
2425af32e75SAxel Dörfler       decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
2435af32e75SAxel Dörfler       decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
2445af32e75SAxel Dörfler 				    _NL_MONETARY_DECIMAL_POINT_WC);
2455af32e75SAxel Dörfler     }
2465af32e75SAxel Dörfler   /* The decimal point character must never be zero.  */
2475af32e75SAxel Dörfler   assert (*decimal != '\0' && decimalwc != L'\0');
2485af32e75SAxel Dörfler 
2495af32e75SAxel Dörfler 
2505af32e75SAxel Dörfler   /* Fetch the argument value.	*/
2515af32e75SAxel Dörfler #ifndef __NO_LONG_DOUBLE_MATH
2525af32e75SAxel Dörfler   if (info->is_long_double && sizeof (long double) > sizeof (double))
2535af32e75SAxel Dörfler     {
2545af32e75SAxel Dörfler       fpnum.ldbl.d = *(const long double *) args[0];
2555af32e75SAxel Dörfler 
2565af32e75SAxel Dörfler       /* Check for special values: not a number or infinity.  */
2577e8263e5SAugustin Cavalier       if (isnan (fpnum.ldbl.d))
2585af32e75SAxel Dörfler 	{
2595af32e75SAxel Dörfler 	  if (isupper (info->spec))
2605af32e75SAxel Dörfler 	    {
2615af32e75SAxel Dörfler 	      special = "NAN";
2625af32e75SAxel Dörfler 	      wspecial = L"NAN";
2635af32e75SAxel Dörfler 	    }
2645af32e75SAxel Dörfler 	  else
2655af32e75SAxel Dörfler 	    {
2665af32e75SAxel Dörfler 	      special = "nan";
2675af32e75SAxel Dörfler 	      wspecial = L"nan";
2685af32e75SAxel Dörfler 	    }
2695af32e75SAxel Dörfler 	  negative = 0;
2705af32e75SAxel Dörfler 	}
2715af32e75SAxel Dörfler       else
2725af32e75SAxel Dörfler 	{
2737e8263e5SAugustin Cavalier 	  if (isinf (fpnum.ldbl.d))
2745af32e75SAxel Dörfler 	    {
2755af32e75SAxel Dörfler 	      if (isupper (info->spec))
2765af32e75SAxel Dörfler 		{
2775af32e75SAxel Dörfler 		  special = "INF";
2785af32e75SAxel Dörfler 		  wspecial = L"INF";
2795af32e75SAxel Dörfler 		}
2805af32e75SAxel Dörfler 	      else
2815af32e75SAxel Dörfler 		{
2825af32e75SAxel Dörfler 		  special = "inf";
2835af32e75SAxel Dörfler 		  wspecial = L"inf";
2845af32e75SAxel Dörfler 		}
2855af32e75SAxel Dörfler 	    }
2865af32e75SAxel Dörfler 
2875af32e75SAxel Dörfler 	  negative = signbit (fpnum.ldbl.d);
2885af32e75SAxel Dörfler 	}
2895af32e75SAxel Dörfler     }
2905af32e75SAxel Dörfler   else
2915af32e75SAxel Dörfler #endif	/* no long double */
2925af32e75SAxel Dörfler     {
2935af32e75SAxel Dörfler       fpnum.dbl.d = *(const double *) args[0];
2945af32e75SAxel Dörfler 
2955af32e75SAxel Dörfler       /* Check for special values: not a number or infinity.  */
296614858a9SAlexander von Gluck IV       if (isnan (fpnum.dbl.d))
2975af32e75SAxel Dörfler 	{
2985af32e75SAxel Dörfler 	  if (isupper (info->spec))
2995af32e75SAxel Dörfler 	    {
3005af32e75SAxel Dörfler 	      special = "NAN";
3015af32e75SAxel Dörfler 	      wspecial = L"NAN";
3025af32e75SAxel Dörfler 	    }
3035af32e75SAxel Dörfler 	  else
3045af32e75SAxel Dörfler 	    {
3055af32e75SAxel Dörfler 	      special = "nan";
3065af32e75SAxel Dörfler 	      wspecial = L"nan";
3075af32e75SAxel Dörfler 	    }
3085af32e75SAxel Dörfler 	  negative = 0;
3095af32e75SAxel Dörfler 	}
3105af32e75SAxel Dörfler       else
3115af32e75SAxel Dörfler 	{
312614858a9SAlexander von Gluck IV 	  if (isinf (fpnum.dbl.d))
3135af32e75SAxel Dörfler 	    {
3145af32e75SAxel Dörfler 	      if (isupper (info->spec))
3155af32e75SAxel Dörfler 		{
3165af32e75SAxel Dörfler 		  special = "INF";
3175af32e75SAxel Dörfler 		  wspecial = L"INF";
3185af32e75SAxel Dörfler 		}
3195af32e75SAxel Dörfler 	      else
3205af32e75SAxel Dörfler 		{
3215af32e75SAxel Dörfler 		  special = "inf";
3225af32e75SAxel Dörfler 		  wspecial = L"inf";
3235af32e75SAxel Dörfler 		}
3245af32e75SAxel Dörfler 	    }
3255af32e75SAxel Dörfler 
3265af32e75SAxel Dörfler 	  negative = signbit (fpnum.dbl.d);
3275af32e75SAxel Dörfler 	}
3285af32e75SAxel Dörfler     }
3295af32e75SAxel Dörfler 
3305af32e75SAxel Dörfler   if (special)
3315af32e75SAxel Dörfler     {
3325af32e75SAxel Dörfler       int width = info->width;
3335af32e75SAxel Dörfler 
3345af32e75SAxel Dörfler       if (negative || info->showsign || info->space)
3355af32e75SAxel Dörfler 	--width;
3365af32e75SAxel Dörfler       width -= 3;
3375af32e75SAxel Dörfler 
3385af32e75SAxel Dörfler       if (!info->left && width > 0)
3395af32e75SAxel Dörfler 	PADN (' ', width);
3405af32e75SAxel Dörfler 
3415af32e75SAxel Dörfler       if (negative)
3425af32e75SAxel Dörfler 	outchar ('-');
3435af32e75SAxel Dörfler       else if (info->showsign)
3445af32e75SAxel Dörfler 	outchar ('+');
3455af32e75SAxel Dörfler       else if (info->space)
3465af32e75SAxel Dörfler 	outchar (' ');
3475af32e75SAxel Dörfler 
3485af32e75SAxel Dörfler       PRINT (special, wspecial, 3);
3495af32e75SAxel Dörfler 
3505af32e75SAxel Dörfler       if (info->left && width > 0)
3515af32e75SAxel Dörfler 	PADN (' ', width);
3525af32e75SAxel Dörfler 
3535af32e75SAxel Dörfler       return done;
3545af32e75SAxel Dörfler     }
3555af32e75SAxel Dörfler 
3565af32e75SAxel Dörfler   if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
3575af32e75SAxel Dörfler     {
3585af32e75SAxel Dörfler       /* We have 52 bits of mantissa plus one implicit digit.  Since
3595af32e75SAxel Dörfler 	 52 bits are representable without rest using hexadecimal
3605af32e75SAxel Dörfler 	 digits we use only the implicit digits for the number before
3615af32e75SAxel Dörfler 	 the decimal point.  */
3625af32e75SAxel Dörfler       unsigned long long int num;
3635af32e75SAxel Dörfler 
3645af32e75SAxel Dörfler       num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
3655af32e75SAxel Dörfler 	     | fpnum.dbl.ieee.mantissa1);
3665af32e75SAxel Dörfler 
3675af32e75SAxel Dörfler       zero_mantissa = num == 0;
3685af32e75SAxel Dörfler 
3695af32e75SAxel Dörfler       if (sizeof (unsigned long int) > 6)
3705af32e75SAxel Dörfler 	{
3715af32e75SAxel Dörfler 	  wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
3725af32e75SAxel Dörfler 				 info->spec == 'A');
3735af32e75SAxel Dörfler 	  numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
3745af32e75SAxel Dörfler 			       info->spec == 'A');
3755af32e75SAxel Dörfler 	}
3765af32e75SAxel Dörfler       else
3775af32e75SAxel Dörfler 	{
3785af32e75SAxel Dörfler 	  wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
3795af32e75SAxel Dörfler 			    info->spec == 'A');
3805af32e75SAxel Dörfler 	  numstr = _itoa (num, numbuf + sizeof numbuf, 16,
3815af32e75SAxel Dörfler 			  info->spec == 'A');
3825af32e75SAxel Dörfler 	}
3835af32e75SAxel Dörfler 
3845af32e75SAxel Dörfler       /* Fill with zeroes.  */
3855af32e75SAxel Dörfler       while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
3865af32e75SAxel Dörfler 	{
3875af32e75SAxel Dörfler 	  *--wnumstr = L'0';
3885af32e75SAxel Dörfler 	  *--numstr = '0';
3895af32e75SAxel Dörfler 	}
3905af32e75SAxel Dörfler 
3915af32e75SAxel Dörfler       leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
3925af32e75SAxel Dörfler 
3935af32e75SAxel Dörfler       exponent = fpnum.dbl.ieee.exponent;
3945af32e75SAxel Dörfler 
3955af32e75SAxel Dörfler       if (exponent == 0)
3965af32e75SAxel Dörfler 	{
3975af32e75SAxel Dörfler 	  if (zero_mantissa)
3985af32e75SAxel Dörfler 	    expnegative = 0;
3995af32e75SAxel Dörfler 	  else
4005af32e75SAxel Dörfler 	    {
4015af32e75SAxel Dörfler 	      /* This is a denormalized number.  */
4025af32e75SAxel Dörfler 	      expnegative = 1;
4035af32e75SAxel Dörfler 	      exponent = IEEE754_DOUBLE_BIAS - 1;
4045af32e75SAxel Dörfler 	    }
4055af32e75SAxel Dörfler 	}
4065af32e75SAxel Dörfler       else if (exponent >= IEEE754_DOUBLE_BIAS)
4075af32e75SAxel Dörfler 	{
4085af32e75SAxel Dörfler 	  expnegative = 0;
4095af32e75SAxel Dörfler 	  exponent -= IEEE754_DOUBLE_BIAS;
4105af32e75SAxel Dörfler 	}
4115af32e75SAxel Dörfler       else
4125af32e75SAxel Dörfler 	{
4135af32e75SAxel Dörfler 	  expnegative = 1;
4145af32e75SAxel Dörfler 	  exponent = -(exponent - IEEE754_DOUBLE_BIAS);
4155af32e75SAxel Dörfler 	}
4165af32e75SAxel Dörfler     }
4175af32e75SAxel Dörfler #ifdef PRINT_FPHEX_LONG_DOUBLE
4185af32e75SAxel Dörfler   else
4195af32e75SAxel Dörfler     PRINT_FPHEX_LONG_DOUBLE;
4205af32e75SAxel Dörfler #endif
4215af32e75SAxel Dörfler 
4225af32e75SAxel Dörfler   /* Look for trailing zeroes.  */
4235af32e75SAxel Dörfler   if (! zero_mantissa)
4245af32e75SAxel Dörfler     {
425294818c5SAlex Smith       wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
426294818c5SAlex Smith       numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
4275af32e75SAxel Dörfler       while (wnumend[-1] == L'0')
4285af32e75SAxel Dörfler 	{
4295af32e75SAxel Dörfler 	  --wnumend;
4305af32e75SAxel Dörfler 	  --numend;
4315af32e75SAxel Dörfler 	}
4325af32e75SAxel Dörfler 
4335af32e75SAxel Dörfler       if (precision == -1)
4345af32e75SAxel Dörfler 	precision = numend - numstr;
4355af32e75SAxel Dörfler       else if (precision < numend - numstr
4365af32e75SAxel Dörfler 	       && (numstr[precision] > '8'
4375af32e75SAxel Dörfler 		   || (('A' < '0' || 'a' < '0')
4385af32e75SAxel Dörfler 		       && numstr[precision] < '0')
4395af32e75SAxel Dörfler 		   || (numstr[precision] == '8'
4405af32e75SAxel Dörfler 		       && (precision + 1 < numend - numstr
4415af32e75SAxel Dörfler 			   /* Round to even.  */
4425af32e75SAxel Dörfler 			   || (precision > 0
4435af32e75SAxel Dörfler 			       && ((numstr[precision - 1] & 1)
4445af32e75SAxel Dörfler 				   ^ (isdigit (numstr[precision - 1]) == 0)))
4455af32e75SAxel Dörfler 			   || (precision == 0
4465af32e75SAxel Dörfler 			       && ((leading & 1)
4475af32e75SAxel Dörfler 				   ^ (isdigit (leading) == 0)))))))
4485af32e75SAxel Dörfler 	{
4495af32e75SAxel Dörfler 	  /* Round up.  */
4505af32e75SAxel Dörfler 	  int cnt = precision;
4515af32e75SAxel Dörfler 	  while (--cnt >= 0)
4525af32e75SAxel Dörfler 	    {
4535af32e75SAxel Dörfler 	      char ch = numstr[cnt];
4545af32e75SAxel Dörfler 	      /* We assume that the digits and the letters are ordered
4555af32e75SAxel Dörfler 		 like in ASCII.  This is true for the rest of GNU, too.  */
4565af32e75SAxel Dörfler 	      if (ch == '9')
4575af32e75SAxel Dörfler 		{
4585af32e75SAxel Dörfler 		  wnumstr[cnt] = (wchar_t) info->spec;
4595af32e75SAxel Dörfler 		  numstr[cnt] = info->spec;	/* This is tricky,
4605af32e75SAxel Dörfler 		  				   think about it!  */
4615af32e75SAxel Dörfler 		  break;
4625af32e75SAxel Dörfler 		}
4635af32e75SAxel Dörfler 	      else if (tolower (ch) < 'f')
4645af32e75SAxel Dörfler 		{
4655af32e75SAxel Dörfler 		  ++numstr[cnt];
4665af32e75SAxel Dörfler 		  ++wnumstr[cnt];
4675af32e75SAxel Dörfler 		  break;
4685af32e75SAxel Dörfler 		}
4695af32e75SAxel Dörfler 	      else
4705af32e75SAxel Dörfler 		{
4715af32e75SAxel Dörfler 		  numstr[cnt] = '0';
4725af32e75SAxel Dörfler 		  wnumstr[cnt] = L'0';
4735af32e75SAxel Dörfler 		}
4745af32e75SAxel Dörfler 	    }
4755af32e75SAxel Dörfler 	  if (cnt < 0)
4765af32e75SAxel Dörfler 	    {
4775af32e75SAxel Dörfler 	      /* The mantissa so far was fff...f  Now increment the
4785af32e75SAxel Dörfler 		 leading digit.  Here it is again possible that we
4795af32e75SAxel Dörfler 		 get an overflow.  */
4805af32e75SAxel Dörfler 	      if (leading == '9')
4815af32e75SAxel Dörfler 		leading = info->spec;
4825af32e75SAxel Dörfler 	      else if (tolower (leading) < 'f')
4835af32e75SAxel Dörfler 		++leading;
4845af32e75SAxel Dörfler 	      else
4855af32e75SAxel Dörfler 		{
486294818c5SAlex Smith 		  leading = '1';
4875af32e75SAxel Dörfler 		  if (expnegative)
4885af32e75SAxel Dörfler 		    {
489294818c5SAlex Smith 		      exponent -= 4;
490294818c5SAlex Smith 		      if (exponent <= 0)
491294818c5SAlex Smith 			{
492294818c5SAlex Smith 			  exponent = -exponent;
4935af32e75SAxel Dörfler 			  expnegative = 0;
4945af32e75SAxel Dörfler 			}
495294818c5SAlex Smith 		    }
4965af32e75SAxel Dörfler 		  else
4975af32e75SAxel Dörfler 		    exponent += 4;
4985af32e75SAxel Dörfler 		}
4995af32e75SAxel Dörfler 	    }
5005af32e75SAxel Dörfler 	}
5015af32e75SAxel Dörfler     }
5025af32e75SAxel Dörfler   else
5035af32e75SAxel Dörfler     {
5045af32e75SAxel Dörfler       if (precision == -1)
5055af32e75SAxel Dörfler 	precision = 0;
5065af32e75SAxel Dörfler       numend = numstr;
5075af32e75SAxel Dörfler       wnumend = wnumstr;
5085af32e75SAxel Dörfler     }
5095af32e75SAxel Dörfler 
5105af32e75SAxel Dörfler   /* Now we can compute the exponent string.  */
5115af32e75SAxel Dörfler   expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
5125af32e75SAxel Dörfler   wexpstr = _itowa_word (exponent,
5135af32e75SAxel Dörfler 			 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
5145af32e75SAxel Dörfler 
5155af32e75SAxel Dörfler   /* Now we have all information to compute the size.  */
5165af32e75SAxel Dörfler   width -= ((negative || info->showsign || info->space)
5175af32e75SAxel Dörfler 	    /* Sign.  */
5185af32e75SAxel Dörfler 	    + 2    + 1 + 0 + precision + 1 + 1
5195af32e75SAxel Dörfler 	    /* 0x    h   .   hhh         P   ExpoSign.  */
5205af32e75SAxel Dörfler 	    + ((expbuf + sizeof expbuf) - expstr));
5215af32e75SAxel Dörfler 	    /* Exponent.  */
5225af32e75SAxel Dörfler 
523294818c5SAlex Smith   /* Count the decimal point.
524294818c5SAlex Smith      A special case when the mantissa or the precision is zero and the `#'
525294818c5SAlex Smith      is not given.  In this case we must not print the decimal point.  */
5265af32e75SAxel Dörfler   if (precision > 0 || info->alt)
5275af32e75SAxel Dörfler     width -= wide ? 1 : strlen (decimal);
5285af32e75SAxel Dörfler 
529294818c5SAlex Smith   if (!info->left && info->pad != '0' && width > 0)
5305af32e75SAxel Dörfler     PADN (' ', width);
5315af32e75SAxel Dörfler 
5325af32e75SAxel Dörfler   if (negative)
5335af32e75SAxel Dörfler     outchar ('-');
5345af32e75SAxel Dörfler   else if (info->showsign)
5355af32e75SAxel Dörfler     outchar ('+');
5365af32e75SAxel Dörfler   else if (info->space)
5375af32e75SAxel Dörfler     outchar (' ');
5385af32e75SAxel Dörfler 
5395af32e75SAxel Dörfler   outchar ('0');
5405af32e75SAxel Dörfler   if ('X' - 'A' == 'x' - 'a')
5415af32e75SAxel Dörfler     outchar (info->spec + ('x' - 'a'));
5425af32e75SAxel Dörfler   else
5435af32e75SAxel Dörfler     outchar (info->spec == 'A' ? 'X' : 'x');
544294818c5SAlex Smith 
545294818c5SAlex Smith   if (!info->left && info->pad == '0' && width > 0)
546294818c5SAlex Smith     PADN ('0', width);
547294818c5SAlex Smith 
5485af32e75SAxel Dörfler   outchar (leading);
5495af32e75SAxel Dörfler 
5505af32e75SAxel Dörfler   if (precision > 0 || info->alt)
5515af32e75SAxel Dörfler     {
5525af32e75SAxel Dörfler       const wchar_t *wtmp = &decimalwc;
5535af32e75SAxel Dörfler       PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
5545af32e75SAxel Dörfler     }
5555af32e75SAxel Dörfler 
5565af32e75SAxel Dörfler   if (precision > 0)
5575af32e75SAxel Dörfler     {
5585af32e75SAxel Dörfler       ssize_t tofill = precision - (numend - numstr);
5595af32e75SAxel Dörfler       PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
5605af32e75SAxel Dörfler       if (tofill > 0)
5615af32e75SAxel Dörfler 	PADN ('0', tofill);
5625af32e75SAxel Dörfler     }
5635af32e75SAxel Dörfler 
5645af32e75SAxel Dörfler   if ('P' - 'A' == 'p' - 'a')
5655af32e75SAxel Dörfler     outchar (info->spec + ('p' - 'a'));
5665af32e75SAxel Dörfler   else
5675af32e75SAxel Dörfler     outchar (info->spec == 'A' ? 'P' : 'p');
5685af32e75SAxel Dörfler 
5695af32e75SAxel Dörfler   outchar (expnegative ? '-' : '+');
5705af32e75SAxel Dörfler 
5715af32e75SAxel Dörfler   PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
5725af32e75SAxel Dörfler 
5735af32e75SAxel Dörfler   if (info->left && info->pad != '0' && width > 0)
5745af32e75SAxel Dörfler     PADN (info->pad, width);
5755af32e75SAxel Dörfler 
5765af32e75SAxel Dörfler   return done;
5775af32e75SAxel Dörfler }
578