1 /* 2 * Copyright (c) 1995 Patrick Powell. 3 * 4 * This code is based on code written by Patrick Powell <papowell (at) astart.com>. 5 * It may be used for any purpose as long as this notice remains intact on all 6 * source code distributions. 7 */ 8 9 /* 10 * Copyright (c) 2008 Holger Weiss. 11 * 12 * This version of the code is maintained by Holger Weiss <holger (at) jhweiss.de>. 13 * My changes to the code may freely be used, modified and/or redistributed for 14 * any purpose. It would be nice if additions and fixes to this file (including 15 * trivial code cleanups) would be sent back in order to let me include them in 16 * the version available at <http://www.jhweiss.de/software/snprintf.html>. 17 * However, this is not a requirement for using or redistributing (possibly 18 * modified) versions of this file, nor is leaving this notice intact mandatory. 19 */ 20 21 /* 22 * History 23 * 24 * 2008-01-20 Holger Weiss <holger (at) jhweiss.de> for C99-snprintf 1.1: 25 * 26 * Fixed the detection of infinite floating point values on IRIX (and 27 * possibly other systems) and applied another few minor cleanups. 28 * 29 * 2008-01-06 Holger Weiss <holger (at) jhweiss.de> for C99-snprintf 1.0: 30 * 31 * Added a lot of new features, fixed many bugs, and incorporated various 32 * improvements done by Andrew Tridgell <tridge (at) samba.org>, Russ Allbery 33 * <rra (at) stanford.edu>, Hrvoje Niksic <hniksic (at) xemacs.org>, Damien Miller 34 * <djm (at) mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH 35 * projects. The additions include: support the "e", "E", "g", "G", and 36 * "F" conversion specifiers (and use conversion style "f" or "F" for the 37 * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", 38 * "t", and "z" length modifiers; support the "#" flag and the (non-C99) 39 * "'" flag; use localeconv(3) (if available) to get both the current 40 * locale's decimal point character and the separator between groups of 41 * digits; fix the handling of various corner cases of field width and 42 * precision specifications; fix various floating point conversion bugs; 43 * handle infinite and NaN floating point values; don't attempt to write to 44 * the output buffer (which may be NULL) if a size of zero was specified; 45 * check for integer overflow of the field width, precision, and return 46 * values and during the floating point conversion; use the OUTCHAR() macro 47 * instead of a function for better performance; provide asprintf(3) and 48 * vasprintf(3) functions; add new test cases. The replacement functions 49 * have been renamed to use an "rpl_" prefix, the function calls in the 50 * main project (and in this file) must be redefined accordingly for each 51 * replacement function which is needed (by using Autoconf or other means). 52 * Various other minor improvements have been applied and the coding style 53 * was cleaned up for consistency. 54 * 55 * 2007-07-23 Holger Weiss <holger (at) jhweiss.de> for Mutt 1.5.13: 56 * 57 * C99 compliant snprintf(3) and vsnprintf(3) functions return the number 58 * of characters that would have been written to a sufficiently sized 59 * buffer (excluding the '\0'). The original code simply returned the 60 * length of the resulting output string, so that's been fixed. 61 * 62 * 1998-03-05 Michael Elkins <me (at) mutt.org> for Mutt 0.90.8: 63 * 64 * The original code assumed that both snprintf(3) and vsnprintf(3) were 65 * missing. Some systems only have snprintf(3) but not vsnprintf(3), so 66 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. 67 * 68 * 1998-01-27 Thomas Roessler <roessler (at) does-not-exist.org> for Mutt 0.89i: 69 * 70 * The PGP code was using unsigned hexadecimal formats. Unfortunately, 71 * unsigned formats simply didn't work. 72 * 73 * 1997-10-22 Brandon Long <blong (at) fiction.net> for Mutt 0.87.1: 74 * 75 * Ok, added some minimal floating point support, which means this probably 76 * requires libm on most operating systems. Don't yet support the exponent 77 * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just 78 * wasn't being exercised in ways which showed it, so that's been fixed. 79 * Also, formatted the code to Mutt conventions, and removed dead code left 80 * over from the original. Also, there is now a builtin-test, run with: 81 * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf 82 * 83 * 2996-09-15 Brandon Long <blong (at) fiction.net> for Mutt 0.43: 84 * 85 * This was ugly. It is still ugly. I opted out of floating point 86 * numbers, but the formatter understands just about everything from the 87 * normal C string format, at least as far as I can tell from the Solaris 88 * 2.5 printf(3S) man page. 89 */ 90 91 /* 92 * ToDo 93 * 94 * - Add wide character support. 95 * - Add support for "%a" and "%A" conversions. 96 * - Create test routines which predefine the expected results. Our test cases 97 * usually expose bugs in system implementations rather than in ours :-) 98 */ 99 100 /* 101 * Usage 102 * 103 * 1) The following preprocessor macros should be defined to 1 if the feature or 104 * file in question is available on the target system (by using Autoconf or 105 * other means), though basic functionality should be available as long as 106 * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: 107 * 108 * HAVE_VSNPRINTF 109 * HAVE_SNPRINTF 110 * HAVE_VASPRINTF 111 * HAVE_ASPRINTF 112 * HAVE_STDARG_H 113 * HAVE_STDDEF_H 114 * HAVE_STDINT_H 115 * HAVE_STDLIB_H 116 * HAVE_INTTYPES_H 117 * HAVE_LOCALE_H 118 * HAVE_LOCALECONV 119 * HAVE_LCONV_DECIMAL_POINT 120 * HAVE_LCONV_THOUSANDS_SEP 121 * HAVE_LONG_DOUBLE 122 * HAVE_LONG_LONG_INT 123 * HAVE_UNSIGNED_LONG_LONG_INT 124 * HAVE_INTMAX_T 125 * HAVE_UINTMAX_T 126 * HAVE_UINTPTR_T 127 * HAVE_PTRDIFF_T 128 * HAVE_VA_COPY 129 * HAVE___VA_COPY 130 * 131 * 2) The calls to the functions which should be replaced must be redefined 132 * throughout the project files (by using Autoconf or other means): 133 * 134 * #define vsnprintf rpl_vsnprintf 135 * #define snprintf rpl_snprintf 136 * #define vasprintf rpl_vasprintf 137 * #define asprintf rpl_asprintf 138 * 139 * 3) The required replacement functions should be declared in some header file 140 * included throughout the project files: 141 * 142 * #if HAVE_CONFIG_H 143 * #include <config.h> 144 * #endif 145 * #if HAVE_STDARG_H 146 * #include <stdarg.h> 147 * #if !HAVE_VSNPRINTF 148 * int rpl_vsnprintf(char *, size_t, const char *, va_list); 149 * #endif 150 * #if !HAVE_SNPRINTF 151 * int rpl_snprintf(char *, size_t, const char *, ...); 152 * #endif 153 * #if !HAVE_VASPRINTF 154 * int rpl_vasprintf(char **, const char *, va_list); 155 * #endif 156 * #if !HAVE_ASPRINTF 157 * int rpl_asprintf(char **, const char *, ...); 158 * #endif 159 * #endif 160 * 161 * Autoconf macros for handling step 1 and step 2 are available at 162 * <http://www.jhweiss.de/software/snprintf.html>. 163 */ 164 165 #include "pipe/p_config.h" 166 167 #if HAVE_CONFIG_H 168 #include <config.h> 169 #else 170 #ifdef WIN32 171 #define vsnprintf util_vsnprintf 172 #define snprintf util_snprintf 173 #define HAVE_VSNPRINTF 0 174 #define HAVE_SNPRINTF 0 175 #define HAVE_VASPRINTF 1 /* not needed */ 176 #define HAVE_ASPRINTF 1 /* not needed */ 177 #define HAVE_STDARG_H 1 178 #define HAVE_STDDEF_H 1 179 #define HAVE_STDINT_H 0 180 #define HAVE_STDLIB_H 1 181 #define HAVE_INTTYPES_H 0 182 #define HAVE_LOCALE_H 0 183 #define HAVE_LOCALECONV 0 184 #define HAVE_LCONV_DECIMAL_POINT 0 185 #define HAVE_LCONV_THOUSANDS_SEP 0 186 #define HAVE_LONG_DOUBLE 0 187 #define HAVE_LONG_LONG_INT 1 188 #define HAVE_UNSIGNED_LONG_LONG_INT 1 189 #define HAVE_INTMAX_T 0 190 #define HAVE_UINTMAX_T 0 191 #define HAVE_UINTPTR_T 1 192 #define HAVE_PTRDIFF_T 1 193 #define HAVE_VA_COPY 0 194 #define HAVE___VA_COPY 0 195 #else 196 #define HAVE_VSNPRINTF 1 197 #define HAVE_SNPRINTF 1 198 #define HAVE_VASPRINTF 1 199 #define HAVE_ASPRINTF 1 200 #endif 201 #endif /* HAVE_CONFIG_H */ 202 203 #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF 204 #include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ 205 #ifdef VA_START 206 #undef VA_START 207 #endif /* defined(VA_START) */ 208 #ifdef VA_SHIFT 209 #undef VA_SHIFT 210 #endif /* defined(VA_SHIFT) */ 211 #if HAVE_STDARG_H 212 #include <stdarg.h> 213 #define VA_START(ap, last) va_start(ap, last) 214 #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ 215 #else /* Assume <varargs.h> is available. */ 216 #include <varargs.h> 217 #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ 218 #define VA_SHIFT(ap, value, type) value = va_arg(ap, type) 219 #endif /* HAVE_STDARG_H */ 220 221 #if !HAVE_VASPRINTF 222 #if HAVE_STDLIB_H 223 #include <stdlib.h> /* For malloc(3). */ 224 #endif /* HAVE_STDLIB_H */ 225 #ifdef VA_COPY 226 #undef VA_COPY 227 #endif /* defined(VA_COPY) */ 228 #ifdef VA_END_COPY 229 #undef VA_END_COPY 230 #endif /* defined(VA_END_COPY) */ 231 #if HAVE_VA_COPY 232 #define VA_COPY(dest, src) va_copy(dest, src) 233 #define VA_END_COPY(ap) va_end(ap) 234 #elif HAVE___VA_COPY 235 #define VA_COPY(dest, src) __va_copy(dest, src) 236 #define VA_END_COPY(ap) va_end(ap) 237 #else 238 #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) 239 #define VA_END_COPY(ap) /* No-op. */ 240 #define NEED_MYMEMCPY 1 241 static void *mymemcpy(void *, void *, size_t); 242 #endif /* HAVE_VA_COPY */ 243 #endif /* !HAVE_VASPRINTF */ 244 245 #if !HAVE_VSNPRINTF 246 #include <limits.h> /* For *_MAX. */ 247 #if HAVE_INTTYPES_H 248 #include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */ 249 #endif /* HAVE_INTTYPES_H */ 250 #if HAVE_LOCALE_H 251 #include <locale.h> /* For localeconv(3). */ 252 #endif /* HAVE_LOCALE_H */ 253 #if HAVE_STDDEF_H 254 #include <stddef.h> /* For ptrdiff_t. */ 255 #endif /* HAVE_STDDEF_H */ 256 #if HAVE_STDINT_H 257 #include <stdint.h> /* For intmax_t. */ 258 #endif /* HAVE_STDINT_H */ 259 260 /* Support for unsigned long long int. We may also need ULLONG_MAX. */ 261 #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ 262 #ifdef UINT_MAX 263 #define ULONG_MAX UINT_MAX 264 #else 265 #define ULONG_MAX INT_MAX 266 #endif /* defined(UINT_MAX) */ 267 #endif /* !defined(ULONG_MAX) */ 268 #ifdef ULLONG 269 #undef ULLONG 270 #endif /* defined(ULLONG) */ 271 #if HAVE_UNSIGNED_LONG_LONG_INT 272 #define ULLONG unsigned long long int 273 #ifndef ULLONG_MAX 274 #define ULLONG_MAX ULONG_MAX 275 #endif /* !defined(ULLONG_MAX) */ 276 #else 277 #define ULLONG unsigned long int 278 #ifdef ULLONG_MAX 279 #undef ULLONG_MAX 280 #endif /* defined(ULLONG_MAX) */ 281 #define ULLONG_MAX ULONG_MAX 282 #endif /* HAVE_LONG_LONG_INT */ 283 284 /* Support for uintmax_t. We also need UINTMAX_MAX. */ 285 #ifdef UINTMAX_T 286 #undef UINTMAX_T 287 #endif /* defined(UINTMAX_T) */ 288 #if HAVE_UINTMAX_T || defined(uintmax_t) 289 #define UINTMAX_T uintmax_t 290 #ifndef UINTMAX_MAX 291 #define UINTMAX_MAX ULLONG_MAX 292 #endif /* !defined(UINTMAX_MAX) */ 293 #else 294 #define UINTMAX_T ULLONG 295 #ifdef UINTMAX_MAX 296 #undef UINTMAX_MAX 297 #endif /* defined(UINTMAX_MAX) */ 298 #define UINTMAX_MAX ULLONG_MAX 299 #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ 300 301 /* Support for long double. */ 302 #ifndef LDOUBLE 303 #if HAVE_LONG_DOUBLE 304 #define LDOUBLE long double 305 #else 306 #define LDOUBLE double 307 #endif /* HAVE_LONG_DOUBLE */ 308 #endif /* !defined(LDOUBLE) */ 309 310 /* Support for long long int. */ 311 #ifndef LLONG 312 #if HAVE_LONG_LONG_INT 313 #define LLONG long long int 314 #else 315 #define LLONG long int 316 #endif /* HAVE_LONG_LONG_INT */ 317 #endif /* !defined(LLONG) */ 318 319 /* Support for intmax_t. */ 320 #ifndef INTMAX_T 321 #if HAVE_INTMAX_T || defined(intmax_t) 322 #define INTMAX_T intmax_t 323 #else 324 #define INTMAX_T LLONG 325 #endif /* HAVE_INTMAX_T || defined(intmax_t) */ 326 #endif /* !defined(INTMAX_T) */ 327 328 /* Support for uintptr_t. */ 329 #ifndef UINTPTR_T 330 #if HAVE_UINTPTR_T || defined(uintptr_t) 331 #define UINTPTR_T uintptr_t 332 #else 333 #define UINTPTR_T unsigned long int 334 #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ 335 #endif /* !defined(UINTPTR_T) */ 336 337 /* WinCE5.0 does not have uintptr_t defined */ 338 #if (_WIN32_WCE < 600) 339 #ifdef UINTPTR_T 340 #undef UINTPTR_T 341 #endif 342 #define UINTPTR_T unsigned long int 343 #endif 344 345 346 /* Support for ptrdiff_t. */ 347 #ifndef PTRDIFF_T 348 #if HAVE_PTRDIFF_T || defined(ptrdiff_t) 349 #define PTRDIFF_T ptrdiff_t 350 #else 351 #define PTRDIFF_T long int 352 #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ 353 #endif /* !defined(PTRDIFF_T) */ 354 355 /* 356 * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: 357 * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an 358 * unsigned type if necessary. This should work just fine in practice. 359 */ 360 #ifndef UPTRDIFF_T 361 #define UPTRDIFF_T PTRDIFF_T 362 #endif /* !defined(UPTRDIFF_T) */ 363 364 /* 365 * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). 366 * However, we'll simply use size_t and convert it to a signed type if 367 * necessary. This should work just fine in practice. 368 */ 369 #ifndef SSIZE_T 370 #define SSIZE_T size_t 371 #endif /* !defined(SSIZE_T) */ 372 373 /* Either ERANGE or E2BIG should be available everywhere. */ 374 #ifndef ERANGE 375 #define ERANGE E2BIG 376 #endif /* !defined(ERANGE) */ 377 #ifndef EOVERFLOW 378 #define EOVERFLOW ERANGE 379 #endif /* !defined(EOVERFLOW) */ 380 381 /* 382 * Buffer size to hold the octal string representation of UINT128_MAX without 383 * nul-termination ("3777777777777777777777777777777777777777777"). 384 */ 385 #ifdef MAX_CONVERT_LENGTH 386 #undef MAX_CONVERT_LENGTH 387 #endif /* defined(MAX_CONVERT_LENGTH) */ 388 #define MAX_CONVERT_LENGTH 43 389 390 /* Format read states. */ 391 #define PRINT_S_DEFAULT 0 392 #define PRINT_S_FLAGS 1 393 #define PRINT_S_WIDTH 2 394 #define PRINT_S_DOT 3 395 #define PRINT_S_PRECISION 4 396 #define PRINT_S_MOD 5 397 #define PRINT_S_CONV 6 398 399 /* Format flags. */ 400 #define PRINT_F_MINUS (1 << 0) 401 #define PRINT_F_PLUS (1 << 1) 402 #define PRINT_F_SPACE (1 << 2) 403 #define PRINT_F_NUM (1 << 3) 404 #define PRINT_F_ZERO (1 << 4) 405 #define PRINT_F_QUOTE (1 << 5) 406 #define PRINT_F_UP (1 << 6) 407 #define PRINT_F_UNSIGNED (1 << 7) 408 #define PRINT_F_TYPE_G (1 << 8) 409 #define PRINT_F_TYPE_E (1 << 9) 410 411 /* Conversion flags. */ 412 #define PRINT_C_CHAR 1 413 #define PRINT_C_SHORT 2 414 #define PRINT_C_LONG 3 415 #define PRINT_C_LLONG 4 416 #define PRINT_C_LDOUBLE 5 417 #define PRINT_C_SIZE 6 418 #define PRINT_C_PTRDIFF 7 419 #define PRINT_C_INTMAX 8 420 421 #ifndef MAX 422 #define MAX(x, y) ((x >= y) ? x : y) 423 #endif /* !defined(MAX) */ 424 #ifndef CHARTOINT 425 #define CHARTOINT(ch) (ch - '0') 426 #endif /* !defined(CHARTOINT) */ 427 #ifndef ISDIGIT 428 #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') 429 #endif /* !defined(ISDIGIT) */ 430 #ifndef ISNAN 431 #define ISNAN(x) (x != x) 432 #endif /* !defined(ISNAN) */ 433 #ifndef ISINF 434 #define ISINF(x) (x != 0.0 && x + x == x) 435 #endif /* !defined(ISINF) */ 436 437 #ifdef OUTCHAR 438 #undef OUTCHAR 439 #endif /* defined(OUTCHAR) */ 440 #define OUTCHAR(str, len, size, ch) \ 441 do { \ 442 if (len + 1 < size) \ 443 str[len] = ch; \ 444 (len)++; \ 445 } while (/* CONSTCOND */ 0) 446 447 static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); 448 static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); 449 static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); 450 static void printsep(char *, size_t *, size_t); 451 static int getnumsep(int); 452 static int getexponent(LDOUBLE); 453 static int convert(UINTMAX_T, char *, size_t, int, int); 454 static UINTMAX_T cast(LDOUBLE); 455 static UINTMAX_T myround(LDOUBLE); 456 static LDOUBLE mypow10(int); 457 458 int 459 util_vsnprintf(char *str, size_t size, const char *format, va_list args) 460 { 461 LDOUBLE fvalue; 462 INTMAX_T value; 463 unsigned char cvalue; 464 const char *strvalue; 465 INTMAX_T *intmaxptr; 466 PTRDIFF_T *ptrdiffptr; 467 SSIZE_T *sizeptr; 468 LLONG *llongptr; 469 long int *longptr; 470 int *intptr; 471 short int *shortptr; 472 signed char *charptr; 473 size_t len = 0; 474 int overflow = 0; 475 int base = 0; 476 int cflags = 0; 477 int flags = 0; 478 int width = 0; 479 int precision = -1; 480 int state = PRINT_S_DEFAULT; 481 char ch = *format++; 482 483 /* 484 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null 485 * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer 486 * even if a size larger than zero was specified. At least NetBSD's 487 * snprintf(3) does the same, as well as other versions of this file. 488 * (Though some of these versions will write to a non-NULL buffer even 489 * if a size of zero was specified, which violates the standard.) 490 */ 491 if (str == NULL && size != 0) 492 size = 0; 493 494 while (ch != '\0') 495 switch (state) { 496 case PRINT_S_DEFAULT: 497 if (ch == '%') 498 state = PRINT_S_FLAGS; 499 else 500 OUTCHAR(str, len, size, ch); 501 ch = *format++; 502 break; 503 case PRINT_S_FLAGS: 504 switch (ch) { 505 case '-': 506 flags |= PRINT_F_MINUS; 507 ch = *format++; 508 break; 509 case '+': 510 flags |= PRINT_F_PLUS; 511 ch = *format++; 512 break; 513 case ' ': 514 flags |= PRINT_F_SPACE; 515 ch = *format++; 516 break; 517 case '#': 518 flags |= PRINT_F_NUM; 519 ch = *format++; 520 break; 521 case '0': 522 flags |= PRINT_F_ZERO; 523 ch = *format++; 524 break; 525 case '\'': /* SUSv2 flag (not in C99). */ 526 flags |= PRINT_F_QUOTE; 527 ch = *format++; 528 break; 529 default: 530 state = PRINT_S_WIDTH; 531 break; 532 } 533 break; 534 case PRINT_S_WIDTH: 535 if (ISDIGIT(ch)) { 536 ch = CHARTOINT(ch); 537 if (width > (INT_MAX - ch) / 10) { 538 overflow = 1; 539 goto out; 540 } 541 width = 10 * width + ch; 542 ch = *format++; 543 } else if (ch == '*') { 544 /* 545 * C99 says: "A negative field width argument is 546 * taken as a `-' flag followed by a positive 547 * field width." (7.19.6.1, 5) 548 */ 549 if ((width = va_arg(args, int)) < 0) { 550 flags |= PRINT_F_MINUS; 551 width = -width; 552 } 553 ch = *format++; 554 state = PRINT_S_DOT; 555 } else 556 state = PRINT_S_DOT; 557 break; 558 case PRINT_S_DOT: 559 if (ch == '.') { 560 state = PRINT_S_PRECISION; 561 ch = *format++; 562 } else 563 state = PRINT_S_MOD; 564 break; 565 case PRINT_S_PRECISION: 566 if (precision == -1) 567 precision = 0; 568 if (ISDIGIT(ch)) { 569 ch = CHARTOINT(ch); 570 if (precision > (INT_MAX - ch) / 10) { 571 overflow = 1; 572 goto out; 573 } 574 precision = 10 * precision + ch; 575 ch = *format++; 576 } else if (ch == '*') { 577 /* 578 * C99 says: "A negative precision argument is 579 * taken as if the precision were omitted." 580 * (7.19.6.1, 5) 581 */ 582 if ((precision = va_arg(args, int)) < 0) 583 precision = -1; 584 ch = *format++; 585 state = PRINT_S_MOD; 586 } else 587 state = PRINT_S_MOD; 588 break; 589 case PRINT_S_MOD: 590 switch (ch) { 591 case 'h': 592 ch = *format++; 593 if (ch == 'h') { /* It's a char. */ 594 ch = *format++; 595 cflags = PRINT_C_CHAR; 596 } else 597 cflags = PRINT_C_SHORT; 598 break; 599 case 'l': 600 ch = *format++; 601 if (ch == 'l') { /* It's a long long. */ 602 ch = *format++; 603 cflags = PRINT_C_LLONG; 604 } else 605 cflags = PRINT_C_LONG; 606 break; 607 case 'L': 608 cflags = PRINT_C_LDOUBLE; 609 ch = *format++; 610 break; 611 case 'j': 612 cflags = PRINT_C_INTMAX; 613 ch = *format++; 614 break; 615 case 't': 616 cflags = PRINT_C_PTRDIFF; 617 ch = *format++; 618 break; 619 case 'z': 620 cflags = PRINT_C_SIZE; 621 ch = *format++; 622 break; 623 } 624 state = PRINT_S_CONV; 625 break; 626 case PRINT_S_CONV: 627 switch (ch) { 628 case 'd': 629 /* FALLTHROUGH */ 630 case 'i': 631 switch (cflags) { 632 case PRINT_C_CHAR: 633 value = (signed char)va_arg(args, int); 634 break; 635 case PRINT_C_SHORT: 636 value = (short int)va_arg(args, int); 637 break; 638 case PRINT_C_LONG: 639 value = va_arg(args, long int); 640 break; 641 case PRINT_C_LLONG: 642 value = va_arg(args, LLONG); 643 break; 644 case PRINT_C_SIZE: 645 value = va_arg(args, SSIZE_T); 646 break; 647 case PRINT_C_INTMAX: 648 value = va_arg(args, INTMAX_T); 649 break; 650 case PRINT_C_PTRDIFF: 651 value = va_arg(args, PTRDIFF_T); 652 break; 653 default: 654 value = va_arg(args, int); 655 break; 656 } 657 fmtint(str, &len, size, value, 10, width, 658 precision, flags); 659 break; 660 case 'X': 661 flags |= PRINT_F_UP; 662 /* FALLTHROUGH */ 663 case 'x': 664 base = 16; 665 /* FALLTHROUGH */ 666 case 'o': 667 if (base == 0) 668 base = 8; 669 /* FALLTHROUGH */ 670 case 'u': 671 if (base == 0) 672 base = 10; 673 flags |= PRINT_F_UNSIGNED; 674 switch (cflags) { 675 case PRINT_C_CHAR: 676 value = (unsigned char)va_arg(args, 677 unsigned int); 678 break; 679 case PRINT_C_SHORT: 680 value = (unsigned short int)va_arg(args, 681 unsigned int); 682 break; 683 case PRINT_C_LONG: 684 value = va_arg(args, unsigned long int); 685 break; 686 case PRINT_C_LLONG: 687 value = va_arg(args, ULLONG); 688 break; 689 case PRINT_C_SIZE: 690 value = va_arg(args, size_t); 691 break; 692 case PRINT_C_INTMAX: 693 value = va_arg(args, UINTMAX_T); 694 break; 695 case PRINT_C_PTRDIFF: 696 value = va_arg(args, UPTRDIFF_T); 697 break; 698 default: 699 value = va_arg(args, unsigned int); 700 break; 701 } 702 fmtint(str, &len, size, value, base, width, 703 precision, flags); 704 break; 705 case 'A': 706 /* Not yet supported, we'll use "%F". */ 707 /* FALLTHROUGH */ 708 case 'F': 709 flags |= PRINT_F_UP; 710 case 'a': 711 /* Not yet supported, we'll use "%f". */ 712 /* FALLTHROUGH */ 713 case 'f': 714 if (cflags == PRINT_C_LDOUBLE) 715 fvalue = va_arg(args, LDOUBLE); 716 else 717 fvalue = va_arg(args, double); 718 fmtflt(str, &len, size, fvalue, width, 719 precision, flags, &overflow); 720 if (overflow) 721 goto out; 722 break; 723 case 'E': 724 flags |= PRINT_F_UP; 725 /* FALLTHROUGH */ 726 case 'e': 727 flags |= PRINT_F_TYPE_E; 728 if (cflags == PRINT_C_LDOUBLE) 729 fvalue = va_arg(args, LDOUBLE); 730 else 731 fvalue = va_arg(args, double); 732 fmtflt(str, &len, size, fvalue, width, 733 precision, flags, &overflow); 734 if (overflow) 735 goto out; 736 break; 737 case 'G': 738 flags |= PRINT_F_UP; 739 /* FALLTHROUGH */ 740 case 'g': 741 flags |= PRINT_F_TYPE_G; 742 if (cflags == PRINT_C_LDOUBLE) 743 fvalue = va_arg(args, LDOUBLE); 744 else 745 fvalue = va_arg(args, double); 746 /* 747 * If the precision is zero, it is treated as 748 * one (cf. C99: 7.19.6.1, 8). 749 */ 750 if (precision == 0) 751 precision = 1; 752 fmtflt(str, &len, size, fvalue, width, 753 precision, flags, &overflow); 754 if (overflow) 755 goto out; 756 break; 757 case 'c': 758 cvalue = (unsigned char)va_arg(args, int); 759 OUTCHAR(str, len, size, cvalue); 760 break; 761 case 's': 762 strvalue = va_arg(args, char *); 763 fmtstr(str, &len, size, strvalue, width, 764 precision, flags); 765 break; 766 case 'p': 767 /* 768 * C99 says: "The value of the pointer is 769 * converted to a sequence of printing 770 * characters, in an implementation-defined 771 * manner." (C99: 7.19.6.1, 8) 772 */ 773 if ((strvalue = va_arg(args, void *)) == NULL) 774 /* 775 * We use the glibc format. BSD prints 776 * "0x0", SysV "0". 777 */ 778 fmtstr(str, &len, size, "(nil)", width, 779 -1, flags); 780 else { 781 /* 782 * We use the BSD/glibc format. SysV 783 * omits the "0x" prefix (which we emit 784 * using the PRINT_F_NUM flag). 785 */ 786 flags |= PRINT_F_NUM; 787 flags |= PRINT_F_UNSIGNED; 788 fmtint(str, &len, size, 789 (UINTPTR_T)strvalue, 16, width, 790 precision, flags); 791 } 792 break; 793 case 'n': 794 switch (cflags) { 795 case PRINT_C_CHAR: 796 charptr = va_arg(args, signed char *); 797 *charptr = (signed char)len; 798 break; 799 case PRINT_C_SHORT: 800 shortptr = va_arg(args, short int *); 801 *shortptr = (short int)len; 802 break; 803 case PRINT_C_LONG: 804 longptr = va_arg(args, long int *); 805 *longptr = (long int)len; 806 break; 807 case PRINT_C_LLONG: 808 llongptr = va_arg(args, LLONG *); 809 *llongptr = (LLONG)len; 810 break; 811 case PRINT_C_SIZE: 812 /* 813 * C99 says that with the "z" length 814 * modifier, "a following `n' conversion 815 * specifier applies to a pointer to a 816 * signed integer type corresponding to 817 * size_t argument." (7.19.6.1, 7) 818 */ 819 sizeptr = va_arg(args, SSIZE_T *); 820 *sizeptr = len; 821 break; 822 case PRINT_C_INTMAX: 823 intmaxptr = va_arg(args, INTMAX_T *); 824 *intmaxptr = len; 825 break; 826 case PRINT_C_PTRDIFF: 827 ptrdiffptr = va_arg(args, PTRDIFF_T *); 828 *ptrdiffptr = len; 829 break; 830 default: 831 intptr = va_arg(args, int *); 832 *intptr = (int)len; 833 break; 834 } 835 break; 836 case '%': /* Print a "%" character verbatim. */ 837 OUTCHAR(str, len, size, ch); 838 break; 839 default: /* Skip other characters. */ 840 break; 841 } 842 ch = *format++; 843 state = PRINT_S_DEFAULT; 844 base = cflags = flags = width = 0; 845 precision = -1; 846 break; 847 } 848 out: 849 if (len < size) 850 str[len] = '\0'; 851 else if (size > 0) 852 str[size - 1] = '\0'; 853 854 if (overflow || len >= INT_MAX) { 855 return -1; 856 } 857 return (int)len; 858 } 859 860 static void 861 fmtstr(char *str, size_t *len, size_t size, const char *value, int width, 862 int precision, int flags) 863 { 864 int padlen, strln; /* Amount to pad. */ 865 int noprecision = (precision == -1); 866 867 if (value == NULL) /* We're forgiving. */ 868 value = "(null)"; 869 870 /* If a precision was specified, don't read the string past it. */ 871 for (strln = 0; value[strln] != '\0' && 872 (noprecision || strln < precision); strln++) 873 continue; 874 875 if ((padlen = width - strln) < 0) 876 padlen = 0; 877 if (flags & PRINT_F_MINUS) /* Left justify. */ 878 padlen = -padlen; 879 880 while (padlen > 0) { /* Leading spaces. */ 881 OUTCHAR(str, *len, size, ' '); 882 padlen--; 883 } 884 while (*value != '\0' && (noprecision || precision-- > 0)) { 885 OUTCHAR(str, *len, size, *value); 886 value++; 887 } 888 while (padlen < 0) { /* Trailing spaces. */ 889 OUTCHAR(str, *len, size, ' '); 890 padlen++; 891 } 892 } 893 894 static void 895 fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, 896 int precision, int flags) 897 { 898 UINTMAX_T uvalue; 899 char iconvert[MAX_CONVERT_LENGTH]; 900 char sign = 0; 901 char hexprefix = 0; 902 int spadlen = 0; /* Amount to space pad. */ 903 int zpadlen = 0; /* Amount to zero pad. */ 904 int pos; 905 int separators = (flags & PRINT_F_QUOTE); 906 int noprecision = (precision == -1); 907 908 if (flags & PRINT_F_UNSIGNED) 909 uvalue = value; 910 else { 911 uvalue = (value >= 0) ? value : -value; 912 if (value < 0) 913 sign = '-'; 914 else if (flags & PRINT_F_PLUS) /* Do a sign. */ 915 sign = '+'; 916 else if (flags & PRINT_F_SPACE) 917 sign = ' '; 918 } 919 920 pos = convert(uvalue, iconvert, sizeof(iconvert), base, 921 flags & PRINT_F_UP); 922 923 if (flags & PRINT_F_NUM && uvalue != 0) { 924 /* 925 * C99 says: "The result is converted to an `alternative form'. 926 * For `o' conversion, it increases the precision, if and only 927 * if necessary, to force the first digit of the result to be a 928 * zero (if the value and precision are both 0, a single 0 is 929 * printed). For `x' (or `X') conversion, a nonzero result has 930 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) 931 */ 932 switch (base) { 933 case 8: 934 if (precision <= pos) 935 precision = pos + 1; 936 break; 937 case 16: 938 hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; 939 break; 940 } 941 } 942 943 if (separators) /* Get the number of group separators we'll print. */ 944 separators = getnumsep(pos); 945 946 zpadlen = precision - pos - separators; 947 spadlen = width /* Minimum field width. */ 948 - separators /* Number of separators. */ 949 - MAX(precision, pos) /* Number of integer digits. */ 950 - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ 951 - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ 952 953 if (zpadlen < 0) 954 zpadlen = 0; 955 if (spadlen < 0) 956 spadlen = 0; 957 958 /* 959 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is 960 * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a 961 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) 962 */ 963 if (flags & PRINT_F_MINUS) /* Left justify. */ 964 spadlen = -spadlen; 965 else if (flags & PRINT_F_ZERO && noprecision) { 966 zpadlen += spadlen; 967 spadlen = 0; 968 } 969 while (spadlen > 0) { /* Leading spaces. */ 970 OUTCHAR(str, *len, size, ' '); 971 spadlen--; 972 } 973 if (sign != 0) /* Sign. */ 974 OUTCHAR(str, *len, size, sign); 975 if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ 976 OUTCHAR(str, *len, size, '0'); 977 OUTCHAR(str, *len, size, hexprefix); 978 } 979 while (zpadlen > 0) { /* Leading zeros. */ 980 OUTCHAR(str, *len, size, '0'); 981 zpadlen--; 982 } 983 while (pos > 0) { /* The actual digits. */ 984 pos--; 985 OUTCHAR(str, *len, size, iconvert[pos]); 986 if (separators > 0 && pos > 0 && pos % 3 == 0) 987 printsep(str, len, size); 988 } 989 while (spadlen < 0) { /* Trailing spaces. */ 990 OUTCHAR(str, *len, size, ' '); 991 spadlen++; 992 } 993 } 994 995 static void 996 fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, 997 int precision, int flags, int *overflow) 998 { 999 LDOUBLE ufvalue; 1000 UINTMAX_T intpart; 1001 UINTMAX_T fracpart; 1002 UINTMAX_T mask; 1003 const char *infnan = NULL; 1004 char iconvert[MAX_CONVERT_LENGTH]; 1005 char fconvert[MAX_CONVERT_LENGTH]; 1006 char econvert[4]; /* "e-12" (without nul-termination). */ 1007 char esign = 0; 1008 char sign = 0; 1009 int leadfraczeros = 0; 1010 int exponent = 0; 1011 int emitpoint = 0; 1012 int omitzeros = 0; 1013 int omitcount = 0; 1014 int padlen = 0; 1015 int epos = 0; 1016 int fpos = 0; 1017 int ipos = 0; 1018 int separators = (flags & PRINT_F_QUOTE); 1019 int estyle = (flags & PRINT_F_TYPE_E); 1020 #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT 1021 struct lconv *lc = localeconv(); 1022 #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ 1023 1024 /* 1025 * AIX' man page says the default is 0, but C99 and at least Solaris' 1026 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX 1027 * defaults to 6. 1028 */ 1029 if (precision == -1) 1030 precision = 6; 1031 1032 if (fvalue < 0.0) 1033 sign = '-'; 1034 else if (flags & PRINT_F_PLUS) /* Do a sign. */ 1035 sign = '+'; 1036 else if (flags & PRINT_F_SPACE) 1037 sign = ' '; 1038 1039 if (ISNAN(fvalue)) 1040 infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; 1041 else if (ISINF(fvalue)) 1042 infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; 1043 1044 if (infnan != NULL) { 1045 if (sign != 0) 1046 iconvert[ipos++] = sign; 1047 while (*infnan != '\0') 1048 iconvert[ipos++] = *infnan++; 1049 fmtstr(str, len, size, iconvert, width, ipos, flags); 1050 return; 1051 } 1052 1053 /* "%e" (or "%E") or "%g" (or "%G") conversion. */ 1054 if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { 1055 if (flags & PRINT_F_TYPE_G) { 1056 /* 1057 * For "%g" (and "%G") conversions, the precision 1058 * specifies the number of significant digits, which 1059 * includes the digits in the integer part. The 1060 * conversion will or will not be using "e-style" (like 1061 * "%e" or "%E" conversions) depending on the precision 1062 * and on the exponent. However, the exponent can be 1063 * affected by rounding the converted value, so we'll 1064 * leave this decision for later. Until then, we'll 1065 * assume that we're going to do an "e-style" conversion 1066 * (in order to get the exponent calculated). For 1067 * "e-style", the precision must be decremented by one. 1068 */ 1069 precision--; 1070 /* 1071 * For "%g" (and "%G") conversions, trailing zeros are 1072 * removed from the fractional portion of the result 1073 * unless the "#" flag was specified. 1074 */ 1075 if (!(flags & PRINT_F_NUM)) 1076 omitzeros = 1; 1077 } 1078 exponent = getexponent(fvalue); 1079 estyle = 1; 1080 } 1081 1082 again: 1083 /* 1084 * Sorry, we only support 9, 19, or 38 digits (that is, the number of 1085 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value 1086 * minus one) past the decimal point due to our conversion method. 1087 */ 1088 switch (sizeof(UINTMAX_T)) { 1089 case 16: 1090 if (precision > 38) 1091 precision = 38; 1092 break; 1093 case 8: 1094 if (precision > 19) 1095 precision = 19; 1096 break; 1097 default: 1098 if (precision > 9) 1099 precision = 9; 1100 break; 1101 } 1102 1103 ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; 1104 if (estyle) /* We want exactly one integer digit. */ 1105 ufvalue /= mypow10(exponent); 1106 1107 if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { 1108 *overflow = 1; 1109 return; 1110 } 1111 1112 /* 1113 * Factor of ten with the number of digits needed for the fractional 1114 * part. For example, if the precision is 3, the mask will be 1000. 1115 */ 1116 mask = (UINTMAX_T)mypow10(precision); 1117 /* 1118 * We "cheat" by converting the fractional part to integer by 1119 * multiplying by a factor of ten. 1120 */ 1121 if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { 1122 /* 1123 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 1124 * (because precision = 3). Now, myround(1000 * 0.99962) will 1125 * return 1000. So, the integer part must be incremented by one 1126 * and the fractional part must be set to zero. 1127 */ 1128 intpart++; 1129 fracpart = 0; 1130 if (estyle && intpart == 10) { 1131 /* 1132 * The value was rounded up to ten, but we only want one 1133 * integer digit if using "e-style". So, the integer 1134 * part must be set to one and the exponent must be 1135 * incremented by one. 1136 */ 1137 intpart = 1; 1138 exponent++; 1139 } 1140 } 1141 1142 /* 1143 * Now that we know the real exponent, we can check whether or not to 1144 * use "e-style" for "%g" (and "%G") conversions. If we don't need 1145 * "e-style", the precision must be adjusted and the integer and 1146 * fractional parts must be recalculated from the original value. 1147 * 1148 * C99 says: "Let P equal the precision if nonzero, 6 if the precision 1149 * is omitted, or 1 if the precision is zero. Then, if a conversion 1150 * with style `E' would have an exponent of X: 1151 * 1152 * - if P > X >= -4, the conversion is with style `f' (or `F') and 1153 * precision P - (X + 1). 1154 * 1155 * - otherwise, the conversion is with style `e' (or `E') and precision 1156 * P - 1." (7.19.6.1, 8) 1157 * 1158 * Note that we had decremented the precision by one. 1159 */ 1160 if (flags & PRINT_F_TYPE_G && estyle && 1161 precision + 1 > exponent && exponent >= -4) { 1162 precision -= exponent; 1163 estyle = 0; 1164 goto again; 1165 } 1166 1167 if (estyle) { 1168 if (exponent < 0) { 1169 exponent = -exponent; 1170 esign = '-'; 1171 } else 1172 esign = '+'; 1173 1174 /* 1175 * Convert the exponent. The sizeof(econvert) is 4. So, the 1176 * econvert buffer can hold e.g. "e+99" and "e-99". We don't 1177 * support an exponent which contains more than two digits. 1178 * Therefore, the following stores are safe. 1179 */ 1180 epos = convert(exponent, econvert, 2, 10, 0); 1181 /* 1182 * C99 says: "The exponent always contains at least two digits, 1183 * and only as many more digits as necessary to represent the 1184 * exponent." (7.19.6.1, 8) 1185 */ 1186 if (epos == 1) 1187 econvert[epos++] = '0'; 1188 econvert[epos++] = esign; 1189 econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; 1190 } 1191 1192 /* Convert the integer part and the fractional part. */ 1193 ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); 1194 if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ 1195 fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); 1196 1197 leadfraczeros = precision - fpos; 1198 1199 if (omitzeros) { 1200 if (fpos > 0) /* Omit trailing fractional part zeros. */ 1201 while (omitcount < fpos && fconvert[omitcount] == '0') 1202 omitcount++; 1203 else { /* The fractional part is zero, omit it completely. */ 1204 omitcount = precision; 1205 leadfraczeros = 0; 1206 } 1207 precision -= omitcount; 1208 } 1209 1210 /* 1211 * Print a decimal point if either the fractional part is non-zero 1212 * and/or the "#" flag was specified. 1213 */ 1214 if (precision > 0 || flags & PRINT_F_NUM) 1215 emitpoint = 1; 1216 if (separators) /* Get the number of group separators we'll print. */ 1217 separators = getnumsep(ipos); 1218 1219 padlen = width /* Minimum field width. */ 1220 - ipos /* Number of integer digits. */ 1221 - epos /* Number of exponent characters. */ 1222 - precision /* Number of fractional digits. */ 1223 - separators /* Number of group separators. */ 1224 - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ 1225 - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ 1226 1227 if (padlen < 0) 1228 padlen = 0; 1229 1230 /* 1231 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is 1232 * ignored." (7.19.6.1, 6) 1233 */ 1234 if (flags & PRINT_F_MINUS) /* Left justifty. */ 1235 padlen = -padlen; 1236 else if (flags & PRINT_F_ZERO && padlen > 0) { 1237 if (sign != 0) { /* Sign. */ 1238 OUTCHAR(str, *len, size, sign); 1239 sign = 0; 1240 } 1241 while (padlen > 0) { /* Leading zeros. */ 1242 OUTCHAR(str, *len, size, '0'); 1243 padlen--; 1244 } 1245 } 1246 while (padlen > 0) { /* Leading spaces. */ 1247 OUTCHAR(str, *len, size, ' '); 1248 padlen--; 1249 } 1250 if (sign != 0) /* Sign. */ 1251 OUTCHAR(str, *len, size, sign); 1252 while (ipos > 0) { /* Integer part. */ 1253 ipos--; 1254 OUTCHAR(str, *len, size, iconvert[ipos]); 1255 if (separators > 0 && ipos > 0 && ipos % 3 == 0) 1256 printsep(str, len, size); 1257 } 1258 if (emitpoint) { /* Decimal point. */ 1259 #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT 1260 if (lc->decimal_point != NULL && *lc->decimal_point != '\0') 1261 OUTCHAR(str, *len, size, *lc->decimal_point); 1262 else /* We'll always print some decimal point character. */ 1263 #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ 1264 OUTCHAR(str, *len, size, '.'); 1265 } 1266 while (leadfraczeros > 0) { /* Leading fractional part zeros. */ 1267 OUTCHAR(str, *len, size, '0'); 1268 leadfraczeros--; 1269 } 1270 while (fpos > omitcount) { /* The remaining fractional part. */ 1271 fpos--; 1272 OUTCHAR(str, *len, size, fconvert[fpos]); 1273 } 1274 while (epos > 0) { /* Exponent. */ 1275 epos--; 1276 OUTCHAR(str, *len, size, econvert[epos]); 1277 } 1278 while (padlen < 0) { /* Trailing spaces. */ 1279 OUTCHAR(str, *len, size, ' '); 1280 padlen++; 1281 } 1282 } 1283 1284 static void 1285 printsep(char *str, size_t *len, size_t size) 1286 { 1287 #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP 1288 struct lconv *lc = localeconv(); 1289 int i; 1290 1291 if (lc->thousands_sep != NULL) 1292 for (i = 0; lc->thousands_sep[i] != '\0'; i++) 1293 OUTCHAR(str, *len, size, lc->thousands_sep[i]); 1294 else 1295 #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ 1296 OUTCHAR(str, *len, size, ','); 1297 } 1298 1299 static int 1300 getnumsep(int digits) 1301 { 1302 int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; 1303 #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP 1304 int strln; 1305 struct lconv *lc = localeconv(); 1306 1307 /* We support an arbitrary separator length (including zero). */ 1308 if (lc->thousands_sep != NULL) { 1309 for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) 1310 continue; 1311 separators *= strln; 1312 } 1313 #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ 1314 return separators; 1315 } 1316 1317 static int 1318 getexponent(LDOUBLE value) 1319 { 1320 LDOUBLE tmp = (value >= 0.0) ? value : -value; 1321 int exponent = 0; 1322 1323 /* 1324 * We check for 99 > exponent > -99 in order to work around possible 1325 * endless loops which could happen (at least) in the second loop (at 1326 * least) if we're called with an infinite value. However, we checked 1327 * for infinity before calling this function using our ISINF() macro, so 1328 * this might be somewhat paranoid. 1329 */ 1330 while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) 1331 tmp *= 10; 1332 while (tmp >= 10.0 && ++exponent < 99) 1333 tmp /= 10; 1334 1335 return exponent; 1336 } 1337 1338 static int 1339 convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) 1340 { 1341 const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; 1342 size_t pos = 0; 1343 1344 /* We return an unterminated buffer with the digits in reverse order. */ 1345 do { 1346 buf[pos++] = digits[value % base]; 1347 value /= base; 1348 } while (value != 0 && pos < size); 1349 1350 return (int)pos; 1351 } 1352 1353 static UINTMAX_T 1354 cast(LDOUBLE value) 1355 { 1356 UINTMAX_T result; 1357 1358 /* 1359 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be 1360 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), 1361 * it may be increased to the nearest higher representable value for the 1362 * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE 1363 * value although converting the latter to UINTMAX_T would overflow. 1364 */ 1365 if (value >= UINTMAX_MAX) 1366 return UINTMAX_MAX; 1367 1368 result = (UINTMAX_T)value; 1369 /* 1370 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to 1371 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates 1372 * the standard). Sigh. 1373 */ 1374 return (result <= value) ? result : result - 1; 1375 } 1376 1377 static UINTMAX_T 1378 myround(LDOUBLE value) 1379 { 1380 UINTMAX_T intpart = cast(value); 1381 1382 return ((value -= intpart) < 0.5) ? intpart : intpart + 1; 1383 } 1384 1385 static LDOUBLE 1386 mypow10(int exponent) 1387 { 1388 LDOUBLE result = 1; 1389 1390 while (exponent > 0) { 1391 result *= 10; 1392 exponent--; 1393 } 1394 while (exponent < 0) { 1395 result /= 10; 1396 exponent++; 1397 } 1398 return result; 1399 } 1400 #endif /* !HAVE_VSNPRINTF */ 1401 1402 #if !HAVE_VASPRINTF 1403 #if NEED_MYMEMCPY 1404 void * 1405 mymemcpy(void *dst, void *src, size_t len) 1406 { 1407 const char *from = src; 1408 char *to = dst; 1409 1410 /* No need for optimization, we use this only to replace va_copy(3). */ 1411 while (len-- > 0) 1412 *to++ = *from++; 1413 return dst; 1414 } 1415 #endif /* NEED_MYMEMCPY */ 1416 1417 int 1418 util_vasprintf(char **ret, const char *format, va_list ap) 1419 { 1420 size_t size; 1421 int len; 1422 va_list aq; 1423 1424 VA_COPY(aq, ap); 1425 len = vsnprintf(NULL, 0, format, aq); 1426 VA_END_COPY(aq); 1427 if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) 1428 return -1; 1429 return vsnprintf(*ret, size, format, ap); 1430 } 1431 #endif /* !HAVE_VASPRINTF */ 1432 1433 #if !HAVE_SNPRINTF 1434 #if HAVE_STDARG_H 1435 int 1436 util_snprintf(char *str, size_t size, const char *format, ...) 1437 #else 1438 int 1439 util_snprintf(va_alist) va_dcl 1440 #endif /* HAVE_STDARG_H */ 1441 { 1442 #if !HAVE_STDARG_H 1443 char *str; 1444 size_t size; 1445 char *format; 1446 #endif /* HAVE_STDARG_H */ 1447 va_list ap; 1448 int len; 1449 1450 VA_START(ap, format); 1451 VA_SHIFT(ap, str, char *); 1452 VA_SHIFT(ap, size, size_t); 1453 VA_SHIFT(ap, format, const char *); 1454 len = vsnprintf(str, size, format, ap); 1455 va_end(ap); 1456 return len; 1457 } 1458 #endif /* !HAVE_SNPRINTF */ 1459 1460 #if !HAVE_ASPRINTF 1461 #if HAVE_STDARG_H 1462 int 1463 util_asprintf(char **ret, const char *format, ...) 1464 #else 1465 int 1466 util_asprintf(va_alist) va_dcl 1467 #endif /* HAVE_STDARG_H */ 1468 { 1469 #if !HAVE_STDARG_H 1470 char **ret; 1471 char *format; 1472 #endif /* HAVE_STDARG_H */ 1473 va_list ap; 1474 int len; 1475 1476 VA_START(ap, format); 1477 VA_SHIFT(ap, ret, char **); 1478 VA_SHIFT(ap, format, const char *); 1479 len = vasprintf(ret, format, ap); 1480 va_end(ap); 1481 return len; 1482 } 1483 #endif /* !HAVE_ASPRINTF */ 1484 #else /* Dummy declaration to avoid empty translation unit warnings. */ 1485 int main(void); 1486 #endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */ 1487 1488 1489 /* vim: set joinspaces textwidth=80: */ 1490