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