Fix typo in nscd/selinux.c
[glibc.git] / stdio-common / printf_fphex.c
blob4599867b3fbdf374b0f7bc67be56f16855dc9e55
1 /* Print floating point number in hexadecimal notation according to ISO C99.
2 Copyright (C) 1997-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
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.
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.
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/>. */
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>
34 /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
35 #include <assert.h>
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
50 /* Macros for doing the actual output. */
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)
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)
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)
82 #ifndef MIN
83 # define MIN(a,b) ((a)<(b)?(a):(b))
84 #endif
87 int
88 __printf_fphex (FILE *fp,
89 const struct printf_info *info,
90 const void *const *args)
92 /* The floating-point value to output. */
93 union
95 union ieee754_double dbl;
96 long double ldbl;
98 fpnum;
100 /* Locale-dependent representation of decimal point. */
101 const char *decimal;
102 wchar_t decimalwc;
104 /* "NaN" or "Inf" for the special cases. */
105 const char *special = NULL;
106 const wchar_t *wspecial = NULL;
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;
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;
126 /* Non-zero is mantissa is zero. */
127 int zero_mantissa;
129 /* The leading digit before the decimal point. */
130 char leading;
132 /* Precision. */
133 int precision = info->prec;
135 /* Width. */
136 int width = info->width;
138 /* Number of characters written. */
139 int done = 0;
141 /* Nonzero if this is output on a wide character stream. */
142 int wide = info->wide;
145 /* Figure out the decimal point character. */
146 if (info->extra == 0)
148 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
149 decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
151 else
153 decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
154 decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
155 _NL_MONETARY_DECIMAL_POINT_WC);
157 /* The decimal point character must never be zero. */
158 assert (*decimal != '\0' && decimalwc != L'\0');
161 /* Fetch the argument value. */
162 #ifndef __NO_LONG_DOUBLE_MATH
163 if (info->is_long_double && sizeof (long double) > sizeof (double))
165 fpnum.ldbl = *(const long double *) args[0];
167 /* Check for special values: not a number or infinity. */
168 if (__isnanl (fpnum.ldbl))
170 if (isupper (info->spec))
172 special = "NAN";
173 wspecial = L"NAN";
175 else
177 special = "nan";
178 wspecial = L"nan";
181 else
183 if (__isinfl (fpnum.ldbl))
185 if (isupper (info->spec))
187 special = "INF";
188 wspecial = L"INF";
190 else
192 special = "inf";
193 wspecial = L"inf";
197 negative = signbit (fpnum.ldbl);
199 else
200 #endif /* no long double */
202 fpnum.dbl.d = *(const double *) args[0];
204 /* Check for special values: not a number or infinity. */
205 if (__isnan (fpnum.dbl.d))
207 negative = fpnum.dbl.ieee.negative != 0;
208 if (isupper (info->spec))
210 special = "NAN";
211 wspecial = L"NAN";
213 else
215 special = "nan";
216 wspecial = L"nan";
219 else
221 int res = __isinf (fpnum.dbl.d);
222 if (res)
224 if (isupper (info->spec))
226 special = "INF";
227 wspecial = L"INF";
229 else
231 special = "inf";
232 wspecial = L"inf";
234 negative = res < 0;
236 else
237 negative = signbit (fpnum.dbl.d);
241 if (special)
243 int width = info->width;
245 if (negative || info->showsign || info->space)
246 --width;
247 width -= 3;
249 if (!info->left && width > 0)
250 PADN (' ', width);
252 if (negative)
253 outchar ('-');
254 else if (info->showsign)
255 outchar ('+');
256 else if (info->space)
257 outchar (' ');
259 PRINT (special, wspecial, 3);
261 if (info->left && width > 0)
262 PADN (' ', width);
264 return done;
267 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
269 /* We have 52 bits of mantissa plus one implicit digit. Since
270 52 bits are representable without rest using hexadecimal
271 digits we use only the implicit digits for the number before
272 the decimal point. */
273 unsigned long long int num;
275 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
276 | fpnum.dbl.ieee.mantissa1);
278 zero_mantissa = num == 0;
280 if (sizeof (unsigned long int) > 6)
282 wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
283 info->spec == 'A');
284 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
285 info->spec == 'A');
287 else
289 wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
290 info->spec == 'A');
291 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
292 info->spec == 'A');
295 /* Fill with zeroes. */
296 while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
298 *--wnumstr = L'0';
299 *--numstr = '0';
302 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
304 exponent = fpnum.dbl.ieee.exponent;
306 if (exponent == 0)
308 if (zero_mantissa)
309 expnegative = 0;
310 else
312 /* This is a denormalized number. */
313 expnegative = 1;
314 exponent = IEEE754_DOUBLE_BIAS - 1;
317 else if (exponent >= IEEE754_DOUBLE_BIAS)
319 expnegative = 0;
320 exponent -= IEEE754_DOUBLE_BIAS;
322 else
324 expnegative = 1;
325 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
328 #ifdef PRINT_FPHEX_LONG_DOUBLE
329 else
330 PRINT_FPHEX_LONG_DOUBLE;
331 #endif
333 /* Look for trailing zeroes. */
334 if (! zero_mantissa)
336 wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
337 numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
338 while (wnumend[-1] == L'0')
340 --wnumend;
341 --numend;
344 bool do_round_away = false;
346 if (precision != -1 && precision < numend - numstr)
348 char last_digit = precision > 0 ? numstr[precision - 1] : leading;
349 char next_digit = numstr[precision];
350 int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
351 ? last_digit - 'A' + 10
352 : (last_digit >= 'a' && last_digit <= 'f'
353 ? last_digit - 'a' + 10
354 : last_digit - '0'));
355 int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
356 ? next_digit - 'A' + 10
357 : (next_digit >= 'a' && next_digit <= 'f'
358 ? next_digit - 'a' + 10
359 : next_digit - '0'));
360 bool more_bits = ((next_digit_value & 7) != 0
361 || precision + 1 < numend - numstr);
362 int rounding_mode = get_rounding_mode ();
363 do_round_away = round_away (negative, last_digit_value & 1,
364 next_digit_value >= 8, more_bits,
365 rounding_mode);
368 if (precision == -1)
369 precision = numend - numstr;
370 else if (do_round_away)
372 /* Round up. */
373 int cnt = precision;
374 while (--cnt >= 0)
376 char ch = numstr[cnt];
377 /* We assume that the digits and the letters are ordered
378 like in ASCII. This is true for the rest of GNU, too. */
379 if (ch == '9')
381 wnumstr[cnt] = (wchar_t) info->spec;
382 numstr[cnt] = info->spec; /* This is tricky,
383 think about it! */
384 break;
386 else if (tolower (ch) < 'f')
388 ++numstr[cnt];
389 ++wnumstr[cnt];
390 break;
392 else
394 numstr[cnt] = '0';
395 wnumstr[cnt] = L'0';
398 if (cnt < 0)
400 /* The mantissa so far was fff...f Now increment the
401 leading digit. Here it is again possible that we
402 get an overflow. */
403 if (leading == '9')
404 leading = info->spec;
405 else if (tolower (leading) < 'f')
406 ++leading;
407 else
409 leading = '1';
410 if (expnegative)
412 exponent -= 4;
413 if (exponent <= 0)
415 exponent = -exponent;
416 expnegative = 0;
419 else
420 exponent += 4;
425 else
427 if (precision == -1)
428 precision = 0;
429 numend = numstr;
430 wnumend = wnumstr;
433 /* Now we can compute the exponent string. */
434 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
435 wexpstr = _itowa_word (exponent,
436 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
438 /* Now we have all information to compute the size. */
439 width -= ((negative || info->showsign || info->space)
440 /* Sign. */
441 + 2 + 1 + 0 + precision + 1 + 1
442 /* 0x h . hhh P ExpoSign. */
443 + ((expbuf + sizeof expbuf) - expstr));
444 /* Exponent. */
446 /* Count the decimal point.
447 A special case when the mantissa or the precision is zero and the `#'
448 is not given. In this case we must not print the decimal point. */
449 if (precision > 0 || info->alt)
450 width -= wide ? 1 : strlen (decimal);
452 if (!info->left && info->pad != '0' && width > 0)
453 PADN (' ', width);
455 if (negative)
456 outchar ('-');
457 else if (info->showsign)
458 outchar ('+');
459 else if (info->space)
460 outchar (' ');
462 outchar ('0');
463 if ('X' - 'A' == 'x' - 'a')
464 outchar (info->spec + ('x' - 'a'));
465 else
466 outchar (info->spec == 'A' ? 'X' : 'x');
468 if (!info->left && info->pad == '0' && width > 0)
469 PADN ('0', width);
471 outchar (leading);
473 if (precision > 0 || info->alt)
475 const wchar_t *wtmp = &decimalwc;
476 PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
479 if (precision > 0)
481 ssize_t tofill = precision - (numend - numstr);
482 PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
483 if (tofill > 0)
484 PADN ('0', tofill);
487 if ('P' - 'A' == 'p' - 'a')
488 outchar (info->spec + ('p' - 'a'));
489 else
490 outchar (info->spec == 'A' ? 'P' : 'p');
492 outchar (expnegative ? '-' : '+');
494 PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
496 if (info->left && info->pad != '0' && width > 0)
497 PADN (info->pad, width);
499 return done;