#ifdef out long double handling code if __NO_LONG_DOUBLE_MATH is
[kopensolaris-gnu/glibc.git] / stdio-common / printf_fphex.c
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.
6
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.
11
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.
16
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.  */
21
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>
31
32 /* #define NDEBUG 1*/           /* Undefine this for debugging assertions.  */
33 #include <assert.h>
34
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 */
52 \f
53 /* Macros for doing the actual output.  */
54
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)
63
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)
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 \f
86
87 int
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       union ieee854_long_double ldbl;
97     }
98   fpnum;
99
100   /* Locale-dependent representation of decimal point.  */
101   wchar_t decimal;
102
103   /* "NaN" or "Inf" for the special cases.  */
104   const char *special = NULL;
105
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;
112
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;
118
119   /* Non-zero is mantissa is zero.  */
120   int zero_mantissa;
121
122   /* The leading digit before the decimal point.  */
123   char leading;
124
125   /* Precision.  */
126   int precision = info->prec;
127
128   /* Width.  */
129   int width = info->width;
130
131   /* Number of characters written.  */
132   int done = 0;
133
134
135   /* Figure out the decimal point character.  */
136   if (info->extra == 0)
137     {
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);
141     }
142   else
143     {
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);
147     }
148   /* Give default value.  */
149   if (decimal == L'\0')
150     decimal = L'.';
151
152
153   /* Fetch the argument value.  */
154 #ifndef __NO_LONG_DOUBLE_MATH
155   if (info->is_long_double && sizeof (long double) > sizeof (double))
156     {
157       fpnum.ldbl.d = *(const long double *) args[0];
158
159       /* Check for special values: not a number or infinity.  */
160       if (__isnanl (fpnum.ldbl.d))
161         {
162           special = isupper (info->spec) ? "NAN" : "nan";
163           negative = 0;
164         }
165       else
166         {
167           if (__isinfl (fpnum.ldbl.d))
168             special = isupper (info->spec) ? "INF" : "inf";
169
170           negative = signbit (fpnum.ldbl.d);
171         }
172     }
173   else
174 #endif  /* no long double */
175     {
176       fpnum.dbl.d = *(const double *) args[0];
177
178       /* Check for special values: not a number or infinity.  */
179       if (__isnan (fpnum.dbl.d))
180         {
181           special = isupper (info->spec) ? "NAN" : "nan";
182           negative = 0;
183         }
184       else
185         {
186           if (__isinf (fpnum.dbl.d))
187             special = isupper (info->spec) ? "INF" : "inf";
188
189           negative = signbit (fpnum.dbl.d);
190         }
191     }
192
193   if (special)
194     {
195       int width = info->width;
196
197       if (negative || info->showsign || info->space)
198         --width;
199       width -= 3;
200
201       if (!info->left && width > 0)
202         PADN (' ', width);
203
204       if (negative)
205         outchar ('-');
206       else if (info->showsign)
207         outchar ('+');
208       else if (info->space)
209         outchar (' ');
210
211       PRINT (special, 3);
212
213       if (info->left && width > 0)
214         PADN (' ', width);
215
216       return done;
217     }
218
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))
222     {
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;
228
229       num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
230              | fpnum.dbl.ieee.mantissa1);
231
232       zero_mantissa = num == 0;
233
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');
240
241       /* Fill with zeroes.  */
242       while (numstr > numbuf + (sizeof numbuf - 52 / 4))
243         *--numstr = '0';
244
245       leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
246
247       exponent = fpnum.dbl.ieee.exponent;
248
249       if (exponent == 0)
250         {
251           if (zero_mantissa)
252             expnegative = 0;
253           else
254             {
255               /* This is a denormalized number.  */
256               expnegative = 1;
257               exponent = -(1 - IEEE754_DOUBLE_BIAS);
258             }
259         }
260       else if (exponent >= IEEE754_DOUBLE_BIAS)
261         {
262           expnegative = 0;
263           exponent -= IEEE754_DOUBLE_BIAS;
264         }
265       else
266         {
267           expnegative = 1;
268           exponent = -(exponent - IEEE754_DOUBLE_BIAS);
269         }
270     }
271   else
272     {
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;
276
277       assert (sizeof (long double) == 12);
278
279       num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32
280              | fpnum.ldbl.ieee.mantissa1);
281
282       zero_mantissa = num == 0;
283
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');
289
290       /* Fill with zeroes.  */
291       while (numstr > numbuf + (sizeof numbuf - 64 / 4))
292         *--numstr = '0';
293
294       /* We use a full nibble for the leading digit.  */
295       leading = *numstr++;
296
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;
300
301       if (exponent == 0)
302         {
303           if (zero_mantissa)
304             expnegative = 0;
305           else
306             {
307               /* This is a denormalized number.  */
308               expnegative = 1;
309               exponent = -(1 - (IEEE854_LONG_DOUBLE_BIAS + 3));
310             }
311         }
312       else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3)
313         {
314           expnegative = 0;
315           exponent -= IEEE854_LONG_DOUBLE_BIAS + 2;
316         }
317       else
318         {
319           expnegative = 1;
320           exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3));
321         }
322     }
323
324   /* Look for trailing zeroes.  */
325   if (! zero_mantissa)
326     {
327       numend = numbuf + sizeof numbuf;
328       while (numend[-1] == '0')
329         --numend;
330
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)))))))
346         {
347           /* Round up.  */
348           int cnt = precision;
349           while (--cnt >= 0)
350             {
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')
355                 {
356                   numstr[cnt] = info->spec;     /* This is tricky,
357                                                    think about it!  */
358                   break;
359                 }
360               else if (tolower (ch) < 'f')
361                 {
362                   ++numstr[cnt];
363                   break;
364                 }
365               else
366                 numstr[cnt] = '0';
367             }
368           if (cnt < 0)
369             {
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
378                 {
379                   leading = 1;
380                   if (expnegative)
381                     {
382                       exponent += 4;
383                       if (exponent >= 0)
384                         expnegative = 0;
385                     }
386                   else
387                     exponent += 4;
388                 }
389             }
390         }
391     }
392   else
393     numend = numstr;
394
395   /* Now we can compute the exponent string.  */
396   expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
397
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.  */
405
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.  */
411
412   if (!info->left && width > 0)
413     PADN (' ', width);
414
415   if (negative)
416     outchar ('-');
417   else if (info->showsign)
418     outchar ('+');
419   else if (info->space)
420     outchar (' ');
421
422   outchar ('0');
423   outchar (info->spec == 'A' ? 'X' : 'x');
424   outchar (leading);
425
426   if (!zero_mantissa || precision > 0 || info->alt)
427     outchar (decimal);
428
429   if (!zero_mantissa || precision > 0)
430     {
431       PRINT (numstr, MIN (numend - numstr, precision));
432       if (precision > numend - numstr)
433         PADN ('0', precision - (numend - numstr));
434     }
435
436   if (info->left && info->pad == '0' && width > 0)
437     PADN ('0', width);
438
439   outchar (info->spec == 'A' ? 'P' : 'p');
440
441   outchar (expnegative ? '-' : '+');
442
443   PRINT (expstr, (expbuf + sizeof expbuf) - expstr);
444
445   if (info->left && info->pad != '0' && width > 0)
446     PADN (info->pad, width);
447
448   return done;
449 }