Update.
[glibc.git] / stdio-common / printf_fphex.c
blobfb53d24a1f3719b2fbdbb580a17e1f37d7c4fea4
1 /* Print floating point number in hexadecimal notation according to
2 ISO C 9X.
3 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <ctype.h>
23 #include <ieee754.h>
24 #include <math.h>
25 #include <printf.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include "_itoa.h"
30 #include <locale/localeinfo.h>
32 /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
33 #include <assert.h>
35 /* This defines make it possible to use the same code for GNU C library and
36 the GNU I/O library. */
37 #ifdef USE_IN_LIBIO
38 # include <libioP.h>
39 # define PUT(f, s, n) _IO_sputn (f, s, n)
40 # define PAD(f, c, n) _IO_padn (f, c, n)
41 /* We use this file GNU C library and GNU I/O library. So make
42 names equal. */
43 # undef putc
44 # define putc(c, f) _IO_putc_unlocked (c, f)
45 # define size_t _IO_size_t
46 # define FILE _IO_FILE
47 #else /* ! USE_IN_LIBIO */
48 # define PUT(f, s, n) fwrite (s, 1, n, f)
49 # define PAD(f, c, n) __printf_pad (f, c, n)
50 ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c. */
51 #endif /* USE_IN_LIBIO */
53 /* Macros for doing the actual output. */
55 #define outchar(ch) \
56 do \
57 { \
58 register const int outc = (ch); \
59 if (putc (outc, fp) == EOF) \
60 return -1; \
61 ++done; \
62 } while (0)
64 #define PRINT(ptr, len) \
65 do \
66 { \
67 int outlen = (len); \
68 const char *cp = (ptr); \
69 while (outlen-- > 0) \
70 outchar (*cp++); \
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 union ieee854_long_double ldbl;
98 fpnum;
100 /* Locale-dependent representation of decimal point. */
101 wchar_t decimal;
103 /* "NaN" or "Inf" for the special cases. */
104 const char *special = NULL;
106 /* Buffer for the generated number string for the mantissa. The
107 maximal size for the mantissa is 64 bits. */
108 char numbuf[16];
109 char *numstr;
110 char *numend;
111 int negative;
113 /* The maximal exponent of two in decimal notation has 5 digits. */
114 char expbuf[5];
115 char *expstr;
116 int expnegative;
117 int exponent;
119 /* Non-zero is mantissa is zero. */
120 int zero_mantissa;
122 /* The leading digit before the decimal point. */
123 char leading;
125 /* Precision. */
126 int precision = info->prec;
128 /* Width. */
129 int width = info->width;
131 /* Number of characters written. */
132 int done = 0;
135 /* Figure out the decimal point character. */
136 if (info->extra == 0)
138 if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
139 strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
140 decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
142 else
144 if (mbtowc (&decimal, _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT),
145 strlen (_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT))) <= 0)
146 decimal = (wchar_t) *_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
148 /* Give default value. */
149 if (decimal == L'\0')
150 decimal = L'.';
153 /* Fetch the argument value. */
154 #ifndef __NO_LONG_DOUBLE_MATH
155 if (info->is_long_double && sizeof (long double) > sizeof (double))
157 fpnum.ldbl.d = *(const long double *) args[0];
159 /* Check for special values: not a number or infinity. */
160 if (__isnanl (fpnum.ldbl.d))
162 special = isupper (info->spec) ? "NAN" : "nan";
163 negative = 0;
165 else
167 if (__isinfl (fpnum.ldbl.d))
168 special = isupper (info->spec) ? "INF" : "inf";
170 negative = signbit (fpnum.ldbl.d);
173 else
174 #endif /* no long double */
176 fpnum.dbl.d = *(const double *) args[0];
178 /* Check for special values: not a number or infinity. */
179 if (__isnan (fpnum.dbl.d))
181 special = isupper (info->spec) ? "NAN" : "nan";
182 negative = 0;
184 else
186 if (__isinf (fpnum.dbl.d))
187 special = isupper (info->spec) ? "INF" : "inf";
189 negative = signbit (fpnum.dbl.d);
193 if (special)
195 int width = info->width;
197 if (negative || info->showsign || info->space)
198 --width;
199 width -= 3;
201 if (!info->left && width > 0)
202 PADN (' ', width);
204 if (negative)
205 outchar ('-');
206 else if (info->showsign)
207 outchar ('+');
208 else if (info->space)
209 outchar (' ');
211 PRINT (special, 3);
213 if (info->left && width > 0)
214 PADN (' ', width);
216 return done;
219 /* We are handling here only 64 and 80 bit IEEE foating point
220 numbers. */
221 if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
223 /* We have 52 bits of mantissa plus one implicit digit. Since
224 52 bits are representable without rest using hexadecimal
225 digits we use only the implicit digits for the number before
226 the decimal point. */
227 unsigned long long int num;
229 num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
230 | fpnum.dbl.ieee.mantissa1);
232 zero_mantissa = num == 0;
234 if (sizeof (unsigned long int) > 6)
235 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
236 info->spec == 'A');
237 else
238 numstr = _itoa (num, numbuf + sizeof numbuf, 16,
239 info->spec == 'A');
241 /* Fill with zeroes. */
242 while (numstr > numbuf + (sizeof numbuf - 52 / 4))
243 *--numstr = '0';
245 leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
247 exponent = fpnum.dbl.ieee.exponent;
249 if (exponent == 0)
251 if (zero_mantissa)
252 expnegative = 0;
253 else
255 /* This is a denormalized number. */
256 expnegative = 1;
257 exponent = -(1 - IEEE754_DOUBLE_BIAS);
260 else if (exponent >= IEEE754_DOUBLE_BIAS)
262 expnegative = 0;
263 exponent -= IEEE754_DOUBLE_BIAS;
265 else
267 expnegative = 1;
268 exponent = -(exponent - IEEE754_DOUBLE_BIAS);
271 else
273 /* The "strange" 80 bit format on ix86 and m68k has an explicit
274 leading digit in the 64 bit mantissa. */
275 unsigned long long int num;
277 assert (sizeof (long double) == 12);
279 num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32
280 | fpnum.ldbl.ieee.mantissa1);
282 zero_mantissa = num == 0;
284 if (sizeof (unsigned long int) > 6)
285 numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
286 info->spec == 'A');
287 else
288 numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A');
290 /* Fill with zeroes. */
291 while (numstr > numbuf + (sizeof numbuf - 64 / 4))
292 *--numstr = '0';
294 /* We use a full nibble for the leading digit. */
295 leading = *numstr++;
297 /* We have 3 bits from the mantissa in the leading nibble.
298 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'. */
299 exponent = fpnum.ldbl.ieee.exponent;
301 if (exponent == 0)
303 if (zero_mantissa)
304 expnegative = 0;
305 else
307 /* This is a denormalized number. */
308 expnegative = 1;
309 exponent = -(1 - (IEEE854_LONG_DOUBLE_BIAS + 3));
312 else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3)
314 expnegative = 0;
315 exponent -= IEEE854_LONG_DOUBLE_BIAS + 2;
317 else
319 expnegative = 1;
320 exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3));
324 /* Look for trailing zeroes. */
325 if (! zero_mantissa)
327 numend = numbuf + sizeof numbuf;
328 while (numend[-1] == '0')
329 --numend;
331 if (precision == -1)
332 precision = numend - numstr;
333 else if (precision < numend - numstr
334 && (numstr[precision] > '8'
335 || (('A' < '0' || 'a' < '0')
336 && numstr[precision] < '0')
337 || (numstr[precision] == '8'
338 && (precision + 1 < numend - numstr
339 /* Round to even. */
340 || (precision > 0
341 && ((numstr[precision - 1] & 1)
342 ^ (isdigit (numstr[precision - 1]) == 0)))
343 || (precision == 0
344 && ((leading & 1)
345 ^ (isdigit (leading) == 0)))))))
347 /* Round up. */
348 int cnt = precision;
349 while (--cnt >= 0)
351 char ch = numstr[cnt];
352 /* We assume that the digits and the letters are ordered
353 like in ASCII. This is true for the rest of GNU, too. */
354 if (ch == '9')
356 numstr[cnt] = info->spec; /* This is tricky,
357 think about it! */
358 break;
360 else if (tolower (ch) < 'f')
362 ++numstr[cnt];
363 break;
365 else
366 numstr[cnt] = '0';
368 if (cnt < 0)
370 /* The mantissa so far was fff...f Now increment the
371 leading digit. Here it is again possible that we
372 get an overflow. */
373 if (leading == '9')
374 leading = info->spec;
375 else if (tolower (leading) < 'f')
376 ++leading;
377 else
379 leading = 1;
380 if (expnegative)
382 exponent += 4;
383 if (exponent >= 0)
384 expnegative = 0;
386 else
387 exponent += 4;
392 else
393 numend = numstr;
395 /* Now we can compute the exponent string. */
396 expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
398 /* Now we have all information to compute the size. */
399 width -= ((negative || info->showsign || info->space)
400 /* Sign. */
401 + 2 + 1 + 1 + precision + 1 + 1
402 /* 0x h . hhh P ExpoSign. */
403 + ((expbuf + sizeof expbuf) - expstr));
404 /* Exponent. */
406 /* A special case if when the mantissa is zero and the `#' is not
407 given. In this case we must not print the decimal point. */
408 if (zero_mantissa && precision == 0 && !info->alt)
409 ++width; /* This nihilates the +1 for the decimal-point
410 character in the following equation. */
412 if (!info->left && width > 0)
413 PADN (' ', width);
415 if (negative)
416 outchar ('-');
417 else if (info->showsign)
418 outchar ('+');
419 else if (info->space)
420 outchar (' ');
422 outchar ('0');
423 outchar (info->spec == 'A' ? 'X' : 'x');
424 outchar (leading);
426 if (!zero_mantissa || precision > 0 || info->alt)
427 outchar (decimal);
429 if (!zero_mantissa || precision > 0)
431 PRINT (numstr, MIN (numend - numstr, precision));
432 if (precision > numend - numstr)
433 PADN ('0', precision - (numend - numstr));
436 if (info->left && info->pad == '0' && width > 0)
437 PADN ('0', width);
439 outchar (info->spec == 'A' ? 'P' : 'p');
441 outchar (expnegative ? '-' : '+');
443 PRINT (expstr, (expbuf + sizeof expbuf) - expstr);
445 if (info->left && info->pad != '0' && width > 0)
446 PADN (info->pad, width);
448 return done;