1/* Print floating point number in hexadecimal notation according to ISO C99.
2 Copyright (C) 1997-2016 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
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
86
87int
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 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 = *(const long double *) args[0];
166
167 /* Check for special values: not a number or infinity. */
168 if (isnan (fpnum.ldbl))
169 {
170 if (isupper (info->spec))
171 {
172 special = "NAN";
173 wspecial = L"NAN";
174 }
175 else
176 {
177 special = "nan";
178 wspecial = L"nan";
179 }
180 }
181 else
182 {
183 if (isinf (fpnum.ldbl))
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 }
196 }
197 negative = signbit (fpnum.ldbl);
198 }
199 else
200#endif /* no long double */
201 {
202 fpnum.dbl.d = *(const double *) args[0];
203
204 /* Check for special values: not a number or infinity. */
205 if (isnan (fpnum.dbl.d))
206 {
207 if (isupper (info->spec))
208 {
209 special = "NAN";
210 wspecial = L"NAN";
211 }
212 else
213 {
214 special = "nan";
215 wspecial = L"nan";
216 }
217 }
218 else
219 {
220 if (isinf (fpnum.dbl.d))
221 {
222 if (isupper (info->spec))
223 {
224 special = "INF";
225 wspecial = L"INF";
226 }
227 else
228 {
229 special = "inf";
230 wspecial = L"inf";
231 }
232 }
233 }
234 negative = signbit (fpnum.dbl.d);
235 }
236
237 if (special)
238 {
239 int width = info->width;
240
241 if (negative || info->showsign || info->space)
242 --width;
243 width -= 3;
244
245 if (!info->left && width > 0)
246 PADN (' ', width);
247
248 if (negative)
249 outchar ('-');
250 else if (info->showsign)
251 outchar ('+');
252 else if (info->space)
253 outchar (' ');
254
255 PRINT (special, wspecial, 3);
256
257 if (info->left && width > 0)
258 PADN (' ', width);
259
260 return done;
261 }
262
263 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
264 {
265 /* We have 52 bits of mantissa plus one implicit digit. Since
266 52 bits are representable without rest using hexadecimal
267 digits we use only the implicit digits for the number before
268 the decimal point. */
269 unsigned long long int num;
270
271 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
272 | fpnum.dbl.ieee.mantissa1);
273
274 zero_mantissa = num == 0;
275
276 if (sizeof (unsigned long int) > 6)
277 {
278 wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
279 info->spec == 'A');
280 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
281 info->spec == 'A');
282 }
283 else
284 {
285 wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
286 info->spec == 'A');
287 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
288 info->spec == 'A');
289 }
290
291 /* Fill with zeroes. */
292 while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
293 {
294 *--wnumstr = L'0';
295 *--numstr = '0';
296 }
297
298 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
299
300 exponent = fpnum.dbl.ieee.exponent;
301
302 if (exponent == 0)
303 {
304 if (zero_mantissa)
305 expnegative = 0;
306 else
307 {
308 /* This is a denormalized number. */
309 expnegative = 1;
310 exponent = IEEE754_DOUBLE_BIAS - 1;
311 }
312 }
313 else if (exponent >= IEEE754_DOUBLE_BIAS)
314 {
315 expnegative = 0;
316 exponent -= IEEE754_DOUBLE_BIAS;
317 }
318 else
319 {
320 expnegative = 1;
321 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
322 }
323 }
324#ifdef PRINT_FPHEX_LONG_DOUBLE
325 else
326 PRINT_FPHEX_LONG_DOUBLE;
327#endif
328
329 /* Look for trailing zeroes. */
330 if (! zero_mantissa)
331 {
332 wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
333 numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
334 while (wnumend[-1] == L'0')
335 {
336 --wnumend;
337 --numend;
338 }
339
340 bool do_round_away = false;
341
342 if (precision != -1 && precision < numend - numstr)
343 {
344 char last_digit = precision > 0 ? numstr[precision - 1] : leading;
345 char next_digit = numstr[precision];
346 int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
347 ? last_digit - 'A' + 10
348 : (last_digit >= 'a' && last_digit <= 'f'
349 ? last_digit - 'a' + 10
350 : last_digit - '0'));
351 int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
352 ? next_digit - 'A' + 10
353 : (next_digit >= 'a' && next_digit <= 'f'
354 ? next_digit - 'a' + 10
355 : next_digit - '0'));
356 bool more_bits = ((next_digit_value & 7) != 0
357 || precision + 1 < numend - numstr);
358 int rounding_mode = get_rounding_mode ();
359 do_round_away = round_away (negative, last_digit_value & 1,
360 next_digit_value >= 8, more_bits,
361 rounding_mode);
362 }
363
364 if (precision == -1)
365 precision = numend - numstr;
366 else if (do_round_away)
367 {
368 /* Round up. */
369 int cnt = precision;
370 while (--cnt >= 0)
371 {
372 char ch = numstr[cnt];
373 /* We assume that the digits and the letters are ordered
374 like in ASCII. This is true for the rest of GNU, too. */
375 if (ch == '9')
376 {
377 wnumstr[cnt] = (wchar_t) info->spec;
378 numstr[cnt] = info->spec; /* This is tricky,
379 think about it! */
380 break;
381 }
382 else if (tolower (ch) < 'f')
383 {
384 ++numstr[cnt];
385 ++wnumstr[cnt];
386 break;
387 }
388 else
389 {
390 numstr[cnt] = '0';
391 wnumstr[cnt] = L'0';
392 }
393 }
394 if (cnt < 0)
395 {
396 /* The mantissa so far was fff...f Now increment the
397 leading digit. Here it is again possible that we
398 get an overflow. */
399 if (leading == '9')
400 leading = info->spec;
401 else if (tolower (leading) < 'f')
402 ++leading;
403 else
404 {
405 leading = '1';
406 if (expnegative)
407 {
408 exponent -= 4;
409 if (exponent <= 0)
410 {
411 exponent = -exponent;
412 expnegative = 0;
413 }
414 }
415 else
416 exponent += 4;
417 }
418 }
419 }
420 }
421 else
422 {
423 if (precision == -1)
424 precision = 0;
425 numend = numstr;
426 wnumend = wnumstr;
427 }
428
429 /* Now we can compute the exponent string. */
430 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
431 wexpstr = _itowa_word (exponent,
432 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
433
434 /* Now we have all information to compute the size. */
435 width -= ((negative || info->showsign || info->space)
436 /* Sign. */
437 + 2 + 1 + 0 + precision + 1 + 1
438 /* 0x h . hhh P ExpoSign. */
439 + ((expbuf + sizeof expbuf) - expstr));
440 /* Exponent. */
441
442 /* Count the decimal point.
443 A special case when the mantissa or the precision is zero and the `#'
444 is not given. In this case we must not print the decimal point. */
445 if (precision > 0 || info->alt)
446 width -= wide ? 1 : strlen (decimal);
447
448 if (!info->left && info->pad != '0' && width > 0)
449 PADN (' ', width);
450
451 if (negative)
452 outchar ('-');
453 else if (info->showsign)
454 outchar ('+');
455 else if (info->space)
456 outchar (' ');
457
458 outchar ('0');
459 if ('X' - 'A' == 'x' - 'a')
460 outchar (info->spec + ('x' - 'a'));
461 else
462 outchar (info->spec == 'A' ? 'X' : 'x');
463
464 if (!info->left && info->pad == '0' && width > 0)
465 PADN ('0', width);
466
467 outchar (leading);
468
469 if (precision > 0 || info->alt)
470 {
471 const wchar_t *wtmp = &decimalwc;
472 PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
473 }
474
475 if (precision > 0)
476 {
477 ssize_t tofill = precision - (numend - numstr);
478 PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
479 if (tofill > 0)
480 PADN ('0', tofill);
481 }
482
483 if ('P' - 'A' == 'p' - 'a')
484 outchar (info->spec + ('p' - 'a'));
485 else
486 outchar (info->spec == 'A' ? 'P' : 'p');
487
488 outchar (expnegative ? '-' : '+');
489
490 PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
491
492 if (info->left && info->pad != '0' && width > 0)
493 PADN (info->pad, width);
494
495 return done;
496}
497