1/* Print floating point number in hexadecimal notation according to ISO C99.
2   Copyright (C) 1997-2002,2004,2006 Free Software Foundation, Inc.
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
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.
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
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with the GNU C Library; if not, write to the Free
18   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   02111-1307 USA.  */
20
21#include <ctype.h>
22#include <ieee754.h>
23#include <math.h>
24#include <printf.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28#include <wchar.h>
29#include "_itoa.h"
30#include "_itowa.h"
31#include <locale/localeinfo.h>
32
33/* #define NDEBUG 1*/		/* Undefine this for debugging assertions.  */
34#include <assert.h>
35
36int __printf_fphex (FILE *fp, const struct printf_info *info,
37		const void *const *args);
38
39/* This defines make it possible to use the same code for GNU C library and
40   the GNU I/O library.	 */
41#ifdef USE_IN_LIBIO
42# include <libioP.h>
43# define PUT(f, s, n) _IO_sputn (f, s, n)
44# define PAD(f, c, n) (wide ? _IO_wpadn (f, c, n) : _IO_padn (f, c, n))
45/* We use this file GNU C library and GNU I/O library.	So make
46   names equal.	 */
47# undef putc
48# define putc(c, f) (wide \
49		     ? (int)_IO_putwc_unlocked (c, f) : _IO_putc_unlocked (c, f))
50# define size_t     _IO_size_t
51# define FILE	     _IO_FILE
52#else	/* ! USE_IN_LIBIO */
53# define PUT(f, s, n) fwrite (s, 1, n, f)
54# define PAD(f, c, n) __printf_pad (f, c, n)
55ssize_t __printf_pad __P ((FILE *, char pad, int n)); /* In vfprintf.c.  */
56#endif	/* USE_IN_LIBIO */
57
58/* Macros for doing the actual output.  */
59
60#define outchar(ch)							      \
61  do									      \
62    {									      \
63      register const int outc = (ch);					      \
64      if (putc (outc, fp) == EOF)					      \
65	return -1;							      \
66      ++done;								      \
67    } while (0)
68
69#define PRINT(ptr, wptr, len)						      \
70  do									      \
71    {									      \
72      register size_t outlen = (len);					      \
73      if (wide)								      \
74	while (outlen-- > 0)						      \
75	  outchar (*wptr++);						      \
76      else								      \
77	while (outlen-- > 0)						      \
78	  outchar (*ptr++);						      \
79    } while (0)
80
81#define PADN(ch, len)							      \
82  do									      \
83    {									      \
84      if (PAD (fp, ch, len) != len)					      \
85	return -1;							      \
86      done += len;							      \
87    }									      \
88  while (0)
89
90#ifndef MIN
91# define MIN(a,b) ((a)<(b)?(a):(b))
92#endif
93
94
95
96#if defined(__x86_64__) || defined(__i386__)
97
98/* sysdeps/x86_64/fpu/printf_fphex.c */
99
100#ifndef LONG_DOUBLE_DENORM_BIAS
101# define LONG_DOUBLE_DENORM_BIAS (IEEE854_LONG_DOUBLE_BIAS - 1)
102#endif
103
104#define PRINT_FPHEX_LONG_DOUBLE \
105do {									      \
106      /* The "strange" 80 bit format on ix86 and m68k has an explicit	      \
107	 leading digit in the 64 bit mantissa.  */			      \
108      unsigned long long int num;					      \
109									      \
110									      \
111      num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32	      \
112	     | fpnum.ldbl.ieee.mantissa1);				      \
113									      \
114      zero_mantissa = num == 0;						      \
115									      \
116      if (sizeof (unsigned long int) > 6)				      \
117	{								      \
118	  numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,		      \
119			       info->spec == 'A');			      \
120	  wnumstr = _itowa_word (num,					      \
121				 wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),\
122				 16, info->spec == 'A');		      \
123	}								      \
124      else								      \
125	{								      \
126	  numstr = _itoa (num, numbuf + sizeof numbuf, 16, info->spec == 'A');\
127	  wnumstr = _itowa (num,					      \
128			    wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),    \
129			    16, info->spec == 'A');			      \
130	}								      \
131									      \
132      /* Fill with zeroes.  */						      \
133      while (numstr > numbuf + (sizeof numbuf - 64 / 4))		      \
134	{								      \
135	  *--numstr = '0';						      \
136	  *--wnumstr = L'0';						      \
137	}								      \
138									      \
139      /* We use a full nibble for the leading digit.  */		      \
140      leading = *numstr++;						      \
141									      \
142      /* We have 3 bits from the mantissa in the leading nibble.	      \
143	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
144      exponent = fpnum.ldbl.ieee.exponent;				      \
145									      \
146      if (exponent == 0)						      \
147	{								      \
148	  if (zero_mantissa)						      \
149	    expnegative = 0;						      \
150	  else								      \
151	    {								      \
152	      /* This is a denormalized number.  */			      \
153	      expnegative = 1;						      \
154	      /* This is a hook for the m68k long double format, where the    \
155		 exponent bias is the same for normalized and denormalized    \
156		 numbers.  */						      \
157	      exponent = LONG_DOUBLE_DENORM_BIAS + 3;			      \
158	    }								      \
159	}								      \
160      else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3)		      \
161	{								      \
162	  expnegative = 0;						      \
163	  exponent -= IEEE854_LONG_DOUBLE_BIAS + 3;			      \
164	}								      \
165      else								      \
166	{								      \
167	  expnegative = 1;						      \
168	  exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3));	      \
169	}								      \
170} while (0)
171
172#endif	/* __x86_64__ || __i386__ */
173
174
175int
176__printf_fphex (FILE *fp,
177		const struct printf_info *info,
178		const void *const *args)
179{
180  /* The floating-point value to output.  */
181  union
182    {
183      union ieee754_double dbl;
184      union ieee854_long_double ldbl;
185    }
186  fpnum;
187
188  /* Locale-dependent representation of decimal point.	*/
189  const char *decimal;
190  wchar_t decimalwc;
191
192  /* "NaN" or "Inf" for the special cases.  */
193  const char *special = NULL;
194  const wchar_t *wspecial = NULL;
195
196  /* Buffer for the generated number string for the mantissa.  The
197     maximal size for the mantissa is 128 bits.  */
198  char numbuf[32];
199  char *numstr="";
200  char *numend;
201  wchar_t wnumbuf[32];
202  wchar_t *wnumstr=L"";
203  wchar_t *wnumend;
204  int negative;
205
206  /* The maximal exponent of two in decimal notation has 5 digits.  */
207  char expbuf[5];
208  char *expstr;
209  wchar_t wexpbuf[5];
210  wchar_t *wexpstr;
211  int expnegative = 0;
212  int exponent = 0;
213
214  /* Non-zero is mantissa is zero.  */
215  int zero_mantissa = 1;
216
217  /* The leading digit before the decimal point.  */
218  char leading = '0';
219
220  /* Precision.  */
221  int precision = info->prec;
222
223  /* Width.  */
224  int width = info->width;
225
226  /* Number of characters written.  */
227  int done = 0;
228
229  /* Nonzero if this is output on a wide character stream.  */
230  int wide = info->wide;
231
232
233  /* Figure out the decimal point character.  */
234  if (info->extra == 0)
235    {
236      decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
237      decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
238    }
239  else
240    {
241      decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
242      decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
243				    _NL_MONETARY_DECIMAL_POINT_WC);
244    }
245  /* The decimal point character must never be zero.  */
246  assert (*decimal != '\0' && decimalwc != L'\0');
247
248
249  /* Fetch the argument value.	*/
250#ifndef __NO_LONG_DOUBLE_MATH
251  if (info->is_long_double && sizeof (long double) > sizeof (double))
252    {
253      fpnum.ldbl.d = *(const long double *) args[0];
254
255      /* Check for special values: not a number or infinity.  */
256      if (isnanl (fpnum.ldbl.d))
257	{
258	  if (isupper (info->spec))
259	    {
260	      special = "NAN";
261	      wspecial = L"NAN";
262	    }
263	  else
264	    {
265	      special = "nan";
266	      wspecial = L"nan";
267	    }
268	  negative = 0;
269	}
270      else
271	{
272	  if (isinfl (fpnum.ldbl.d))
273	    {
274	      if (isupper (info->spec))
275		{
276		  special = "INF";
277		  wspecial = L"INF";
278		}
279	      else
280		{
281		  special = "inf";
282		  wspecial = L"inf";
283		}
284	    }
285
286	  negative = signbit (fpnum.ldbl.d);
287	}
288    }
289  else
290#endif	/* no long double */
291    {
292      fpnum.dbl.d = *(const double *) args[0];
293
294      /* Check for special values: not a number or infinity.  */
295      if (isnan (fpnum.dbl.d))
296	{
297	  if (isupper (info->spec))
298	    {
299	      special = "NAN";
300	      wspecial = L"NAN";
301	    }
302	  else
303	    {
304	      special = "nan";
305	      wspecial = L"nan";
306	    }
307	  negative = 0;
308	}
309      else
310	{
311	  if (isinf (fpnum.dbl.d))
312	    {
313	      if (isupper (info->spec))
314		{
315		  special = "INF";
316		  wspecial = L"INF";
317		}
318	      else
319		{
320		  special = "inf";
321		  wspecial = L"inf";
322		}
323	    }
324
325	  negative = signbit (fpnum.dbl.d);
326	}
327    }
328
329  if (special)
330    {
331      int width = info->width;
332
333      if (negative || info->showsign || info->space)
334	--width;
335      width -= 3;
336
337      if (!info->left && width > 0)
338	PADN (' ', width);
339
340      if (negative)
341	outchar ('-');
342      else if (info->showsign)
343	outchar ('+');
344      else if (info->space)
345	outchar (' ');
346
347      PRINT (special, wspecial, 3);
348
349      if (info->left && width > 0)
350	PADN (' ', width);
351
352      return done;
353    }
354
355  if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
356    {
357      /* We have 52 bits of mantissa plus one implicit digit.  Since
358	 52 bits are representable without rest using hexadecimal
359	 digits we use only the implicit digits for the number before
360	 the decimal point.  */
361      unsigned long long int num;
362
363      num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
364	     | fpnum.dbl.ieee.mantissa1);
365
366      zero_mantissa = num == 0;
367
368      if (sizeof (unsigned long int) > 6)
369	{
370	  wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
371				 info->spec == 'A');
372	  numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
373			       info->spec == 'A');
374	}
375      else
376	{
377	  wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
378			    info->spec == 'A');
379	  numstr = _itoa (num, numbuf + sizeof numbuf, 16,
380			  info->spec == 'A');
381	}
382
383      /* Fill with zeroes.  */
384      while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
385	{
386	  *--wnumstr = L'0';
387	  *--numstr = '0';
388	}
389
390      leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
391
392      exponent = fpnum.dbl.ieee.exponent;
393
394      if (exponent == 0)
395	{
396	  if (zero_mantissa)
397	    expnegative = 0;
398	  else
399	    {
400	      /* This is a denormalized number.  */
401	      expnegative = 1;
402	      exponent = IEEE754_DOUBLE_BIAS - 1;
403	    }
404	}
405      else if (exponent >= IEEE754_DOUBLE_BIAS)
406	{
407	  expnegative = 0;
408	  exponent -= IEEE754_DOUBLE_BIAS;
409	}
410      else
411	{
412	  expnegative = 1;
413	  exponent = -(exponent - IEEE754_DOUBLE_BIAS);
414	}
415    }
416#ifdef PRINT_FPHEX_LONG_DOUBLE
417  else
418    PRINT_FPHEX_LONG_DOUBLE;
419#endif
420
421  /* Look for trailing zeroes.  */
422  if (! zero_mantissa)
423    {
424      wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
425      numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
426      while (wnumend[-1] == L'0')
427	{
428	  --wnumend;
429	  --numend;
430	}
431
432      if (precision == -1)
433	precision = numend - numstr;
434      else if (precision < numend - numstr
435	       && (numstr[precision] > '8'
436		   || (('A' < '0' || 'a' < '0')
437		       && numstr[precision] < '0')
438		   || (numstr[precision] == '8'
439		       && (precision + 1 < numend - numstr
440			   /* Round to even.  */
441			   || (precision > 0
442			       && ((numstr[precision - 1] & 1)
443				   ^ (isdigit (numstr[precision - 1]) == 0)))
444			   || (precision == 0
445			       && ((leading & 1)
446				   ^ (isdigit (leading) == 0)))))))
447	{
448	  /* Round up.  */
449	  int cnt = precision;
450	  while (--cnt >= 0)
451	    {
452	      char ch = numstr[cnt];
453	      /* We assume that the digits and the letters are ordered
454		 like in ASCII.  This is true for the rest of GNU, too.  */
455	      if (ch == '9')
456		{
457		  wnumstr[cnt] = (wchar_t) info->spec;
458		  numstr[cnt] = info->spec;	/* This is tricky,
459		  				   think about it!  */
460		  break;
461		}
462	      else if (tolower (ch) < 'f')
463		{
464		  ++numstr[cnt];
465		  ++wnumstr[cnt];
466		  break;
467		}
468	      else
469		{
470		  numstr[cnt] = '0';
471		  wnumstr[cnt] = L'0';
472		}
473	    }
474	  if (cnt < 0)
475	    {
476	      /* The mantissa so far was fff...f  Now increment the
477		 leading digit.  Here it is again possible that we
478		 get an overflow.  */
479	      if (leading == '9')
480		leading = info->spec;
481	      else if (tolower (leading) < 'f')
482		++leading;
483	      else
484		{
485		  leading = '1';
486		  if (expnegative)
487		    {
488		      exponent -= 4;
489		      if (exponent <= 0)
490			{
491			  exponent = -exponent;
492			  expnegative = 0;
493			}
494		    }
495		  else
496		    exponent += 4;
497		}
498	    }
499	}
500    }
501  else
502    {
503      if (precision == -1)
504	precision = 0;
505      numend = numstr;
506      wnumend = wnumstr;
507    }
508
509  /* Now we can compute the exponent string.  */
510  expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
511  wexpstr = _itowa_word (exponent,
512			 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
513
514  /* Now we have all information to compute the size.  */
515  width -= ((negative || info->showsign || info->space)
516	    /* Sign.  */
517	    + 2    + 1 + 0 + precision + 1 + 1
518	    /* 0x    h   .   hhh         P   ExpoSign.  */
519	    + ((expbuf + sizeof expbuf) - expstr));
520	    /* Exponent.  */
521
522  /* Count the decimal point.
523     A special case when the mantissa or the precision is zero and the `#'
524     is not given.  In this case we must not print the decimal point.  */
525  if (precision > 0 || info->alt)
526    width -= wide ? 1 : strlen (decimal);
527
528  if (!info->left && info->pad != '0' && width > 0)
529    PADN (' ', width);
530
531  if (negative)
532    outchar ('-');
533  else if (info->showsign)
534    outchar ('+');
535  else if (info->space)
536    outchar (' ');
537
538  outchar ('0');
539  if ('X' - 'A' == 'x' - 'a')
540    outchar (info->spec + ('x' - 'a'));
541  else
542    outchar (info->spec == 'A' ? 'X' : 'x');
543
544  if (!info->left && info->pad == '0' && width > 0)
545    PADN ('0', width);
546
547  outchar (leading);
548
549  if (precision > 0 || info->alt)
550    {
551      const wchar_t *wtmp = &decimalwc;
552      PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
553    }
554
555  if (precision > 0)
556    {
557      ssize_t tofill = precision - (numend - numstr);
558      PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
559      if (tofill > 0)
560	PADN ('0', tofill);
561    }
562
563  if ('P' - 'A' == 'p' - 'a')
564    outchar (info->spec + ('p' - 'a'));
565  else
566    outchar (info->spec == 'A' ? 'P' : 'p');
567
568  outchar (expnegative ? '-' : '+');
569
570  PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
571
572  if (info->left && info->pad != '0' && width > 0)
573    PADN (info->pad, width);
574
575  return done;
576}
577