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      wnumstr++;							      \
142									      \
143      /* We have 3 bits from the mantissa in the leading nibble.	      \
144	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
145      exponent = fpnum.ldbl.ieee.exponent;				      \
146									      \
147      if (exponent == 0)						      \
148	{								      \
149	  if (zero_mantissa)						      \
150	    expnegative = 0;						      \
151	  else								      \
152	    {								      \
153	      /* This is a denormalized number.  */			      \
154	      expnegative = 1;						      \
155	      /* This is a hook for the m68k long double format, where the    \
156		 exponent bias is the same for normalized and denormalized    \
157		 numbers.  */						      \
158	      exponent = LONG_DOUBLE_DENORM_BIAS + 3;			      \
159	    }								      \
160	}								      \
161      else if (exponent >= IEEE854_LONG_DOUBLE_BIAS + 3)		      \
162	{								      \
163	  expnegative = 0;						      \
164	  exponent -= IEEE854_LONG_DOUBLE_BIAS + 3;			      \
165	}								      \
166      else								      \
167	{								      \
168	  expnegative = 1;						      \
169	  exponent = -(exponent - (IEEE854_LONG_DOUBLE_BIAS + 3));	      \
170	}								      \
171} while (0)
172
173#endif	/* __x86_64__ || __i386__ */
174
175
176int
177__printf_fphex (FILE *fp,
178		const struct printf_info *info,
179		const void *const *args)
180{
181  /* The floating-point value to output.  */
182  union
183    {
184      union ieee754_double dbl;
185      union ieee854_long_double ldbl;
186    }
187  fpnum;
188
189  /* Locale-dependent representation of decimal point.	*/
190  const char *decimal;
191  wchar_t decimalwc;
192
193  /* "NaN" or "Inf" for the special cases.  */
194  const char *special = NULL;
195  const wchar_t *wspecial = NULL;
196
197  /* Buffer for the generated number string for the mantissa.  The
198     maximal size for the mantissa is 128 bits.  */
199  char numbuf[32];
200  char *numstr="";
201  char *numend;
202  wchar_t wnumbuf[32];
203  wchar_t *wnumstr=L"";
204  wchar_t *wnumend;
205  int negative;
206
207  /* The maximal exponent of two in decimal notation has 5 digits.  */
208  char expbuf[5];
209  char *expstr;
210  wchar_t wexpbuf[5];
211  wchar_t *wexpstr;
212  int expnegative = 0;
213  int exponent = 0;
214
215  /* Non-zero is mantissa is zero.  */
216  int zero_mantissa = 1;
217
218  /* The leading digit before the decimal point.  */
219  char leading = '0';
220
221  /* Precision.  */
222  int precision = info->prec;
223
224  /* Width.  */
225  int width = info->width;
226
227  /* Number of characters written.  */
228  int done = 0;
229
230  /* Nonzero if this is output on a wide character stream.  */
231  int wide = info->wide;
232
233
234  /* Figure out the decimal point character.  */
235  if (info->extra == 0)
236    {
237      decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT);
238      decimalwc = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
239    }
240  else
241    {
242      decimal = _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT);
243      decimalwc = _NL_CURRENT_WORD (LC_MONETARY,
244				    _NL_MONETARY_DECIMAL_POINT_WC);
245    }
246  /* The decimal point character must never be zero.  */
247  assert (*decimal != '\0' && decimalwc != L'\0');
248
249
250  /* Fetch the argument value.	*/
251#ifndef __NO_LONG_DOUBLE_MATH
252  if (info->is_long_double && sizeof (long double) > sizeof (double))
253    {
254      fpnum.ldbl.d = *(const long double *) args[0];
255
256      /* Check for special values: not a number or infinity.  */
257      if (isnan (fpnum.ldbl.d))
258	{
259	  if (isupper (info->spec))
260	    {
261	      special = "NAN";
262	      wspecial = L"NAN";
263	    }
264	  else
265	    {
266	      special = "nan";
267	      wspecial = L"nan";
268	    }
269	  negative = 0;
270	}
271      else
272	{
273	  if (isinf (fpnum.ldbl.d))
274	    {
275	      if (isupper (info->spec))
276		{
277		  special = "INF";
278		  wspecial = L"INF";
279		}
280	      else
281		{
282		  special = "inf";
283		  wspecial = L"inf";
284		}
285	    }
286
287	  negative = signbit (fpnum.ldbl.d);
288	}
289    }
290  else
291#endif	/* no long double */
292    {
293      fpnum.dbl.d = *(const double *) args[0];
294
295      /* Check for special values: not a number or infinity.  */
296      if (isnan (fpnum.dbl.d))
297	{
298	  if (isupper (info->spec))
299	    {
300	      special = "NAN";
301	      wspecial = L"NAN";
302	    }
303	  else
304	    {
305	      special = "nan";
306	      wspecial = L"nan";
307	    }
308	  negative = 0;
309	}
310      else
311	{
312	  if (isinf (fpnum.dbl.d))
313	    {
314	      if (isupper (info->spec))
315		{
316		  special = "INF";
317		  wspecial = L"INF";
318		}
319	      else
320		{
321		  special = "inf";
322		  wspecial = L"inf";
323		}
324	    }
325
326	  negative = signbit (fpnum.dbl.d);
327	}
328    }
329
330  if (special)
331    {
332      int width = info->width;
333
334      if (negative || info->showsign || info->space)
335	--width;
336      width -= 3;
337
338      if (!info->left && width > 0)
339	PADN (' ', width);
340
341      if (negative)
342	outchar ('-');
343      else if (info->showsign)
344	outchar ('+');
345      else if (info->space)
346	outchar (' ');
347
348      PRINT (special, wspecial, 3);
349
350      if (info->left && width > 0)
351	PADN (' ', width);
352
353      return done;
354    }
355
356  if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
357    {
358      /* We have 52 bits of mantissa plus one implicit digit.  Since
359	 52 bits are representable without rest using hexadecimal
360	 digits we use only the implicit digits for the number before
361	 the decimal point.  */
362      unsigned long long int num;
363
364      num = (((unsigned long long int) fpnum.dbl.ieee.mantissa0) << 32
365	     | fpnum.dbl.ieee.mantissa1);
366
367      zero_mantissa = num == 0;
368
369      if (sizeof (unsigned long int) > 6)
370	{
371	  wnumstr = _itowa_word (num, wnumbuf + (sizeof wnumbuf) / sizeof (wchar_t), 16,
372				 info->spec == 'A');
373	  numstr = _itoa_word (num, numbuf + sizeof numbuf, 16,
374			       info->spec == 'A');
375	}
376      else
377	{
378	  wnumstr = _itowa (num, wnumbuf + sizeof wnumbuf / sizeof (wchar_t), 16,
379			    info->spec == 'A');
380	  numstr = _itoa (num, numbuf + sizeof numbuf, 16,
381			  info->spec == 'A');
382	}
383
384      /* Fill with zeroes.  */
385      while (wnumstr > wnumbuf + (sizeof wnumbuf - 52) / sizeof (wchar_t))
386	{
387	  *--wnumstr = L'0';
388	  *--numstr = '0';
389	}
390
391      leading = fpnum.dbl.ieee.exponent == 0 ? '0' : '1';
392
393      exponent = fpnum.dbl.ieee.exponent;
394
395      if (exponent == 0)
396	{
397	  if (zero_mantissa)
398	    expnegative = 0;
399	  else
400	    {
401	      /* This is a denormalized number.  */
402	      expnegative = 1;
403	      exponent = IEEE754_DOUBLE_BIAS - 1;
404	    }
405	}
406      else if (exponent >= IEEE754_DOUBLE_BIAS)
407	{
408	  expnegative = 0;
409	  exponent -= IEEE754_DOUBLE_BIAS;
410	}
411      else
412	{
413	  expnegative = 1;
414	  exponent = -(exponent - IEEE754_DOUBLE_BIAS);
415	}
416    }
417#ifdef PRINT_FPHEX_LONG_DOUBLE
418  else
419    PRINT_FPHEX_LONG_DOUBLE;
420#endif
421
422  /* Look for trailing zeroes.  */
423  if (! zero_mantissa)
424    {
425      wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]];
426      numend = &numbuf[sizeof numbuf / sizeof numbuf[0]];
427      while (wnumend[-1] == L'0')
428	{
429	  --wnumend;
430	  --numend;
431	}
432
433      if (precision == -1)
434	precision = numend - numstr;
435      else if (precision < numend - numstr
436	       && (numstr[precision] > '8'
437		   || (('A' < '0' || 'a' < '0')
438		       && numstr[precision] < '0')
439		   || (numstr[precision] == '8'
440		       && (precision + 1 < numend - numstr
441			   /* Round to even.  */
442			   || (precision > 0
443			       && ((numstr[precision - 1] & 1)
444				   ^ (isdigit (numstr[precision - 1]) == 0)))
445			   || (precision == 0
446			       && ((leading & 1)
447				   ^ (isdigit (leading) == 0)))))))
448	{
449	  /* Round up.  */
450	  int cnt = precision;
451	  while (--cnt >= 0)
452	    {
453	      char ch = numstr[cnt];
454	      /* We assume that the digits and the letters are ordered
455		 like in ASCII.  This is true for the rest of GNU, too.  */
456	      if (ch == '9')
457		{
458		  wnumstr[cnt] = (wchar_t) info->spec;
459		  numstr[cnt] = info->spec;	/* This is tricky,
460		  				   think about it!  */
461		  break;
462		}
463	      else if (tolower (ch) < 'f')
464		{
465		  ++numstr[cnt];
466		  ++wnumstr[cnt];
467		  break;
468		}
469	      else
470		{
471		  numstr[cnt] = '0';
472		  wnumstr[cnt] = L'0';
473		}
474	    }
475	  if (cnt < 0)
476	    {
477	      /* The mantissa so far was fff...f  Now increment the
478		 leading digit.  Here it is again possible that we
479		 get an overflow.  */
480	      if (leading == '9')
481		leading = info->spec;
482	      else if (tolower (leading) < 'f')
483		++leading;
484	      else
485		{
486		  leading = '1';
487		  if (expnegative)
488		    {
489		      exponent -= 4;
490		      if (exponent <= 0)
491			{
492			  exponent = -exponent;
493			  expnegative = 0;
494			}
495		    }
496		  else
497		    exponent += 4;
498		}
499	    }
500	}
501    }
502  else
503    {
504      if (precision == -1)
505	precision = 0;
506      numend = numstr;
507      wnumend = wnumstr;
508    }
509
510  /* Now we can compute the exponent string.  */
511  expstr = _itoa_word (exponent, expbuf + sizeof expbuf, 10, 0);
512  wexpstr = _itowa_word (exponent,
513			 wexpbuf + sizeof wexpbuf / sizeof (wchar_t), 10, 0);
514
515  /* Now we have all information to compute the size.  */
516  width -= ((negative || info->showsign || info->space)
517	    /* Sign.  */
518	    + 2    + 1 + 0 + precision + 1 + 1
519	    /* 0x    h   .   hhh         P   ExpoSign.  */
520	    + ((expbuf + sizeof expbuf) - expstr));
521	    /* Exponent.  */
522
523  /* Count the decimal point.
524     A special case when the mantissa or the precision is zero and the `#'
525     is not given.  In this case we must not print the decimal point.  */
526  if (precision > 0 || info->alt)
527    width -= wide ? 1 : strlen (decimal);
528
529  if (!info->left && info->pad != '0' && width > 0)
530    PADN (' ', width);
531
532  if (negative)
533    outchar ('-');
534  else if (info->showsign)
535    outchar ('+');
536  else if (info->space)
537    outchar (' ');
538
539  outchar ('0');
540  if ('X' - 'A' == 'x' - 'a')
541    outchar (info->spec + ('x' - 'a'));
542  else
543    outchar (info->spec == 'A' ? 'X' : 'x');
544
545  if (!info->left && info->pad == '0' && width > 0)
546    PADN ('0', width);
547
548  outchar (leading);
549
550  if (precision > 0 || info->alt)
551    {
552      const wchar_t *wtmp = &decimalwc;
553      PRINT (decimal, wtmp, wide ? 1 : strlen (decimal));
554    }
555
556  if (precision > 0)
557    {
558      ssize_t tofill = precision - (numend - numstr);
559      PRINT (numstr, wnumstr, MIN (numend - numstr, precision));
560      if (tofill > 0)
561	PADN ('0', tofill);
562    }
563
564  if ('P' - 'A' == 'p' - 'a')
565    outchar (info->spec + ('p' - 'a'));
566  else
567    outchar (info->spec == 'A' ? 'P' : 'p');
568
569  outchar (expnegative ? '-' : '+');
570
571  PRINT (expstr, wexpstr, (expbuf + sizeof expbuf) - expstr);
572
573  if (info->left && info->pad != '0' && width > 0)
574    PADN (info->pad, width);
575
576  return done;
577}
578