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