(MIN): New macro.
[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 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 "_itoa.h"
29 #include "../locale/localeinfo.h"
30
31 /* #define NDEBUG 1*/           /* Undefine this for debugging assertions.  */
32 #include <assert.h>
33
34 /* This defines make it possible to use the same code for GNU C library and
35    the GNU I/O library.  */
36 #ifdef USE_IN_LIBIO
37 # include <libioP.h>
38 # define PUT(f, s, n) _IO_sputn (f, s, n)
39 # define PAD(f, c, n) _IO_padn (f, c, n)
40 /* We use this file GNU C library and GNU I/O library.  So make
41    names equal.  */
42 # undef putc
43 # define putc(c, f) _IO_putc_unlocked (c, f)
44 # define size_t     _IO_size_t
45 # define FILE        _IO_FILE
46 #else   /* ! USE_IN_LIBIO */
47 # define PUT(f, s, n) fwrite (s, 1, n, f)
48 # define PAD(f, c, n) __printf_pad (f, c, n)
49 ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c.  */
50 #endif  /* USE_IN_LIBIO */
51 \f
52 /* Macros for doing the actual output.  */
53
54 #define outchar(ch)                                                           \
55   do                                                                          \
56     {                                                                         \
57       register const int outc = (ch);                                         \
58       if (putc (outc, fp) == EOF)                                             \
59         return -1;                                                            \
60       ++done;                                                                 \
61     } while (0)
62
63 #define PRINT(ptr, len)                                                       \
64   do                                                                          \
65     {                                                                         \
66        int outlen = (len);                                                    \
67        const char *cp = (ptr);                                                \
68        while (outlen-- > 0)                                                   \
69          outchar (*cp++);                                                     \
70     } while (0)
71
72 #define PADN(ch, len)                                                         \
73   do                                                                          \
74     {                                                                         \
75       if (PAD (fp, ch, len) != len)                                           \
76         return -1;                                                            \
77       done += len;                                                            \
78     }                                                                         \
79   while (0)
80
81 #ifndef MIN
82 # define MIN(a,b) ((a)<(b)?(a):(b))
83 #endif
84 \f
85
86 int
87 __printf_fphex (FILE *fp,
88                 const struct printf_info *info,
89                 const void *const *args)
90 {
91   /* The floating-point value to output.  */
92   union
93     {
94       union ieee754_double dbl;
95       union ieee854_long_double ldbl;
96     }
97   fpnum;
98
99   /* Locale-dependent representation of decimal point.  */
100   wchar_t decimal;
101
102   /* "NaN" or "Inf" for the special cases.  */
103   const char *special = NULL;
104
105   /* Buffer for the generated number string for the mantissa.  The
106      maximal size for the mantissa is 64 bits.  */
107   char numbuf[16];
108   char *numstr;
109   char *numend;
110   int negative;
111
112   /* The maximal exponent of two in decimal notation has 5 digits.  */
113   char expbuf[5];
114   char *expstr;
115   int expnegative;
116   int exponent;
117
118   /* Non-zero is mantissa is zero.  */
119   int zero_mantissa;
120
121   /* The leading digit before the decimal point.  */
122   char leading;
123
124   /* Precision.  */
125   int precision = info->prec;
126
127   /* Width.  */
128   int width = info->width;
129
130   /* Number of characters written.  */
131   int done = 0;
132
133
134   /* Figure out the decimal point character.  */
135   if (info->extra == 0)
136     {
137       if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
138                   strlen (_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT))) <= 0)
139         decimal = (wchar_t) *_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
140     }
141   else
142     {
143       if (mbtowc (&decimal, _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT),
144                   strlen (_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT))) <= 0)
145         decimal = (wchar_t) *_NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
146     }
147   /* Give default value.  */
148   if (decimal == L'\0')
149     decimal = L'.';
150
151
152   /* Fetch the argument value.  */
153   if (info->is_long_double && sizeof (long double) > sizeof (double))
154     {
155       fpnum.ldbl.d = *(const long double *) args[0];
156
157       /* Check for special values: not a number or infinity.  */
158       if (__isnanl (fpnum.ldbl.d))
159         {
160           special = isupper (info->spec) ? "NAN" : "nan";
161           negative = 0;
162         }
163       else
164         {
165           if (__isinfl (fpnum.ldbl.d))
166             special = isupper (info->spec) ? "INF" : "inf";
167
168           negative = fpnum.ldbl.d < 0;
169         }
170     }
171   else
172     {
173       fpnum.dbl.d = *(const double *) args[0];
174
175       /* Check for special values: not a number or infinity.  */
176       if (__isnan (fpnum.dbl.d))
177         {
178           special = isupper (info->spec) ? "NAN" : "nan";
179           negative = 0;
180         }
181       else
182         {
183           if (__isinf (fpnum.dbl.d))
184             special = isupper (info->spec) ? "INF" : "inf";
185
186           negative = fpnum.dbl.d < 0;
187         }
188     }
189
190   if (special)
191     {
192       int width = info->prec > info->width ? info->prec : info->width;
193
194       if (negative || info->showsign || info->space)
195         --width;
196       width -= 3;
197
198       if (!info->left && width > 0)
199         PADN (' ', width);
200
201       if (negative)
202         outchar ('-');
203       else if (info->showsign)
204         outchar ('+');
205       else if (info->space)
206         outchar (' ');
207
208       PRINT (special, 3);
209
210       if (info->left && width > 0)
211         PADN (' ', width);
212
213       return done;
214     }
215
216   /* We are handling here only 64 and 80 bit IEEE foating point
217      numbers.  */
218   if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
219     {
220       /* We have 52 bits of mantissa plus one implicit digit.  Since
221          52 bits are representable without rest using hexadecimal
222          digits we use only the implicit digits for the number before
223          the decimal point.  */
224       unsigned long long int num;
225
226       num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
227              | fpnum.dbl.ieee.mantissa1);
228
229       zero_mantissa = num == 0;
230
231       if (sizeof (unsigned long int) > 6)
232         numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
233                              info->spec == 'A');
234       else
235         numstr = _itoa (num, numbuf + sizeof numbuf, 16,
236                         info->spec == 'A');
237
238       /* Fill with zeroes.  */
239       while (numstr > numbuf + (sizeof numbuf - 13))    /* 52 ÷ 4 = 13 */
240         *--numstr = '0';
241
242       leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
243
244       exponent = fpnum.dbl.ieee.exponent;
245
246       if ((exponent != 0 && exponent < IEEE754_DOUBLE_BIAS)
247           || (exponent == 0 && !zero_mantissa))
248         {
249           expnegative = 1;
250           exponent = abs (exponent - IEEE754_DOUBLE_BIAS);
251         }
252       else
253         {
254           expnegative = 0;
255           if (exponent != 0)
256             exponent -= IEEE754_DOUBLE_BIAS;
257         }
258     }
259   else
260     {
261       /* The "strange" 80 bit format on ix86 and m68k has an explicit
262          leading digit in the 64 bit mantissa.  */
263       unsigned long long int num;
264
265       assert (sizeof (long double) == 12);
266
267       num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32
268              | fpnum.ldbl.ieee.mantissa1);
269
270       zero_mantissa = num == 0;
271
272       if (sizeof (unsigned long int) > 6)
273         numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
274                              info->spec == 'A');
275       else
276         numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A');
277
278       /* We use a full nibble for the leading digit.  */
279       leading = *numstr++;
280
281       /* Fill with zeroes.  */
282       while (numstr > numbuf + (sizeof numbuf - 15))    /* 60 ÷ 4 = 15 */
283         *--numstr = '0';
284
285       /* We have 3 bits from the mantissa in the leading nibble.  */
286       exponent = fpnum.ldbl.ieee.exponent - 3;
287
288       if ((exponent != 0 && exponent < IEEE854_LONG_DOUBLE_BIAS)
289           || (exponent == 0 && !zero_mantissa))
290         {
291           expnegative = 1;
292           exponent = abs (exponent - IEEE854_LONG_DOUBLE_BIAS);
293         }
294       else
295         {
296           expnegative = 0;
297           if (exponent != 0)
298             exponent -= IEEE854_LONG_DOUBLE_BIAS;
299         }
300     }
301
302   /* Look for trailing zeroes.  */
303   if (! zero_mantissa)
304     {
305       numend = numbuf + sizeof numbuf;
306       while (numend[-1] == '0')
307         --numend;
308
309       if (precision == -1)
310         precision = numend - numstr;
311       else if (precision < numend - numstr
312                && (numstr[precision] > 5
313                    || (numstr[precision] == 5
314                        && (precision + 1 < numend - numstr
315                            /* Round to even.  */
316                            || (precision > 0
317                                && ((numstr[precision - 1] & 1)
318                                    ^ (isdigit (numstr[precision - 1]) == 0)))
319                            || (precision == 0
320                                && ((leading & 1)
321                                    ^ (isdigit (leading) == 0)))))))
322         {
323           /* Round up.  */
324           int cnt = precision;
325           while (--cnt >= 0)
326             {
327               char ch = numstr[cnt];
328               /* We assume that the digits and the letters are ordered
329                  like in ASCII.  This is true for the rest of GNU, too.  */
330               if (ch == '9')
331                 {
332                   numstr[cnt] = info->spec;     /* This is tricky,
333                                                    think about it!  */
334                   break;
335                 }
336               else if (tolower (ch) < 'f')
337                 {
338                   ++numstr[cnt];
339                   break;
340                 }
341               else
342                 numstr[cnt] = '0';
343             }
344           if (cnt < 0)
345             {
346               /* The mantissa so far was fff...f  Now increment the
347                  leading digit.  Here it is again possible that we
348                  get an overflow.  */
349               if (leading == '9')
350                 leading = info->spec;
351               else if (tolower (leading) < 'f')
352                 ++leading;
353               else
354                 {
355                   leading = 1;
356                   if (expnegative)
357                     {
358                       exponent += 4;
359                       if (exponent >= 0)
360                         expnegative = 0;
361                     }
362                   else
363                     exponent += 4;
364                 }
365             }
366         }
367     }
368   else
369     numend = numstr;
370
371   /* Now we can compute the exponent string.  */
372   expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
373
374   /* Now we have all information to compute the size.  */
375   width -= ((negative || info->showsign || info->space)
376             /* Sign.  */
377             + 2    + 1 + 1 + precision + 1 + 1
378             /* 0x    h   .   hhh         P   ExpoSign.  */
379             + ((expbuf + sizeof expbuf) - expstr));
380             /* Exponent.  */
381
382   /* A special case if when the mantissa is zero and the `#' is not
383      given.  In this case we must not print the decimal point.  */
384   if (zero_mantissa && precision == 0 && !info->alt)
385     ++width;            /* This nihilates the +1 for the decimal-point
386                            character in the following equation.  */
387
388   if (!info->left && width > 0)
389     PADN (' ', width);
390
391   if (negative)
392     outchar ('-');
393   else if (info->showsign)
394     outchar ('+');
395   else if (info->space)
396     outchar (' ');
397
398   outchar ('0');
399   outchar (info->spec == 'A' ? 'X' : 'x');
400   outchar (leading);
401
402   if (!zero_mantissa || precision > 0 || info->alt)
403     outchar (decimal);
404
405   if (!zero_mantissa || precision > 0)
406     {
407       PRINT (numstr, MIN (numend - numstr, precision));
408       if (precision > numend - numstr)
409         PADN ('0', precision - (numend - numstr));
410     }
411
412   if (info->left && info->pad == '0' && width > 0)
413     PADN ('0', width);
414
415   outchar (info->spec == 'A' ? 'P' : 'p');
416
417   outchar (expnegative ? '-' : '+');
418
419   PRINT (expstr, (expbuf + sizeof expbuf) - expstr);
420
421   if (info->left && info->pad != '0' && width > 0)
422     PADN (info->pad, width);
423
424   return done;
425 }