]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdio-common/printf_fphex.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / stdio-common / printf_fphex.c
CommitLineData
a1d84548 1/* Print floating point number in hexadecimal notation according to ISO C99.
688903eb 2 Copyright (C) 1997-2018 Free Software Foundation, Inc.
2f6d1f1b
UD
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
41bdb6e2
AJ
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.
2f6d1f1b
UD
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
41bdb6e2 14 Lesser General Public License for more details.
2f6d1f1b 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
2f6d1f1b 19
d10b132b 20#include <array_length.h>
2f6d1f1b
UD
21#include <ctype.h>
22#include <ieee754.h>
23#include <math.h>
24#include <printf.h>
25#include <stdlib.h>
26#include <stdio.h>
f671aeab 27#include <string.h>
8d8c6efa 28#include <wchar.h>
eb96ffb0
L
29#include <_itoa.h>
30#include <_itowa.h>
8f2ece69 31#include <locale/localeinfo.h>
a9f8e53a
JM
32#include <stdbool.h>
33#include <rounding-mode.h>
2f6d1f1b 34
cf2046ec
GG
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
42
2f6d1f1b
UD
43/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
44#include <assert.h>
45
46/* This defines make it possible to use the same code for GNU C library and
47 the GNU I/O library. */
3ce1f295
UD
48#include <libioP.h>
49#define PUT(f, s, n) _IO_sputn (f, s, n)
d18ea0c5 50#define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
2f6d1f1b
UD
51/* We use this file GNU C library and GNU I/O library. So make
52 names equal. */
3ce1f295
UD
53#undef putc
54#define putc(c, f) (wide \
1dc72e4f 55 ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
3ce1f295
UD
56#define size_t _IO_size_t
57#define FILE _IO_FILE
2f6d1f1b
UD
58\f
59/* Macros for doing the actual output. */
60
61#define outchar(ch) \
62 do \
63 { \
2e09a79a 64 const int outc = (ch); \
2f6d1f1b
UD
65 if (putc (outc, fp) == EOF) \
66 return -1; \
67 ++done; \
68 } while (0)
69
a1d84548 70#define PRINT(ptr, wptr, len) \
2f6d1f1b
UD
71 do \
72 { \
2e09a79a 73 size_t outlen = (len); \
a1d84548
UD
74 if (wide) \
75 while (outlen-- > 0) \
76 outchar (*wptr++); \
77 else \
78 while (outlen-- > 0) \
79 outchar (*ptr++); \
2f6d1f1b
UD
80 } while (0)
81
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)
0d8733c4
UD
90
91#ifndef MIN
92# define MIN(a,b) ((a)<(b)?(a):(b))
93#endif
2f6d1f1b
UD
94\f
95
96int
97__printf_fphex (FILE *fp,
98 const struct printf_info *info,
99 const void *const *args)
100{
101 /* The floating-point value to output. */
102 union
103 {
104 union ieee754_double dbl;
1b6adf88 105 long double ldbl;
cf2046ec
GG
106#if __HAVE_DISTINCT_FLOAT128
107 _Float128 flt128;
108#endif
2f6d1f1b
UD
109 }
110 fpnum;
111
112 /* Locale-dependent representation of decimal point. */
a1d84548
UD
113 const char *decimal;
114 wchar_t decimalwc;
2f6d1f1b
UD
115
116 /* "NaN" or "Inf" for the special cases. */
117 const char *special = NULL;
a1d84548 118 const wchar_t *wspecial = NULL;
2f6d1f1b
UD
119
120 /* Buffer for the generated number string for the mantissa. The
abfbdde1
UD
121 maximal size for the mantissa is 128 bits. */
122 char numbuf[32];
2f6d1f1b
UD
123 char *numstr;
124 char *numend;
a1d84548
UD
125 wchar_t wnumbuf[32];
126 wchar_t *wnumstr;
127 wchar_t *wnumend;
2f6d1f1b
UD
128 int negative;
129
130 /* The maximal exponent of two in decimal notation has 5 digits. */
131 char expbuf[5];
132 char *expstr;
a1d84548
UD
133 wchar_t wexpbuf[5];
134 wchar_t *wexpstr;
2f6d1f1b
UD
135 int expnegative;
136 int exponent;
137
138 /* Non-zero is mantissa is zero. */
139 int zero_mantissa;
140
141 /* The leading digit before the decimal point. */
142 char leading;
143
144 /* Precision. */
145 int precision = info->prec;
146
147 /* Width. */
148 int width = info->width;
149
150 /* Number of characters written. */
151 int done = 0;
152
d64b6ad0
UD
153 /* Nonzero if this is output on a wide character stream. */
154 int wide = info->wide;
155
2f6d1f1b
UD
156
157 /* Figure out the decimal point character. */
158 if (info->extra == 0)
159 {
a1d84548
UD
160 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
161 decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
2f6d1f1b
UD
162 }
163 else
164 {
a1d84548
UD
165 decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
166 decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
167 _NL_MONETARY_DECIMAL_POINT_WC);
2f6d1f1b 168 }
a1d84548
UD
169 /* The decimal point character must never be zero. */
170 assert (*decimal != '\0' && decimalwc != L'\0');
2f6d1f1b 171
aab0f374
GG
172#define PRINTF_FPHEX_FETCH(FLOAT, VAR) \
173 { \
174 (VAR) = *(const FLOAT *) args[0]; \
175 \
176 /* Check for special values: not a number or infinity. */ \
177 if (isnan (VAR)) \
178 { \
179 if (isupper (info->spec)) \
180 { \
181 special = "NAN"; \
182 wspecial = L"NAN"; \
183 } \
184 else \
185 { \
186 special = "nan"; \
187 wspecial = L"nan"; \
188 } \
189 } \
190 else \
191 { \
192 if (isinf (VAR)) \
193 { \
194 if (isupper (info->spec)) \
195 { \
196 special = "INF"; \
197 wspecial = L"INF"; \
198 } \
199 else \
200 { \
201 special = "inf"; \
202 wspecial = L"inf"; \
203 } \
204 } \
205 } \
206 negative = signbit (VAR); \
207 }
2f6d1f1b
UD
208
209 /* Fetch the argument value. */
cf2046ec
GG
210#if __HAVE_DISTINCT_FLOAT128
211 if (info->is_binary128)
212 PRINTF_FPHEX_FETCH (_Float128, fpnum.flt128)
213 else
214#endif
f98b4bbd 215#ifndef __NO_LONG_DOUBLE_MATH
2f6d1f1b 216 if (info->is_long_double && sizeof (long double) > sizeof (double))
aab0f374 217 PRINTF_FPHEX_FETCH (long double, fpnum.ldbl)
2f6d1f1b 218 else
aab0f374
GG
219#endif
220 PRINTF_FPHEX_FETCH (double, fpnum.dbl.d)
221
222#undef PRINTF_FPHEX_FETCH
2f6d1f1b
UD
223
224 if (special)
225 {
1f205a47 226 int width = info->width;
2f6d1f1b
UD
227
228 if (negative || info->showsign || info->space)
229 --width;
230 width -= 3;
231
232 if (!info->left && width > 0)
233 PADN (' ', width);
234
235 if (negative)
236 outchar ('-');
237 else if (info->showsign)
238 outchar ('+');
239 else if (info->space)
240 outchar (' ');
241
a1d84548 242 PRINT (special, wspecial, 3);
2f6d1f1b
UD
243
244 if (info->left && width > 0)
245 PADN (' ', width);
246
247 return done;
248 }
249
cf2046ec
GG
250#if __HAVE_DISTINCT_FLOAT128
251 if (info->is_binary128)
252 PRINT_FPHEX_FLOAT128;
253 else
254#endif
2f6d1f1b
UD
255 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
256 {
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. */
377a515b 261 unsigned long long int num;
2f6d1f1b 262
377a515b
UD
263 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
264 | fpnum.dbl.ieee.mantissa1);
2f6d1f1b 265
377a515b 266 zero_mantissa = num == 0;
2f6d1f1b 267
377a515b 268 if (sizeof (unsigned long int) > 6)
a1d84548 269 {
a535ce14 270 wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
a1d84548
UD
271 info->spec == 'A');
272 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
273 info->spec == 'A');
274 }
2f6d1f1b 275 else
a1d84548 276 {
a535ce14 277 wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
a1d84548
UD
278 info->spec == 'A');
279 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
280 info->spec == 'A');
281 }
2f6d1f1b
UD
282
283 /* Fill with zeroes. */
a535ce14 284 while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
a1d84548
UD
285 {
286 *--wnumstr = L'0';
287 *--numstr = '0';
288 }
2f6d1f1b
UD
289
290 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
291
292 exponent = fpnum.dbl.ieee.exponent;
293
d8cceb4f 294 if (exponent == 0)
2f6d1f1b 295 {
d8cceb4f
UD
296 if (zero_mantissa)
297 expnegative = 0;
298 else
299 {
300 /* This is a denormalized number. */
301 expnegative = 1;
91ea72b7 302 exponent = IEEE754_DOUBLE_BIAS - 1;
d8cceb4f 303 }
2f6d1f1b 304 }
d8cceb4f 305 else if (exponent >= IEEE754_DOUBLE_BIAS)
2f6d1f1b
UD
306 {
307 expnegative = 0;
d8cceb4f
UD
308 exponent -= IEEE754_DOUBLE_BIAS;
309 }
310 else
311 {
312 expnegative = 1;
313 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
2f6d1f1b
UD
314 }
315 }
abfbdde1 316#ifdef PRINT_FPHEX_LONG_DOUBLE
2f6d1f1b 317 else
abfbdde1 318 PRINT_FPHEX_LONG_DOUBLE;
91ea72b7 319#endif
2f6d1f1b
UD
320
321 /* Look for trailing zeroes. */
322 if (! zero_mantissa)
323 {
d10b132b
FW
324 wnumend = array_end (wnumbuf);
325 numend = array_end (numbuf);
a1d84548
UD
326 while (wnumend[-1] == L'0')
327 {
328 --wnumend;
329 --numend;
330 }
2f6d1f1b 331
a9f8e53a
JM
332 bool do_round_away = false;
333
334 if (precision != -1 && precision < numend - numstr)
335 {
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);
354 }
355
2f6d1f1b
UD
356 if (precision == -1)
357 precision = numend - numstr;
a9f8e53a 358 else if (do_round_away)
2f6d1f1b
UD
359 {
360 /* Round up. */
361 int cnt = precision;
362 while (--cnt >= 0)
363 {
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')
368 {
a1d84548 369 wnumstr[cnt] = (wchar_t) info->spec;
2f6d1f1b 370 numstr[cnt] = info->spec; /* This is tricky,
350635a5 371 think about it! */
2f6d1f1b
UD
372 break;
373 }
374 else if (tolower (ch) < 'f')
375 {
376 ++numstr[cnt];
a1d84548 377 ++wnumstr[cnt];
2f6d1f1b
UD
378 break;
379 }
380 else
a1d84548
UD
381 {
382 numstr[cnt] = '0';
383 wnumstr[cnt] = L'0';
384 }
2f6d1f1b
UD
385 }
386 if (cnt < 0)
387 {
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
396 {
9c06eb66 397 leading = '1';
2f6d1f1b
UD
398 if (expnegative)
399 {
9c06eb66
UD
400 exponent -= 4;
401 if (exponent <= 0)
6c215a8d
UD
402 {
403 exponent = -exponent;
404 expnegative = 0;
405 }
2f6d1f1b
UD
406 }
407 else
408 exponent += 4;
409 }
410 }
411 }
412 }
413 else
263456bd
UD
414 {
415 if (precision == -1)
416 precision = 0;
417 numend = numstr;
a1d84548 418 wnumend = wnumstr;
263456bd 419 }
2f6d1f1b
UD
420
421 /* Now we can compute the exponent string. */
422 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
66bdfcab
UD
423 wexpstr = _itowa_word (exponent,
424 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
2f6d1f1b
UD
425
426 /* Now we have all information to compute the size. */
427 width -= ((negative || info->showsign || info->space)
428 /* Sign. */
b15cb495 429 + 2 + 1 + 0 + precision + 1 + 1
2f6d1f1b
UD
430 /* 0x h . hhh P ExpoSign. */
431 + ((expbuf + sizeof expbuf) - expstr));
432 /* Exponent. */
433
90d59870
RM
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. */
b15cb495
UD
437 if (precision > 0 || info->alt)
438 width -= wide ? 1 : strlen (decimal);
439
90d59870 440 if (!info->left && info->pad != '0' && width > 0)
2f6d1f1b
UD
441 PADN (' ', width);
442
443 if (negative)
444 outchar ('-');
445 else if (info->showsign)
446 outchar ('+');
447 else if (info->space)
448 outchar (' ');
449
450 outchar ('0');
263456bd
UD
451 if ('X' - 'A' == 'x' - 'a')
452 outchar (info->spec + ('x' - 'a'));
453 else
454 outchar (info->spec == 'A' ? 'X' : 'x');
90d59870
RM
455
456 if (!info->left && info->pad == '0' && width > 0)
457 PADN ('0', width);
458
2f6d1f1b
UD
459 outchar (leading);
460
263456bd 461 if (precision > 0 || info->alt)
a1d84548
UD
462 {
463 const wchar_t *wtmp = &decimalwc;
464 PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
465 }
2f6d1f1b 466
263456bd 467 if (precision > 0)
2f6d1f1b 468 {
b15cb495 469 ssize_t tofill = precision - (numend - numstr);
a1d84548 470 PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
b15cb495
UD
471 if (tofill > 0)
472 PADN ('0', tofill);
2f6d1f1b
UD
473 }
474
263456bd
UD
475 if ('P' - 'A' == 'p' - 'a')
476 outchar (info->spec + ('p' - 'a'));
477 else
478 outchar (info->spec == 'A' ? 'P' : 'p');
2f6d1f1b
UD
479
480 outchar (expnegative ? '-' : '+');
481
a1d84548 482 PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
2f6d1f1b
UD
483
484 if (info->left && info->pad != '0' && width > 0)
485 PADN (info->pad, width);
486
487 return done;
488}