xref: /netbsd-src/external/gpl3/gcc.old/dist/libquadmath/printf/printf_fphex.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1*627f7eb2Smrg /* Print floating point number in hexadecimal notation according to ISO C99.
2*627f7eb2Smrg    Copyright (C) 1997-2012 Free Software Foundation, Inc.
3*627f7eb2Smrg    This file is part of the GNU C Library.
4*627f7eb2Smrg    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5*627f7eb2Smrg 
6*627f7eb2Smrg    The GNU C Library is free software; you can redistribute it and/or
7*627f7eb2Smrg    modify it under the terms of the GNU Lesser General Public
8*627f7eb2Smrg    License as published by the Free Software Foundation; either
9*627f7eb2Smrg    version 2.1 of the License, or (at your option) any later version.
10*627f7eb2Smrg 
11*627f7eb2Smrg    The GNU C Library is distributed in the hope that it will be useful,
12*627f7eb2Smrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*627f7eb2Smrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*627f7eb2Smrg    Lesser General Public License for more details.
15*627f7eb2Smrg 
16*627f7eb2Smrg    You should have received a copy of the GNU Lesser General Public
17*627f7eb2Smrg    License along with the GNU C Library; if not, see
18*627f7eb2Smrg    <http://www.gnu.org/licenses/>.  */
19*627f7eb2Smrg 
20*627f7eb2Smrg #include <config.h>
21*627f7eb2Smrg #include <math.h>
22*627f7eb2Smrg #include <stdlib.h>
23*627f7eb2Smrg #include <stdio.h>
24*627f7eb2Smrg #include <string.h>
25*627f7eb2Smrg #include <stdbool.h>
26*627f7eb2Smrg #define NDEBUG
27*627f7eb2Smrg #include <assert.h>
28*627f7eb2Smrg #include "quadmath-rounding-mode.h"
29*627f7eb2Smrg #include "quadmath-printf.h"
30*627f7eb2Smrg #include "_itoa.h"
31*627f7eb2Smrg #include "_itowa.h"
32*627f7eb2Smrg 
33*627f7eb2Smrg 
34*627f7eb2Smrg /* Macros for doing the actual output.  */
35*627f7eb2Smrg 
36*627f7eb2Smrg #define outchar(ch)							      \
37*627f7eb2Smrg   do									      \
38*627f7eb2Smrg     {									      \
39*627f7eb2Smrg       register const int outc = (ch);					      \
40*627f7eb2Smrg       if (PUTC (outc, fp) == EOF)					      \
41*627f7eb2Smrg 	return -1;							      \
42*627f7eb2Smrg       ++done;								      \
43*627f7eb2Smrg     } while (0)
44*627f7eb2Smrg 
45*627f7eb2Smrg #define PRINT(ptr, wptr, len)						      \
46*627f7eb2Smrg   do									      \
47*627f7eb2Smrg     {									      \
48*627f7eb2Smrg       register size_t outlen = (len);					      \
49*627f7eb2Smrg       if (wide)								      \
50*627f7eb2Smrg 	while (outlen-- > 0)						      \
51*627f7eb2Smrg 	  outchar (*wptr++);						      \
52*627f7eb2Smrg       else								      \
53*627f7eb2Smrg 	while (outlen-- > 0)						      \
54*627f7eb2Smrg 	  outchar (*ptr++);						      \
55*627f7eb2Smrg     } while (0)
56*627f7eb2Smrg 
57*627f7eb2Smrg #define PADN(ch, len)							      \
58*627f7eb2Smrg   do									      \
59*627f7eb2Smrg     {									      \
60*627f7eb2Smrg       if (PAD (fp, ch, len) != len)					      \
61*627f7eb2Smrg 	return -1;							      \
62*627f7eb2Smrg       done += len;							      \
63*627f7eb2Smrg     }									      \
64*627f7eb2Smrg   while (0)
65*627f7eb2Smrg 
66*627f7eb2Smrg 
67*627f7eb2Smrg 
68*627f7eb2Smrg int
__quadmath_printf_fphex(struct __quadmath_printf_file * fp,const struct printf_info * info,const void * const * args)69*627f7eb2Smrg __quadmath_printf_fphex (struct __quadmath_printf_file *fp,
70*627f7eb2Smrg 			 const struct printf_info *info,
71*627f7eb2Smrg 			 const void *const *args)
72*627f7eb2Smrg {
73*627f7eb2Smrg   /* The floating-point value to output.  */
74*627f7eb2Smrg   ieee854_float128 fpnum;
75*627f7eb2Smrg 
76*627f7eb2Smrg   /* Locale-dependent representation of decimal point.	*/
77*627f7eb2Smrg   const char *decimal;
78*627f7eb2Smrg   wchar_t decimalwc;
79*627f7eb2Smrg 
80*627f7eb2Smrg   /* "NaN" or "Inf" for the special cases.  */
81*627f7eb2Smrg   const char *special = NULL;
82*627f7eb2Smrg   const wchar_t *wspecial = NULL;
83*627f7eb2Smrg 
84*627f7eb2Smrg   /* Buffer for the generated number string for the mantissa.  The
85*627f7eb2Smrg      maximal size for the mantissa is 128 bits.  */
86*627f7eb2Smrg   char numbuf[32];
87*627f7eb2Smrg   char *numstr;
88*627f7eb2Smrg   char *numend;
89*627f7eb2Smrg   wchar_t wnumbuf[32];
90*627f7eb2Smrg   wchar_t *wnumstr;
91*627f7eb2Smrg   wchar_t *wnumend;
92*627f7eb2Smrg   int negative;
93*627f7eb2Smrg 
94*627f7eb2Smrg   /* The maximal exponent of two in decimal notation has 5 digits.  */
95*627f7eb2Smrg   char expbuf[5];
96*627f7eb2Smrg   char *expstr;
97*627f7eb2Smrg   wchar_t wexpbuf[5];
98*627f7eb2Smrg   wchar_t *wexpstr;
99*627f7eb2Smrg   int expnegative;
100*627f7eb2Smrg   int exponent;
101*627f7eb2Smrg 
102*627f7eb2Smrg   /* Non-zero is mantissa is zero.  */
103*627f7eb2Smrg   int zero_mantissa;
104*627f7eb2Smrg 
105*627f7eb2Smrg   /* The leading digit before the decimal point.  */
106*627f7eb2Smrg   char leading;
107*627f7eb2Smrg 
108*627f7eb2Smrg   /* Precision.  */
109*627f7eb2Smrg   int precision = info->prec;
110*627f7eb2Smrg 
111*627f7eb2Smrg   /* Width.  */
112*627f7eb2Smrg   int width = info->width;
113*627f7eb2Smrg 
114*627f7eb2Smrg   /* Number of characters written.  */
115*627f7eb2Smrg   int done = 0;
116*627f7eb2Smrg 
117*627f7eb2Smrg   /* Nonzero if this is output on a wide character stream.  */
118*627f7eb2Smrg   int wide = info->wide;
119*627f7eb2Smrg 
120*627f7eb2Smrg   bool do_round_away;
121*627f7eb2Smrg 
122*627f7eb2Smrg   /* Figure out the decimal point character.  */
123*627f7eb2Smrg #ifdef USE_NL_LANGINFO
124*627f7eb2Smrg   if (info->extra == 0)
125*627f7eb2Smrg     decimal = nl_langinfo (DECIMAL_POINT);
126*627f7eb2Smrg   else
127*627f7eb2Smrg     {
128*627f7eb2Smrg       decimal = nl_langinfo (MON_DECIMAL_POINT);
129*627f7eb2Smrg       if (*decimal == '\0')
130*627f7eb2Smrg 	decimal = nl_langinfo (DECIMAL_POINT);
131*627f7eb2Smrg     }
132*627f7eb2Smrg   /* The decimal point character must never be zero.  */
133*627f7eb2Smrg   assert (*decimal != '\0');
134*627f7eb2Smrg #elif defined USE_LOCALECONV
135*627f7eb2Smrg   const struct lconv *lc = localeconv ();
136*627f7eb2Smrg   if (info->extra == 0)
137*627f7eb2Smrg     decimal = lc->decimal_point;
138*627f7eb2Smrg   else
139*627f7eb2Smrg     {
140*627f7eb2Smrg       decimal = lc->mon_decimal_point;
141*627f7eb2Smrg       if (decimal == NULL || *decimal == '\0')
142*627f7eb2Smrg 	decimal = lc->decimal_point;
143*627f7eb2Smrg     }
144*627f7eb2Smrg   if (decimal == NULL || *decimal == '\0')
145*627f7eb2Smrg     decimal = ".";
146*627f7eb2Smrg #else
147*627f7eb2Smrg   decimal = ".";
148*627f7eb2Smrg #endif
149*627f7eb2Smrg #ifdef USE_NL_LANGINFO_WC
150*627f7eb2Smrg   if (info->extra == 0)
151*627f7eb2Smrg     decimalwc = nl_langinfo_wc (_NL_NUMERIC_DECIMAL_POINT_WC);
152*627f7eb2Smrg   else
153*627f7eb2Smrg     {
154*627f7eb2Smrg       decimalwc = nl_langinfo_wc (_NL_MONETARY_DECIMAL_POINT_WC);
155*627f7eb2Smrg       if (decimalwc == L_('\0'))
156*627f7eb2Smrg 	decimalwc = nl_langinfo_wc (_NL_NUMERIC_DECIMAL_POINT_WC);
157*627f7eb2Smrg     }
158*627f7eb2Smrg   /* The decimal point character must never be zero.  */
159*627f7eb2Smrg   assert (decimalwc != L_('\0'));
160*627f7eb2Smrg #else
161*627f7eb2Smrg   decimalwc = L_('.');
162*627f7eb2Smrg #endif
163*627f7eb2Smrg 
164*627f7eb2Smrg   /* Fetch the argument value.	*/
165*627f7eb2Smrg     {
166*627f7eb2Smrg       fpnum.value = **(const __float128 **) args[0];
167*627f7eb2Smrg 
168*627f7eb2Smrg       /* Check for special values: not a number or infinity.  */
169*627f7eb2Smrg       if (isnanq (fpnum.value))
170*627f7eb2Smrg 	{
171*627f7eb2Smrg 	  negative = fpnum.ieee.negative != 0;
172*627f7eb2Smrg 	  if (isupper (info->spec))
173*627f7eb2Smrg 	    {
174*627f7eb2Smrg 	      special = "NAN";
175*627f7eb2Smrg 	      wspecial = L_("NAN");
176*627f7eb2Smrg 	    }
177*627f7eb2Smrg 	  else
178*627f7eb2Smrg 	    {
179*627f7eb2Smrg 	      special = "nan";
180*627f7eb2Smrg 	      wspecial = L_("nan");
181*627f7eb2Smrg 	    }
182*627f7eb2Smrg 	}
183*627f7eb2Smrg       else
184*627f7eb2Smrg 	{
185*627f7eb2Smrg 	  if (isinfq (fpnum.value))
186*627f7eb2Smrg 	    {
187*627f7eb2Smrg 	      if (isupper (info->spec))
188*627f7eb2Smrg 		{
189*627f7eb2Smrg 		  special = "INF";
190*627f7eb2Smrg 		  wspecial = L_("INF");
191*627f7eb2Smrg 		}
192*627f7eb2Smrg 	      else
193*627f7eb2Smrg 		{
194*627f7eb2Smrg 		  special = "inf";
195*627f7eb2Smrg 		  wspecial = L_("inf");
196*627f7eb2Smrg 		}
197*627f7eb2Smrg 	    }
198*627f7eb2Smrg 
199*627f7eb2Smrg 	  negative = signbitq (fpnum.value);
200*627f7eb2Smrg 	}
201*627f7eb2Smrg     }
202*627f7eb2Smrg 
203*627f7eb2Smrg   if (special)
204*627f7eb2Smrg     {
205*627f7eb2Smrg       int width = info->width;
206*627f7eb2Smrg 
207*627f7eb2Smrg       if (negative || info->showsign || info->space)
208*627f7eb2Smrg 	--width;
209*627f7eb2Smrg       width -= 3;
210*627f7eb2Smrg 
211*627f7eb2Smrg       if (!info->left && width > 0)
212*627f7eb2Smrg 	PADN (' ', width);
213*627f7eb2Smrg 
214*627f7eb2Smrg       if (negative)
215*627f7eb2Smrg 	outchar ('-');
216*627f7eb2Smrg       else if (info->showsign)
217*627f7eb2Smrg 	outchar ('+');
218*627f7eb2Smrg       else if (info->space)
219*627f7eb2Smrg 	outchar (' ');
220*627f7eb2Smrg 
221*627f7eb2Smrg       PRINT (special, wspecial, 3);
222*627f7eb2Smrg 
223*627f7eb2Smrg       if (info->left && width > 0)
224*627f7eb2Smrg 	PADN (' ', width);
225*627f7eb2Smrg 
226*627f7eb2Smrg       return done;
227*627f7eb2Smrg     }
228*627f7eb2Smrg 
229*627f7eb2Smrg     {
230*627f7eb2Smrg       /* We have 112 bits of mantissa plus one implicit digit.  Since
231*627f7eb2Smrg 	 112 bits are representable without rest using hexadecimal
232*627f7eb2Smrg 	 digits we use only the implicit digits for the number before
233*627f7eb2Smrg 	 the decimal point.  */
234*627f7eb2Smrg       uint64_t num0, num1;
235*627f7eb2Smrg 
236*627f7eb2Smrg       assert (sizeof (long double) == 16);
237*627f7eb2Smrg 
238*627f7eb2Smrg       num0 = (((unsigned long long int) fpnum.ieee.mantissa0) << 32
239*627f7eb2Smrg 	      | fpnum.ieee.mantissa1);
240*627f7eb2Smrg       num1 = (((unsigned long long int) fpnum.ieee.mantissa2) << 32
241*627f7eb2Smrg 	      | fpnum.ieee.mantissa3);
242*627f7eb2Smrg 
243*627f7eb2Smrg       zero_mantissa = (num0|num1) == 0;
244*627f7eb2Smrg 
245*627f7eb2Smrg       if (sizeof (unsigned long int) > 6)
246*627f7eb2Smrg 	{
247*627f7eb2Smrg 	  numstr = _itoa_word (num1, numbuf + sizeof numbuf, 16,
248*627f7eb2Smrg 			       info->spec == 'A');
249*627f7eb2Smrg 	  wnumstr = _itowa_word (num1,
250*627f7eb2Smrg 				 wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),
251*627f7eb2Smrg 				 16, info->spec == 'A');
252*627f7eb2Smrg 	}
253*627f7eb2Smrg       else
254*627f7eb2Smrg 	{
255*627f7eb2Smrg 	  numstr = _itoa (num1, numbuf + sizeof numbuf, 16,
256*627f7eb2Smrg 			  info->spec == 'A');
257*627f7eb2Smrg 	  wnumstr = _itowa (num1,
258*627f7eb2Smrg 			    wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),
259*627f7eb2Smrg 			    16, info->spec == 'A');
260*627f7eb2Smrg 	}
261*627f7eb2Smrg 
262*627f7eb2Smrg       while (numstr > numbuf + (sizeof numbuf - 64 / 4))
263*627f7eb2Smrg 	{
264*627f7eb2Smrg 	  *--numstr = '0';
265*627f7eb2Smrg 	  *--wnumstr = L_('0');
266*627f7eb2Smrg 	}
267*627f7eb2Smrg 
268*627f7eb2Smrg       if (sizeof (unsigned long int) > 6)
269*627f7eb2Smrg 	{
270*627f7eb2Smrg 	  numstr = _itoa_word (num0, numstr, 16, info->spec == 'A');
271*627f7eb2Smrg 	  wnumstr = _itowa_word (num0, wnumstr, 16, info->spec == 'A');
272*627f7eb2Smrg 	}
273*627f7eb2Smrg       else
274*627f7eb2Smrg 	{
275*627f7eb2Smrg 	  numstr = _itoa (num0, numstr, 16, info->spec == 'A');
276*627f7eb2Smrg 	  wnumstr = _itowa (num0, wnumstr, 16, info->spec == 'A');
277*627f7eb2Smrg 	}
278*627f7eb2Smrg 
279*627f7eb2Smrg       /* Fill with zeroes.  */
280*627f7eb2Smrg       while (numstr > numbuf + (sizeof numbuf - 112 / 4))
281*627f7eb2Smrg 	{
282*627f7eb2Smrg 	  *--wnumstr = L_('0');
283*627f7eb2Smrg 	  *--numstr = '0';
284*627f7eb2Smrg 	}
285*627f7eb2Smrg 
286*627f7eb2Smrg       leading = fpnum.ieee.exponent == 0 ? '0' : '1';
287*627f7eb2Smrg 
288*627f7eb2Smrg       exponent = fpnum.ieee.exponent;
289*627f7eb2Smrg 
290*627f7eb2Smrg       if (exponent == 0)
291*627f7eb2Smrg 	{
292*627f7eb2Smrg 	  if (zero_mantissa)
293*627f7eb2Smrg 	    expnegative = 0;
294*627f7eb2Smrg 	  else
295*627f7eb2Smrg 	    {
296*627f7eb2Smrg 	      /* This is a denormalized number.  */
297*627f7eb2Smrg 	      expnegative = 1;
298*627f7eb2Smrg 	      exponent = IEEE854_FLOAT128_BIAS - 1;
299*627f7eb2Smrg 	    }
300*627f7eb2Smrg 	}
301*627f7eb2Smrg       else if (exponent >= IEEE854_FLOAT128_BIAS)
302*627f7eb2Smrg 	{
303*627f7eb2Smrg 	  expnegative = 0;
304*627f7eb2Smrg 	  exponent -= IEEE854_FLOAT128_BIAS;
305*627f7eb2Smrg 	}
306*627f7eb2Smrg       else
307*627f7eb2Smrg 	{
308*627f7eb2Smrg 	  expnegative = 1;
309*627f7eb2Smrg 	  exponent = -(exponent - IEEE854_FLOAT128_BIAS);
310*627f7eb2Smrg 	}
311*627f7eb2Smrg     }
312*627f7eb2Smrg 
313*627f7eb2Smrg   /* Look for trailing zeroes.  */
314*627f7eb2Smrg   if (! zero_mantissa)
315*627f7eb2Smrg     {
316*627f7eb2Smrg       wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
317*627f7eb2Smrg       numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
318*627f7eb2Smrg       while (wnumend[-1] == L_('0'))
319*627f7eb2Smrg 	{
320*627f7eb2Smrg 	  --wnumend;
321*627f7eb2Smrg 	  --numend;
322*627f7eb2Smrg 	}
323*627f7eb2Smrg 
324*627f7eb2Smrg       do_round_away = false;
325*627f7eb2Smrg 
326*627f7eb2Smrg       if (precision != -1 && precision < numend - numstr)
327*627f7eb2Smrg 	{
328*627f7eb2Smrg 	  char last_digit = precision > 0 ? numstr[precision - 1] : leading;
329*627f7eb2Smrg 	  char next_digit = numstr[precision];
330*627f7eb2Smrg 	  int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
331*627f7eb2Smrg 				  ? last_digit - 'A' + 10
332*627f7eb2Smrg 				  : (last_digit >= 'a' && last_digit <= 'f'
333*627f7eb2Smrg 				     ? last_digit - 'a' + 10
334*627f7eb2Smrg 				     : last_digit - '0'));
335*627f7eb2Smrg 	  int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
336*627f7eb2Smrg 				  ? next_digit - 'A' + 10
337*627f7eb2Smrg 				  : (next_digit >= 'a' && next_digit <= 'f'
338*627f7eb2Smrg 				     ? next_digit - 'a' + 10
339*627f7eb2Smrg 				     : next_digit - '0'));
340*627f7eb2Smrg 	  bool more_bits = ((next_digit_value & 7) != 0
341*627f7eb2Smrg 			    || precision + 1 < numend - numstr);
342*627f7eb2Smrg #ifdef HAVE_FENV_H
343*627f7eb2Smrg 	  int rounding_mode = get_rounding_mode ();
344*627f7eb2Smrg 	  do_round_away = round_away (negative, last_digit_value & 1,
345*627f7eb2Smrg 				      next_digit_value >= 8, more_bits,
346*627f7eb2Smrg 				      rounding_mode);
347*627f7eb2Smrg #endif
348*627f7eb2Smrg 	}
349*627f7eb2Smrg 
350*627f7eb2Smrg       if (precision == -1)
351*627f7eb2Smrg 	precision = numend - numstr;
352*627f7eb2Smrg       else if (do_round_away)
353*627f7eb2Smrg 	{
354*627f7eb2Smrg 	  /* Round up.  */
355*627f7eb2Smrg 	  int cnt = precision;
356*627f7eb2Smrg 	  while (--cnt >= 0)
357*627f7eb2Smrg 	    {
358*627f7eb2Smrg 	      char ch = numstr[cnt];
359*627f7eb2Smrg 	      /* We assume that the digits and the letters are ordered
360*627f7eb2Smrg 		 like in ASCII.  This is true for the rest of GNU, too.  */
361*627f7eb2Smrg 	      if (ch == '9')
362*627f7eb2Smrg 		{
363*627f7eb2Smrg 		  wnumstr[cnt] = (wchar_t) info->spec;
364*627f7eb2Smrg 		  numstr[cnt] = info->spec;	/* This is tricky,
365*627f7eb2Smrg 		  				   think about it!  */
366*627f7eb2Smrg 		  break;
367*627f7eb2Smrg 		}
368*627f7eb2Smrg 	      else if (tolower (ch) < 'f')
369*627f7eb2Smrg 		{
370*627f7eb2Smrg 		  ++numstr[cnt];
371*627f7eb2Smrg 		  ++wnumstr[cnt];
372*627f7eb2Smrg 		  break;
373*627f7eb2Smrg 		}
374*627f7eb2Smrg 	      else
375*627f7eb2Smrg 		{
376*627f7eb2Smrg 		  numstr[cnt] = '0';
377*627f7eb2Smrg 		  wnumstr[cnt] = L_('0');
378*627f7eb2Smrg 		}
379*627f7eb2Smrg 	    }
380*627f7eb2Smrg 	  if (cnt < 0)
381*627f7eb2Smrg 	    {
382*627f7eb2Smrg 	      /* The mantissa so far was fff...f  Now increment the
383*627f7eb2Smrg 		 leading digit.  Here it is again possible that we
384*627f7eb2Smrg 		 get an overflow.  */
385*627f7eb2Smrg 	      if (leading == '9')
386*627f7eb2Smrg 		leading = info->spec;
387*627f7eb2Smrg 	      else if (tolower (leading) < 'f')
388*627f7eb2Smrg 		++leading;
389*627f7eb2Smrg 	      else
390*627f7eb2Smrg 		{
391*627f7eb2Smrg 		  leading = '1';
392*627f7eb2Smrg 		  if (expnegative)
393*627f7eb2Smrg 		    {
394*627f7eb2Smrg 		      exponent -= 4;
395*627f7eb2Smrg 		      if (exponent <= 0)
396*627f7eb2Smrg 			{
397*627f7eb2Smrg 			  exponent = -exponent;
398*627f7eb2Smrg 			  expnegative = 0;
399*627f7eb2Smrg 			}
400*627f7eb2Smrg 		    }
401*627f7eb2Smrg 		  else
402*627f7eb2Smrg 		    exponent += 4;
403*627f7eb2Smrg 		}
404*627f7eb2Smrg 	    }
405*627f7eb2Smrg 	}
406*627f7eb2Smrg     }
407*627f7eb2Smrg   else
408*627f7eb2Smrg     {
409*627f7eb2Smrg       if (precision == -1)
410*627f7eb2Smrg 	precision = 0;
411*627f7eb2Smrg       numend = numstr;
412*627f7eb2Smrg       wnumend = wnumstr;
413*627f7eb2Smrg     }
414*627f7eb2Smrg 
415*627f7eb2Smrg   /* Now we can compute the exponent string.  */
416*627f7eb2Smrg   expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
417*627f7eb2Smrg   wexpstr = _itowa_word (exponent,
418*627f7eb2Smrg 			 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
419*627f7eb2Smrg 
420*627f7eb2Smrg   /* Now we have all information to compute the size.  */
421*627f7eb2Smrg   width -= ((negative || info->showsign || info->space)
422*627f7eb2Smrg 	    /* Sign.  */
423*627f7eb2Smrg 	    + 2    + 1 + 0 + precision + 1 + 1
424*627f7eb2Smrg 	    /* 0x    h   .   hhh         P   ExpoSign.  */
425*627f7eb2Smrg 	    + ((expbuf + sizeof expbuf) - expstr));
426*627f7eb2Smrg 	    /* Exponent.  */
427*627f7eb2Smrg 
428*627f7eb2Smrg   /* Count the decimal point.
429*627f7eb2Smrg      A special case when the mantissa or the precision is zero and the `#'
430*627f7eb2Smrg      is not given.  In this case we must not print the decimal point.  */
431*627f7eb2Smrg   if (precision > 0 || info->alt)
432*627f7eb2Smrg     width -= wide ? 1 : strlen (decimal);
433*627f7eb2Smrg 
434*627f7eb2Smrg   if (!info->left && info->pad != '0' && width > 0)
435*627f7eb2Smrg     PADN (' ', width);
436*627f7eb2Smrg 
437*627f7eb2Smrg   if (negative)
438*627f7eb2Smrg     outchar ('-');
439*627f7eb2Smrg   else if (info->showsign)
440*627f7eb2Smrg     outchar ('+');
441*627f7eb2Smrg   else if (info->space)
442*627f7eb2Smrg     outchar (' ');
443*627f7eb2Smrg 
444*627f7eb2Smrg   outchar ('0');
445*627f7eb2Smrg   if ('X' - 'A' == 'x' - 'a')
446*627f7eb2Smrg     outchar (info->spec + ('x' - 'a'));
447*627f7eb2Smrg   else
448*627f7eb2Smrg     outchar (info->spec == 'A' ? 'X' : 'x');
449*627f7eb2Smrg 
450*627f7eb2Smrg   if (!info->left && info->pad == '0' && width > 0)
451*627f7eb2Smrg     PADN ('0', width);
452*627f7eb2Smrg 
453*627f7eb2Smrg   outchar (leading);
454*627f7eb2Smrg 
455*627f7eb2Smrg   if (precision > 0 || info->alt)
456*627f7eb2Smrg     {
457*627f7eb2Smrg       const wchar_t *wtmp = &decimalwc;
458*627f7eb2Smrg       PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
459*627f7eb2Smrg     }
460*627f7eb2Smrg 
461*627f7eb2Smrg   if (precision > 0)
462*627f7eb2Smrg     {
463*627f7eb2Smrg       ssize_t tofill = precision - (numend - numstr);
464*627f7eb2Smrg       PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
465*627f7eb2Smrg       if (tofill > 0)
466*627f7eb2Smrg 	PADN ('0', tofill);
467*627f7eb2Smrg     }
468*627f7eb2Smrg 
469*627f7eb2Smrg   if ('P' - 'A' == 'p' - 'a')
470*627f7eb2Smrg     outchar (info->spec + ('p' - 'a'));
471*627f7eb2Smrg   else
472*627f7eb2Smrg     outchar (info->spec == 'A' ? 'P' : 'p');
473*627f7eb2Smrg 
474*627f7eb2Smrg   outchar (expnegative ? '-' : '+');
475*627f7eb2Smrg 
476*627f7eb2Smrg   PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
477*627f7eb2Smrg 
478*627f7eb2Smrg   if (info->left && info->pad != '0' && width > 0)
479*627f7eb2Smrg     PADN (info->pad, width);
480*627f7eb2Smrg 
481*627f7eb2Smrg   return done;
482*627f7eb2Smrg }
483