Cleanup Linux sigqueue implementation
[glibc.git] / stdio-common / printf_fphex.c
blob938b0b32e0d52315fd3ac979f806c00f241122e8
1 /* Print floating point number in hexadecimal notation according to ISO C99.
2 Copyright (C) 1997-2017 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 <array_length.h>
21 #include <ctype.h>
22 #include <ieee754.h>
23 #include <math.h>
24 #include <printf.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <wchar.h>
29 #include <_itoa.h>
30 #include <_itowa.h>
31 #include <locale/localeinfo.h>
32 #include <stdbool.h>
33 #include <rounding-mode.h>
35 #if __HAVE_DISTINCT_FLOAT128
36 # include "ieee754_float128.h"
37 # include <ldbl-128/printf_fphex_macros.h>
38 # define PRINT_FPHEX_FLOAT128 \
39 PRINT_FPHEX (_Float128, fpnum.flt128, ieee854_float128, \
40 IEEE854_FLOAT128_BIAS)
41 #endif
43 /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
44 #include <assert.h>
46 /* This defines make it possible to use the same code for GNU C library and
47 the GNU I/O library. */
48 #include <libioP.h>
49 #define PUT(f, s, n) _IO_sputn (f, s, n)
50 #define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
51 /* We use this file GNU C library and GNU I/O library. So make
52 names equal. */
53 #undef putc
54 #define putc(c, f) (wide \
55 ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
56 #define size_t _IO_size_t
57 #define FILE _IO_FILE
59 /* Macros for doing the actual output. */
61 #define outchar(ch) \
62 do \
63 { \
64 const int outc = (ch); \
65 if (putc (outc, fp) == EOF) \
66 return -1; \
67 ++done; \
68 } while (0)
70 #define PRINT(ptr, wptr, len) \
71 do \
72 { \
73 size_t outlen = (len); \
74 if (wide) \
75 while (outlen-- > 0) \
76 outchar (*wptr++); \
77 else \
78 while (outlen-- > 0) \
79 outchar (*ptr++); \
80 } while (0)
82 #define PADN(ch, len) \
83 do \
84 { \
85 if (PAD (fp, ch, len) != len) \
86 return -1; \
87 done += len; \
88 } \
89 while (0)
91 #ifndef MIN
92 # define MIN(a,b) ((a)<(b)?(a):(b))
93 #endif
96 int
97 __printf_fphex (FILE *fp,
98 const struct printf_info *info,
99 const void *const *args)
101 /* The floating-point value to output. */
102 union
104 union ieee754_double dbl;
105 long double ldbl;
106 #if __HAVE_DISTINCT_FLOAT128
107 _Float128 flt128;
108 #endif
110 fpnum;
112 /* Locale-dependent representation of decimal point. */
113 const char *decimal;
114 wchar_t decimalwc;
116 /* "NaN" or "Inf" for the special cases. */
117 const char *special = NULL;
118 const wchar_t *wspecial = NULL;
120 /* Buffer for the generated number string for the mantissa. The
121 maximal size for the mantissa is 128 bits. */
122 char numbuf[32];
123 char *numstr;
124 char *numend;
125 wchar_t wnumbuf[32];
126 wchar_t *wnumstr;
127 wchar_t *wnumend;
128 int negative;
130 /* The maximal exponent of two in decimal notation has 5 digits. */
131 char expbuf[5];
132 char *expstr;
133 wchar_t wexpbuf[5];
134 wchar_t *wexpstr;
135 int expnegative;
136 int exponent;
138 /* Non-zero is mantissa is zero. */
139 int zero_mantissa;
141 /* The leading digit before the decimal point. */
142 char leading;
144 /* Precision. */
145 int precision = info->prec;
147 /* Width. */
148 int width = info->width;
150 /* Number of characters written. */
151 int done = 0;
153 /* Nonzero if this is output on a wide character stream. */
154 int wide = info->wide;
157 /* Figure out the decimal point character. */
158 if (info->extra == 0)
160 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
161 decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
163 else
165 decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
166 decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
167 _NL_MONETARY_DECIMAL_POINT_WC);
169 /* The decimal point character must never be zero. */
170 assert (*decimal != '\0' && decimalwc != L'\0');
172 #define PRINTF_FPHEX_FETCH(FLOAT, VAR) \
174 (VAR) = *(const FLOAT *) args[0]; \
176 /* Check for special values: not a number or infinity. */ \
177 if (isnan (VAR)) \
179 if (isupper (info->spec)) \
181 special = "NAN"; \
182 wspecial = L"NAN"; \
184 else \
186 special = "nan"; \
187 wspecial = L"nan"; \
190 else \
192 if (isinf (VAR)) \
194 if (isupper (info->spec)) \
196 special = "INF"; \
197 wspecial = L"INF"; \
199 else \
201 special = "inf"; \
202 wspecial = L"inf"; \
206 negative = signbit (VAR); \
209 /* Fetch the argument value. */
210 #if __HAVE_DISTINCT_FLOAT128
211 if (info->is_binary128)
212 PRINTF_FPHEX_FETCH (_Float128, fpnum.flt128)
213 else
214 #endif
215 #ifndef __NO_LONG_DOUBLE_MATH
216 if (info->is_long_double && sizeof (long double) > sizeof (double))
217 PRINTF_FPHEX_FETCH (long double, fpnum.ldbl)
218 else
219 #endif
220 PRINTF_FPHEX_FETCH (double, fpnum.dbl.d)
222 #undef PRINTF_FPHEX_FETCH
224 if (special)
226 int width = info->width;
228 if (negative || info->showsign || info->space)
229 --width;
230 width -= 3;
232 if (!info->left && width > 0)
233 PADN (' ', width);
235 if (negative)
236 outchar ('-');
237 else if (info->showsign)
238 outchar ('+');
239 else if (info->space)
240 outchar (' ');
242 PRINT (special, wspecial, 3);
244 if (info->left && width > 0)
245 PADN (' ', width);
247 return done;
250 #if __HAVE_DISTINCT_FLOAT128
251 if (info->is_binary128)
252 PRINT_FPHEX_FLOAT128;
253 else
254 #endif
255 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
257 /* We have 52 bits of mantissa plus one implicit digit. Since
258 52 bits are representable without rest using hexadecimal
259 digits we use only the implicit digits for the number before
260 the decimal point. */
261 unsigned long long int num;
263 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
264 | fpnum.dbl.ieee.mantissa1);
266 zero_mantissa = num == 0;
268 if (sizeof (unsigned long int) > 6)
270 wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
271 info->spec == 'A');
272 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
273 info->spec == 'A');
275 else
277 wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
278 info->spec == 'A');
279 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
280 info->spec == 'A');
283 /* Fill with zeroes. */
284 while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
286 *--wnumstr = L'0';
287 *--numstr = '0';
290 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
292 exponent = fpnum.dbl.ieee.exponent;
294 if (exponent == 0)
296 if (zero_mantissa)
297 expnegative = 0;
298 else
300 /* This is a denormalized number. */
301 expnegative = 1;
302 exponent = IEEE754_DOUBLE_BIAS - 1;
305 else if (exponent >= IEEE754_DOUBLE_BIAS)
307 expnegative = 0;
308 exponent -= IEEE754_DOUBLE_BIAS;
310 else
312 expnegative = 1;
313 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
316 #ifdef PRINT_FPHEX_LONG_DOUBLE
317 else
318 PRINT_FPHEX_LONG_DOUBLE;
319 #endif
321 /* Look for trailing zeroes. */
322 if (! zero_mantissa)
324 wnumend = array_end (wnumbuf);
325 numend = array_end (numbuf);
326 while (wnumend[-1] == L'0')
328 --wnumend;
329 --numend;
332 bool do_round_away = false;
334 if (precision != -1 && precision < numend - numstr)
336 char last_digit = precision > 0 ? numstr[precision - 1] : leading;
337 char next_digit = numstr[precision];
338 int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
339 ? last_digit - 'A' + 10
340 : (last_digit >= 'a' && last_digit <= 'f'
341 ? last_digit - 'a' + 10
342 : last_digit - '0'));
343 int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
344 ? next_digit - 'A' + 10
345 : (next_digit >= 'a' && next_digit <= 'f'
346 ? next_digit - 'a' + 10
347 : next_digit - '0'));
348 bool more_bits = ((next_digit_value & 7) != 0
349 || precision + 1 < numend - numstr);
350 int rounding_mode = get_rounding_mode ();
351 do_round_away = round_away (negative, last_digit_value & 1,
352 next_digit_value >= 8, more_bits,
353 rounding_mode);
356 if (precision == -1)
357 precision = numend - numstr;
358 else if (do_round_away)
360 /* Round up. */
361 int cnt = precision;
362 while (--cnt >= 0)
364 char ch = numstr[cnt];
365 /* We assume that the digits and the letters are ordered
366 like in ASCII. This is true for the rest of GNU, too. */
367 if (ch == '9')
369 wnumstr[cnt] = (wchar_t) info->spec;
370 numstr[cnt] = info->spec; /* This is tricky,
371 think about it! */
372 break;
374 else if (tolower (ch) < 'f')
376 ++numstr[cnt];
377 ++wnumstr[cnt];
378 break;
380 else
382 numstr[cnt] = '0';
383 wnumstr[cnt] = L'0';
386 if (cnt < 0)
388 /* The mantissa so far was fff...f Now increment the
389 leading digit. Here it is again possible that we
390 get an overflow. */
391 if (leading == '9')
392 leading = info->spec;
393 else if (tolower (leading) < 'f')
394 ++leading;
395 else
397 leading = '1';
398 if (expnegative)
400 exponent -= 4;
401 if (exponent <= 0)
403 exponent = -exponent;
404 expnegative = 0;
407 else
408 exponent += 4;
413 else
415 if (precision == -1)
416 precision = 0;
417 numend = numstr;
418 wnumend = wnumstr;
421 /* Now we can compute the exponent string. */
422 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
423 wexpstr = _itowa_word (exponent,
424 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
426 /* Now we have all information to compute the size. */
427 width -= ((negative || info->showsign || info->space)
428 /* Sign. */
429 + 2 + 1 + 0 + precision + 1 + 1
430 /* 0x h . hhh P ExpoSign. */
431 + ((expbuf + sizeof expbuf) - expstr));
432 /* Exponent. */
434 /* Count the decimal point.
435 A special case when the mantissa or the precision is zero and the `#'
436 is not given. In this case we must not print the decimal point. */
437 if (precision > 0 || info->alt)
438 width -= wide ? 1 : strlen (decimal);
440 if (!info->left && info->pad != '0' && width > 0)
441 PADN (' ', width);
443 if (negative)
444 outchar ('-');
445 else if (info->showsign)
446 outchar ('+');
447 else if (info->space)
448 outchar (' ');
450 outchar ('0');
451 if ('X' - 'A' == 'x' - 'a')
452 outchar (info->spec + ('x' - 'a'));
453 else
454 outchar (info->spec == 'A' ? 'X' : 'x');
456 if (!info->left && info->pad == '0' && width > 0)
457 PADN ('0', width);
459 outchar (leading);
461 if (precision > 0 || info->alt)
463 const wchar_t *wtmp = &decimalwc;
464 PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
467 if (precision > 0)
469 ssize_t tofill = precision - (numend - numstr);
470 PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
471 if (tofill > 0)
472 PADN ('0', tofill);
475 if ('P' - 'A' == 'p' - 'a')
476 outchar (info->spec + ('p' - 'a'));
477 else
478 outchar (info->spec == 'A' ? 'P' : 'p');
480 outchar (expnegative ? '-' : '+');
482 PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
484 if (info->left && info->pad != '0' && width > 0)
485 PADN (info->pad, width);
487 return done;