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