Include <string.h>.
[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 <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   if (info->is_long_double && sizeof (long double) > sizeof (double))
155     {
156       fpnum.ldbl.d = *(const long double *) args[0];
157
158       /* Check for special values: not a number or infinity.  */
159       if (__isnanl (fpnum.ldbl.d))
160         {
161           special = isupper (info->spec) ? "NAN" : "nan";
162           negative = 0;
163         }
164       else
165         {
166           if (__isinfl (fpnum.ldbl.d))
167             special = isupper (info->spec) ? "INF" : "inf";
168
169           negative = fpnum.ldbl.d < 0;
170         }
171     }
172   else
173     {
174       fpnum.dbl.d = *(const double *) args[0];
175
176       /* Check for special values: not a number or infinity.  */
177       if (__isnan (fpnum.dbl.d))
178         {
179           special = isupper (info->spec) ? "NAN" : "nan";
180           negative = 0;
181         }
182       else
183         {
184           if (__isinf (fpnum.dbl.d))
185             special = isupper (info->spec) ? "INF" : "inf";
186
187           negative = fpnum.dbl.d < 0;
188         }
189     }
190
191   if (special)
192     {
193       int width = info->width;
194
195       if (negative || info->showsign || info->space)
196         --width;
197       width -= 3;
198
199       if (!info->left && width > 0)
200         PADN (' ', width);
201
202       if (negative)
203         outchar ('-');
204       else if (info->showsign)
205         outchar ('+');
206       else if (info->space)
207         outchar (' ');
208
209       PRINT (special, 3);
210
211       if (info->left && width > 0)
212         PADN (' ', width);
213
214       return done;
215     }
216
217   /* We are handling here only 64 and 80 bit IEEE foating point
218      numbers.  */
219   if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
220     {
221       /* We have 52 bits of mantissa plus one implicit digit.  Since
222          52 bits are representable without rest using hexadecimal
223          digits we use only the implicit digits for the number before
224          the decimal point.  */
225       unsigned long long int num;
226
227       num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
228              | fpnum.dbl.ieee.mantissa1);
229
230       zero_mantissa = num == 0;
231
232       if (sizeof (unsigned long int) > 6)
233         numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
234                              info->spec == 'A');
235       else
236         numstr = _itoa (num, numbuf + sizeof numbuf, 16,
237                         info->spec == 'A');
238
239       /* Fill with zeroes.  */
240       while (numstr > numbuf + (sizeof numbuf - 13))    /* 52 ÷ 4 = 13 */
241         *--numstr = '0';
242
243       leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
244
245       exponent = fpnum.dbl.ieee.exponent;
246
247       if ((exponent != 0 && exponent < IEEE754_DOUBLE_BIAS)
248           || (exponent == 0 && !zero_mantissa))
249         {
250           expnegative = 1;
251           exponent = abs (exponent - IEEE754_DOUBLE_BIAS);
252         }
253       else
254         {
255           expnegative = 0;
256           if (exponent != 0)
257             exponent -= IEEE754_DOUBLE_BIAS;
258         }
259     }
260   else
261     {
262       /* The "strange" 80 bit format on ix86 and m68k has an explicit
263          leading digit in the 64 bit mantissa.  */
264       unsigned long long int num;
265
266       assert (sizeof (long double) == 12);
267
268       num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32
269              | fpnum.ldbl.ieee.mantissa1);
270
271       zero_mantissa = num == 0;
272
273       if (sizeof (unsigned long int) > 6)
274         numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
275                              info->spec == 'A');
276       else
277         numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A');
278
279       /* We use a full nibble for the leading digit.  */
280       leading = *numstr++;
281
282       /* Fill with zeroes.  */
283       while (numstr > numbuf + (sizeof numbuf - 15))    /* 60 ÷ 4 = 15 */
284         *--numstr = '0';
285
286       /* We have 3 bits from the mantissa in the leading nibble.  */
287       exponent = fpnum.ldbl.ieee.exponent - 3;
288
289       if ((exponent != 0 && exponent < IEEE854_LONG_DOUBLE_BIAS)
290           || (exponent == 0 && !zero_mantissa))
291         {
292           expnegative = 1;
293           exponent = abs (exponent - IEEE854_LONG_DOUBLE_BIAS);
294         }
295       else
296         {
297           expnegative = 0;
298           if (exponent != 0)
299             exponent -= IEEE854_LONG_DOUBLE_BIAS;
300         }
301     }
302
303   /* Look for trailing zeroes.  */
304   if (! zero_mantissa)
305     {
306       numend = numbuf + sizeof numbuf;
307       while (numend[-1] == '0')
308         --numend;
309
310       if (precision == -1)
311         precision = numend - numstr;
312       else if (precision < numend - numstr
313                && (numstr[precision] > 5
314                    || (numstr[precision] == 5
315                        && (precision + 1 < numend - numstr
316                            /* Round to even.  */
317                            || (precision > 0
318                                && ((numstr[precision - 1] & 1)
319                                    ^ (isdigit (numstr[precision - 1]) == 0)))
320                            || (precision == 0
321                                && ((leading & 1)
322                                    ^ (isdigit (leading) == 0)))))))
323         {
324           /* Round up.  */
325           int cnt = precision;
326           while (--cnt >= 0)
327             {
328               char ch = numstr[cnt];
329               /* We assume that the digits and the letters are ordered
330                  like in ASCII.  This is true for the rest of GNU, too.  */
331               if (ch == '9')
332                 {
333                   numstr[cnt] = info->spec;     /* This is tricky,
334                                                    think about it!  */
335                   break;
336                 }
337               else if (tolower (ch) < 'f')
338                 {
339                   ++numstr[cnt];
340                   break;
341                 }
342               else
343                 numstr[cnt] = '0';
344             }
345           if (cnt < 0)
346             {
347               /* The mantissa so far was fff...f  Now increment the
348                  leading digit.  Here it is again possible that we
349                  get an overflow.  */
350               if (leading == '9')
351                 leading = info->spec;
352               else if (tolower (leading) < 'f')
353                 ++leading;
354               else
355                 {
356                   leading = 1;
357                   if (expnegative)
358                     {
359                       exponent += 4;
360                       if (exponent >= 0)
361                         expnegative = 0;
362                     }
363                   else
364                     exponent += 4;
365                 }
366             }
367         }
368     }
369   else
370     numend = numstr;
371
372   /* Now we can compute the exponent string.  */
373   expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
374
375   /* Now we have all information to compute the size.  */
376   width -= ((negative || info->showsign || info->space)
377             /* Sign.  */
378             + 2    + 1 + 1 + precision + 1 + 1
379             /* 0x    h   .   hhh         P   ExpoSign.  */
380             + ((expbuf + sizeof expbuf) - expstr));
381             /* Exponent.  */
382
383   /* A special case if when the mantissa is zero and the `#' is not
384      given.  In this case we must not print the decimal point.  */
385   if (zero_mantissa && precision == 0 && !info->alt)
386     ++width;            /* This nihilates the +1 for the decimal-point
387                            character in the following equation.  */
388
389   if (!info->left && width > 0)
390     PADN (' ', width);
391
392   if (negative)
393     outchar ('-');
394   else if (info->showsign)
395     outchar ('+');
396   else if (info->space)
397     outchar (' ');
398
399   outchar ('0');
400   outchar (info->spec == 'A' ? 'X' : 'x');
401   outchar (leading);
402
403   if (!zero_mantissa || precision > 0 || info->alt)
404     outchar (decimal);
405
406   if (!zero_mantissa || precision > 0)
407     {
408       PRINT (numstr, MIN (numend - numstr, precision));
409       if (precision > numend - numstr)
410         PADN ('0', precision - (numend - numstr));
411     }
412
413   if (info->left && info->pad == '0' && width > 0)
414     PADN ('0', width);
415
416   outchar (info->spec == 'A' ? 'P' : 'p');
417
418   outchar (expnegative ? '-' : '+');
419
420   PRINT (expstr, (expbuf + sizeof expbuf) - expstr);
421
422   if (info->left && info->pad != '0' && width > 0)
423     PADN (info->pad, width);
424
425   return done;
426 }