]> git.ipfire.org Git - thirdparty/glibc.git/blame - stdio-common/printf_fphex.c
PowerPC floating point little-endian [1 of 15]
[thirdparty/glibc.git] / stdio-common / printf_fphex.c
CommitLineData
a1d84548 1/* Print floating point number in hexadecimal notation according to ISO C99.
568035b7 2 Copyright (C) 1997-2013 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
UD
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>
f671aeab 26#include <string.h>
8d8c6efa 27#include <wchar.h>
eb96ffb0
L
28#include <_itoa.h>
29#include <_itowa.h>
8f2ece69 30#include <locale/localeinfo.h>
a9f8e53a
JM
31#include <stdbool.h>
32#include <rounding-mode.h>
2f6d1f1b
UD
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. */
3ce1f295
UD
39#include <libioP.h>
40#define PUT(f, s, n) _IO_sputn (f, s, n)
d18ea0c5 41#define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
2f6d1f1b
UD
42/* We use this file GNU C library and GNU I/O library. So make
43 names equal. */
3ce1f295
UD
44#undef putc
45#define putc(c, f) (wide \
1dc72e4f 46 ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
3ce1f295
UD
47#define size_t _IO_size_t
48#define FILE _IO_FILE
2f6d1f1b
UD
49\f
50/* Macros for doing the actual output. */
51
52#define outchar(ch) \
53 do \
54 { \
2e09a79a 55 const int outc = (ch); \
2f6d1f1b
UD
56 if (putc (outc, fp) == EOF) \
57 return -1; \
58 ++done; \
59 } while (0)
60
a1d84548 61#define PRINT(ptr, wptr, len) \
2f6d1f1b
UD
62 do \
63 { \
2e09a79a 64 size_t outlen = (len); \
a1d84548
UD
65 if (wide) \
66 while (outlen-- > 0) \
67 outchar (*wptr++); \
68 else \
69 while (outlen-- > 0) \
70 outchar (*ptr++); \
2f6d1f1b
UD
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)
0d8733c4
UD
81
82#ifndef MIN
83# define MIN(a,b) ((a)<(b)?(a):(b))
84#endif
2f6d1f1b
UD
85\f
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;
1b6adf88 96 long double ldbl;
2f6d1f1b
UD
97 }
98 fpnum;
99
100 /* Locale-dependent representation of decimal point. */
a1d84548
UD
101 const char *decimal;
102 wchar_t decimalwc;
2f6d1f1b
UD
103
104 /* "NaN" or "Inf" for the special cases. */
105 const char *special = NULL;
a1d84548 106 const wchar_t *wspecial = NULL;
2f6d1f1b
UD
107
108 /* Buffer for the generated number string for the mantissa. The
abfbdde1
UD
109 maximal size for the mantissa is 128 bits. */
110 char numbuf[32];
2f6d1f1b
UD
111 char *numstr;
112 char *numend;
a1d84548
UD
113 wchar_t wnumbuf[32];
114 wchar_t *wnumstr;
115 wchar_t *wnumend;
2f6d1f1b
UD
116 int negative;
117
118 /* The maximal exponent of two in decimal notation has 5 digits. */
119 char expbuf[5];
120 char *expstr;
a1d84548
UD
121 wchar_t wexpbuf[5];
122 wchar_t *wexpstr;
2f6d1f1b
UD
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
d64b6ad0
UD
141 /* Nonzero if this is output on a wide character stream. */
142 int wide = info->wide;
143
2f6d1f1b
UD
144
145 /* Figure out the decimal point character. */
146 if (info->extra == 0)
147 {
a1d84548
UD
148 decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
149 decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
2f6d1f1b
UD
150 }
151 else
152 {
a1d84548
UD
153 decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
154 decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
155 _NL_MONETARY_DECIMAL_POINT_WC);
2f6d1f1b 156 }
a1d84548
UD
157 /* The decimal point character must never be zero. */
158 assert (*decimal != '\0' && decimalwc != L'\0');
2f6d1f1b
UD
159
160
161 /* Fetch the argument value. */
f98b4bbd 162#ifndef __NO_LONG_DOUBLE_MATH
2f6d1f1b
UD
163 if (info->is_long_double && sizeof (long double) > sizeof (double))
164 {
1b6adf88 165 fpnum.ldbl = *(const long double *) args[0];
2f6d1f1b
UD
166
167 /* Check for special values: not a number or infinity. */
1b6adf88 168 if (__isnanl (fpnum.ldbl))
2f6d1f1b 169 {
a1d84548
UD
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 }
2f6d1f1b
UD
180 }
181 else
182 {
1b6adf88 183 if (__isinfl (fpnum.ldbl))
a1d84548
UD
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 }
2f6d1f1b 196 }
1b6adf88 197 negative = signbit (fpnum.ldbl);
2f6d1f1b
UD
198 }
199 else
f98b4bbd 200#endif /* no long double */
2f6d1f1b
UD
201 {
202 fpnum.dbl.d = *(const double *) args[0];
203
204 /* Check for special values: not a number or infinity. */
76f2646f 205 if (__isnan (fpnum.dbl.d))
2f6d1f1b 206 {
003c9895 207 negative = fpnum.dbl.ieee.negative != 0;
a1d84548
UD
208 if (isupper (info->spec))
209 {
210 special = "NAN";
211 wspecial = L"NAN";
212 }
213 else
214 {
215 special = "nan";
216 wspecial = L"nan";
217 }
2f6d1f1b
UD
218 }
219 else
220 {
187da0ae
UD
221 int res = __isinf (fpnum.dbl.d);
222 if (res)
a1d84548
UD
223 {
224 if (isupper (info->spec))
225 {
226 special = "INF";
227 wspecial = L"INF";
228 }
229 else
230 {
231 special = "inf";
232 wspecial = L"inf";
233 }
187da0ae 234 negative = res < 0;
a1d84548 235 }
187da0ae
UD
236 else
237 negative = signbit (fpnum.dbl.d);
2f6d1f1b
UD
238 }
239 }
240
241 if (special)
242 {
1f205a47 243 int width = info->width;
2f6d1f1b
UD
244
245 if (negative || info->showsign || info->space)
246 --width;
247 width -= 3;
248
249 if (!info->left && width > 0)
250 PADN (' ', width);
251
252 if (negative)
253 outchar ('-');
254 else if (info->showsign)
255 outchar ('+');
256 else if (info->space)
257 outchar (' ');
258
a1d84548 259 PRINT (special, wspecial, 3);
2f6d1f1b
UD
260
261 if (info->left && width > 0)
262 PADN (' ', width);
263
264 return done;
265 }
266
2f6d1f1b
UD
267 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
268 {
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. */
377a515b 273 unsigned long long int num;
2f6d1f1b 274
377a515b
UD
275 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
276 | fpnum.dbl.ieee.mantissa1);
2f6d1f1b 277
377a515b 278 zero_mantissa = num == 0;
2f6d1f1b 279
377a515b 280 if (sizeof (unsigned long int) > 6)
a1d84548 281 {
a535ce14 282 wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
a1d84548
UD
283 info->spec == 'A');
284 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
285 info->spec == 'A');
286 }
2f6d1f1b 287 else
a1d84548 288 {
a535ce14 289 wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
a1d84548
UD
290 info->spec == 'A');
291 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
292 info->spec == 'A');
293 }
2f6d1f1b
UD
294
295 /* Fill with zeroes. */
a535ce14 296 while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
a1d84548
UD
297 {
298 *--wnumstr = L'0';
299 *--numstr = '0';
300 }
2f6d1f1b
UD
301
302 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
303
304 exponent = fpnum.dbl.ieee.exponent;
305
d8cceb4f 306 if (exponent == 0)
2f6d1f1b 307 {
d8cceb4f
UD
308 if (zero_mantissa)
309 expnegative = 0;
310 else
311 {
312 /* This is a denormalized number. */
313 expnegative = 1;
91ea72b7 314 exponent = IEEE754_DOUBLE_BIAS - 1;
d8cceb4f 315 }
2f6d1f1b 316 }
d8cceb4f 317 else if (exponent >= IEEE754_DOUBLE_BIAS)
2f6d1f1b
UD
318 {
319 expnegative = 0;
d8cceb4f
UD
320 exponent -= IEEE754_DOUBLE_BIAS;
321 }
322 else
323 {
324 expnegative = 1;
325 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
2f6d1f1b
UD
326 }
327 }
abfbdde1 328#ifdef PRINT_FPHEX_LONG_DOUBLE
2f6d1f1b 329 else
abfbdde1 330 PRINT_FPHEX_LONG_DOUBLE;
91ea72b7 331#endif
2f6d1f1b
UD
332
333 /* Look for trailing zeroes. */
334 if (! zero_mantissa)
335 {
90d59870
RM
336 wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
337 numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
a1d84548
UD
338 while (wnumend[-1] == L'0')
339 {
340 --wnumend;
341 --numend;
342 }
2f6d1f1b 343
a9f8e53a
JM
344 bool do_round_away = false;
345
346 if (precision != -1 && precision < numend - numstr)
347 {
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);
366 }
367
2f6d1f1b
UD
368 if (precision == -1)
369 precision = numend - numstr;
a9f8e53a 370 else if (do_round_away)
2f6d1f1b
UD
371 {
372 /* Round up. */
373 int cnt = precision;
374 while (--cnt >= 0)
375 {
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')
380 {
a1d84548 381 wnumstr[cnt] = (wchar_t) info->spec;
2f6d1f1b 382 numstr[cnt] = info->spec; /* This is tricky,
350635a5 383 think about it! */
2f6d1f1b
UD
384 break;
385 }
386 else if (tolower (ch) < 'f')
387 {
388 ++numstr[cnt];
a1d84548 389 ++wnumstr[cnt];
2f6d1f1b
UD
390 break;
391 }
392 else
a1d84548
UD
393 {
394 numstr[cnt] = '0';
395 wnumstr[cnt] = L'0';
396 }
2f6d1f1b
UD
397 }
398 if (cnt < 0)
399 {
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
408 {
9c06eb66 409 leading = '1';
2f6d1f1b
UD
410 if (expnegative)
411 {
9c06eb66
UD
412 exponent -= 4;
413 if (exponent <= 0)
6c215a8d
UD
414 {
415 exponent = -exponent;
416 expnegative = 0;
417 }
2f6d1f1b
UD
418 }
419 else
420 exponent += 4;
421 }
422 }
423 }
424 }
425 else
263456bd
UD
426 {
427 if (precision == -1)
428 precision = 0;
429 numend = numstr;
a1d84548 430 wnumend = wnumstr;
263456bd 431 }
2f6d1f1b
UD
432
433 /* Now we can compute the exponent string. */
434 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
66bdfcab
UD
435 wexpstr = _itowa_word (exponent,
436 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
2f6d1f1b
UD
437
438 /* Now we have all information to compute the size. */
439 width -= ((negative || info->showsign || info->space)
440 /* Sign. */
b15cb495 441 + 2 + 1 + 0 + precision + 1 + 1
2f6d1f1b
UD
442 /* 0x h . hhh P ExpoSign. */
443 + ((expbuf + sizeof expbuf) - expstr));
444 /* Exponent. */
445
90d59870
RM
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. */
b15cb495
UD
449 if (precision > 0 || info->alt)
450 width -= wide ? 1 : strlen (decimal);
451
90d59870 452 if (!info->left && info->pad != '0' && width > 0)
2f6d1f1b
UD
453 PADN (' ', width);
454
455 if (negative)
456 outchar ('-');
457 else if (info->showsign)
458 outchar ('+');
459 else if (info->space)
460 outchar (' ');
461
462 outchar ('0');
263456bd
UD
463 if ('X' - 'A' == 'x' - 'a')
464 outchar (info->spec + ('x' - 'a'));
465 else
466 outchar (info->spec == 'A' ? 'X' : 'x');
90d59870
RM
467
468 if (!info->left && info->pad == '0' && width > 0)
469 PADN ('0', width);
470
2f6d1f1b
UD
471 outchar (leading);
472
263456bd 473 if (precision > 0 || info->alt)
a1d84548
UD
474 {
475 const wchar_t *wtmp = &decimalwc;
476 PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
477 }
2f6d1f1b 478
263456bd 479 if (precision > 0)
2f6d1f1b 480 {
b15cb495 481 ssize_t tofill = precision - (numend - numstr);
a1d84548 482 PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
b15cb495
UD
483 if (tofill > 0)
484 PADN ('0', tofill);
2f6d1f1b
UD
485 }
486
263456bd
UD
487 if ('P' - 'A' == 'p' - 'a')
488 outchar (info->spec + ('p' - 'a'));
489 else
490 outchar (info->spec == 'A' ? 'P' : 'p');
2f6d1f1b
UD
491
492 outchar (expnegative ? '-' : '+');
493
a1d84548 494 PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
2f6d1f1b
UD
495
496 if (info->left && info->pad != '0' && width > 0)
497 PADN (info->pad, width);
498
499 return done;
500}