1 /* $NetBSD: snprintf.c,v 1.5 2018/09/29 21:52:33 christos Exp $ */ 2 3 /* 4 * Modified by Dave Hart for integration into NTP 4.2.7 <hart@ntp.org> 5 * 6 * Changed in a backwards-incompatible way to separate HAVE_SNPRINTF 7 * from HW_WANT_RPL_SNPRINTF, etc. for each of the four replaced 8 * functions. 9 * 10 * Changed to honor hw_force_rpl_snprintf=yes, etc. This is used by NTP 11 * to test rpl_snprintf() and rpl_vsnprintf() on platforms which provide 12 * C99-compliant implementations. 13 */ 14 15 /* Id */ 16 17 /* 18 * Copyright (c) 1995 Patrick Powell. 19 * 20 * This code is based on code written by Patrick Powell <papowell@astart.com>. 21 * It may be used for any purpose as long as this notice remains intact on all 22 * source code distributions. 23 */ 24 25 /* 26 * Copyright (c) 2008 Holger Weiss. 27 * 28 * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>. 29 * My changes to the code may freely be used, modified and/or redistributed for 30 * any purpose. It would be nice if additions and fixes to this file (including 31 * trivial code cleanups) would be sent back in order to let me include them in 32 * the version available at <http://www.jhweiss.de/software/snprintf.html>. 33 * However, this is not a requirement for using or redistributing (possibly 34 * modified) versions of this file, nor is leaving this notice intact mandatory. 35 */ 36 37 /* 38 * History 39 * 40 * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1: 41 * 42 * Fixed the detection of infinite floating point values on IRIX (and 43 * possibly other systems) and applied another few minor cleanups. 44 * 45 * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0: 46 * 47 * Added a lot of new features, fixed many bugs, and incorporated various 48 * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery 49 * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller 50 * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH 51 * projects. The additions include: support the "e", "E", "g", "G", and 52 * "F" conversion specifiers (and use conversion style "f" or "F" for the 53 * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", 54 * "t", and "z" length modifiers; support the "#" flag and the (non-C99) 55 * "'" flag; use localeconv(3) (if available) to get both the current 56 * locale's decimal point character and the separator between groups of 57 * digits; fix the handling of various corner cases of field width and 58 * precision specifications; fix various floating point conversion bugs; 59 * handle infinite and NaN floating point values; don't attempt to write to 60 * the output buffer (which may be NULL) if a size of zero was specified; 61 * check for integer overflow of the field width, precision, and return 62 * values and during the floating point conversion; use the OUTCHAR() macro 63 * instead of a function for better performance; provide asprintf(3) and 64 * vasprintf(3) functions; add new test cases. The replacement functions 65 * have been renamed to use an "rpl_" prefix, the function calls in the 66 * main project (and in this file) must be redefined accordingly for each 67 * replacement function which is needed (by using Autoconf or other means). 68 * Various other minor improvements have been applied and the coding style 69 * was cleaned up for consistency. 70 * 71 * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13: 72 * 73 * C99 compliant snprintf(3) and vsnprintf(3) functions return the number 74 * of characters that would have been written to a sufficiently sized 75 * buffer (excluding the '\0'). The original code simply returned the 76 * length of the resulting output string, so that's been fixed. 77 * 78 * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8: 79 * 80 * The original code assumed that both snprintf(3) and vsnprintf(3) were 81 * missing. Some systems only have snprintf(3) but not vsnprintf(3), so 82 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. 83 * 84 * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i: 85 * 86 * The PGP code was using unsigned hexadecimal formats. Unfortunately, 87 * unsigned formats simply didn't work. 88 * 89 * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1: 90 * 91 * Ok, added some minimal floating point support, which means this probably 92 * requires libm on most operating systems. Don't yet support the exponent 93 * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just 94 * wasn't being exercised in ways which showed it, so that's been fixed. 95 * Also, formatted the code to Mutt conventions, and removed dead code left 96 * over from the original. Also, there is now a builtin-test, run with: 97 * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf 98 * 99 * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43: 100 * 101 * This was ugly. It is still ugly. I opted out of floating point 102 * numbers, but the formatter understands just about everything from the 103 * normal C string format, at least as far as I can tell from the Solaris 104 * 2.5 printf(3S) man page. 105 */ 106 107 /* 108 * ToDo 109 * 110 * - Add wide character support. 111 * - Add support for "%a" and "%A" conversions. 112 * - Create test routines which predefine the expected results. Our test cases 113 * usually expose bugs in system implementations rather than in ours :-) 114 */ 115 116 /* 117 * Usage 118 * 119 * 1) The following preprocessor macros should be defined to 1 if the feature or 120 * file in question is available on the target system (by using Autoconf or 121 * other means), though basic functionality should be available as long as 122 * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: 123 * 124 * HW_WANT_RPL_VSNPRINTF 125 * HW_WANT_RPL_SNPRINTF 126 * HW_WANT_RPL_VASPRINTF 127 * HW_WANT_RPL_ASPRINTF 128 * HAVE_VSNPRINTF // define to 1 #if HW_WANT_RPL_VSNPRINTF 129 * HAVE_SNPRINTF // define to 1 #if HW_WANT_RPL_SNPRINTF 130 * HAVE_VASPRINTF // define to 1 #if HW_WANT_RPL_VASPRINTF 131 * HAVE_ASPRINTF // define to 1 #if HW_WANT_RPL_ASPRINTF 132 * HAVE_STDARG_H 133 * HAVE_STDDEF_H 134 * HAVE_STDINT_H 135 * HAVE_STDLIB_H 136 * HAVE_INTTYPES_H 137 * HAVE_LOCALE_H 138 * HAVE_LOCALECONV 139 * HAVE_LCONV_DECIMAL_POINT 140 * HAVE_LCONV_THOUSANDS_SEP 141 * HAVE_LONG_DOUBLE 142 * HAVE_LONG_LONG_INT 143 * HAVE_UNSIGNED_LONG_LONG_INT 144 * HAVE_INTMAX_T 145 * HAVE_UINTMAX_T 146 * HAVE_UINTPTR_T 147 * HAVE_PTRDIFF_T 148 * HAVE_VA_COPY 149 * HAVE___VA_COPY 150 * 151 * 2) The calls to the functions which should be replaced must be redefined 152 * throughout the project files (by using Autoconf or other means): 153 * 154 * #if HW_WANT_RPL_VSNPRINTF 155 * #define vsnprintf rpl_vsnprintf 156 * #endif 157 * #if HW_WANT_RPL_SNPRINTF 158 * #define snprintf rpl_snprintf 159 * #endif 160 * #if HW_WANT_RPL_VASPRINTF 161 * #define vasprintf rpl_vasprintf 162 * #endif 163 * #if HW_WANT_RPL_ASPRINTF 164 * #define asprintf rpl_asprintf 165 * #endif 166 * 167 * 3) The required replacement functions should be declared in some header file 168 * included throughout the project files: 169 * 170 * #if HAVE_CONFIG_H 171 * #include <config.h> 172 * #endif 173 * #if HAVE_STDARG_H 174 * #include <stdarg.h> 175 * #if HW_WANT_RPL_VSNPRINTF 176 * int rpl_vsnprintf(char *, size_t, const char *, va_list); 177 * #endif 178 * #if HW_WANT_RPL_SNPRINTF 179 * int rpl_snprintf(char *, size_t, const char *, ...); 180 * #endif 181 * #if HW_WANT_RPL_VASPRINTF 182 * int rpl_vasprintf(char **, const char *, va_list); 183 * #endif 184 * #if HW_WANT_RPL_ASPRINTF 185 * int rpl_asprintf(char **, const char *, ...); 186 * #endif 187 * #endif 188 * 189 * Autoconf macros for handling step 1 and step 2 are available at 190 * <http://www.jhweiss.de/software/snprintf.html>. 191 */ 192 193 #if HAVE_CONFIG_H 194 #include <config.h> 195 #endif /* HAVE_CONFIG_H */ 196 197 #if TEST_SNPRINTF 198 #include <math.h> /* For pow(3), NAN, and INFINITY. */ 199 #include <string.h> /* For strcmp(3). */ 200 #if defined(__NetBSD__) || \ 201 defined(__FreeBSD__) || \ 202 defined(__OpenBSD__) || \ 203 defined(__NeXT__) || \ 204 defined(__bsd__) 205 #define OS_BSD 1 206 #elif defined(sgi) || defined(__sgi) 207 #ifndef __c99 208 #define __c99 /* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */ 209 #endif /* !defined(__c99) */ 210 #define OS_IRIX 1 211 #define OS_SYSV 1 212 #elif defined(__svr4__) 213 #define OS_SYSV 1 214 #elif defined(__linux__) 215 #define OS_LINUX 1 216 #endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */ 217 #if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */ 218 #ifdef HAVE_SNPRINTF 219 #undef HAVE_SNPRINTF 220 #endif /* defined(HAVE_SNPRINTF) */ 221 #ifdef HAVE_VSNPRINTF 222 #undef HAVE_VSNPRINTF 223 #endif /* defined(HAVE_VSNPRINTF) */ 224 #ifdef HAVE_ASPRINTF 225 #undef HAVE_ASPRINTF 226 #endif /* defined(HAVE_ASPRINTF) */ 227 #ifdef HAVE_VASPRINTF 228 #undef HAVE_VASPRINTF 229 #endif /* defined(HAVE_VASPRINTF) */ 230 #ifdef snprintf 231 #undef snprintf 232 #endif /* defined(snprintf) */ 233 #ifdef vsnprintf 234 #undef vsnprintf 235 #endif /* defined(vsnprintf) */ 236 #ifdef asprintf 237 #undef asprintf 238 #endif /* defined(asprintf) */ 239 #ifdef vasprintf 240 #undef vasprintf 241 #endif /* defined(vasprintf) */ 242 #else /* By default, we assume a modern system for testing. */ 243 #ifndef HAVE_STDARG_H 244 #define HAVE_STDARG_H 1 245 #endif /* HAVE_STDARG_H */ 246 #ifndef HAVE_STDDEF_H 247 #define HAVE_STDDEF_H 1 248 #endif /* HAVE_STDDEF_H */ 249 #ifndef HAVE_STDINT_H 250 #define HAVE_STDINT_H 1 251 #endif /* HAVE_STDINT_H */ 252 #ifndef HAVE_STDLIB_H 253 #define HAVE_STDLIB_H 1 254 #endif /* HAVE_STDLIB_H */ 255 #ifndef HAVE_INTTYPES_H 256 #define HAVE_INTTYPES_H 1 257 #endif /* HAVE_INTTYPES_H */ 258 #ifndef HAVE_LOCALE_H 259 #define HAVE_LOCALE_H 1 260 #endif /* HAVE_LOCALE_H */ 261 #ifndef HAVE_LOCALECONV 262 #define HAVE_LOCALECONV 1 263 #endif /* !defined(HAVE_LOCALECONV) */ 264 #ifndef HAVE_LCONV_DECIMAL_POINT 265 #define HAVE_LCONV_DECIMAL_POINT 1 266 #endif /* HAVE_LCONV_DECIMAL_POINT */ 267 #ifndef HAVE_LCONV_THOUSANDS_SEP 268 #define HAVE_LCONV_THOUSANDS_SEP 1 269 #endif /* HAVE_LCONV_THOUSANDS_SEP */ 270 #ifndef HAVE_LONG_DOUBLE 271 #define HAVE_LONG_DOUBLE 1 272 #endif /* !defined(HAVE_LONG_DOUBLE) */ 273 #ifndef HAVE_LONG_LONG_INT 274 #define HAVE_LONG_LONG_INT 1 275 #endif /* !defined(HAVE_LONG_LONG_INT) */ 276 #ifndef HAVE_UNSIGNED_LONG_LONG_INT 277 #define HAVE_UNSIGNED_LONG_LONG_INT 1 278 #endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */ 279 #ifndef HAVE_INTMAX_T 280 #define HAVE_INTMAX_T 1 281 #endif /* !defined(HAVE_INTMAX_T) */ 282 #ifndef HAVE_UINTMAX_T 283 #define HAVE_UINTMAX_T 1 284 #endif /* !defined(HAVE_UINTMAX_T) */ 285 #ifndef HAVE_UINTPTR_T 286 #define HAVE_UINTPTR_T 1 287 #endif /* !defined(HAVE_UINTPTR_T) */ 288 #ifndef HAVE_PTRDIFF_T 289 #define HAVE_PTRDIFF_T 1 290 #endif /* !defined(HAVE_PTRDIFF_T) */ 291 #ifndef HAVE_VA_COPY 292 #define HAVE_VA_COPY 1 293 #endif /* !defined(HAVE_VA_COPY) */ 294 #ifndef HAVE___VA_COPY 295 #define HAVE___VA_COPY 1 296 #endif /* !defined(HAVE___VA_COPY) */ 297 #endif /* HAVE_CONFIG_H */ 298 #define snprintf rpl_snprintf 299 #define vsnprintf rpl_vsnprintf 300 #define asprintf rpl_asprintf 301 #define vasprintf rpl_vasprintf 302 #endif /* TEST_SNPRINTF */ 303 304 #if HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || HW_WANT_RPL_VASPRINTF 305 #include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ 306 #ifdef VA_START 307 #undef VA_START 308 #endif /* defined(VA_START) */ 309 #ifdef VA_SHIFT 310 #undef VA_SHIFT 311 #endif /* defined(VA_SHIFT) */ 312 #if HAVE_STDARG_H 313 #include <stdarg.h> 314 #define VA_START(ap, last) va_start(ap, last) 315 #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ 316 #else /* Assume <varargs.h> is available. */ 317 #include <varargs.h> 318 #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ 319 #define VA_SHIFT(ap, value, type) value = va_arg(ap, type) 320 #endif /* HAVE_STDARG_H */ 321 322 #if HW_WANT_RPL_VASPRINTF 323 #if HAVE_STDLIB_H 324 #include <stdlib.h> /* For malloc(3). */ 325 #endif /* HAVE_STDLIB_H */ 326 #ifdef VA_COPY 327 #undef VA_COPY 328 #endif /* defined(VA_COPY) */ 329 #ifdef VA_END_COPY 330 #undef VA_END_COPY 331 #endif /* defined(VA_END_COPY) */ 332 #if HAVE_VA_COPY 333 #define VA_COPY(dest, src) va_copy(dest, src) 334 #define VA_END_COPY(ap) va_end(ap) 335 #elif HAVE___VA_COPY 336 #define VA_COPY(dest, src) __va_copy(dest, src) 337 #define VA_END_COPY(ap) va_end(ap) 338 #else 339 #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) 340 #define VA_END_COPY(ap) /* No-op. */ 341 #define NEED_MYMEMCPY 1 342 static void *mymemcpy(void *, void *, size_t); 343 #endif /* HAVE_VA_COPY */ 344 #endif /* HW_WANT_RPL_VASPRINTF */ 345 346 #if HW_WANT_RPL_VSNPRINTF 347 #include <errno.h> /* For ERANGE and errno. */ 348 #include <limits.h> /* For *_MAX. */ 349 #if HAVE_INTTYPES_H 350 #include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */ 351 #endif /* HAVE_INTTYPES_H */ 352 #if HAVE_LOCALE_H 353 #include <locale.h> /* For localeconv(3). */ 354 #endif /* HAVE_LOCALE_H */ 355 #if HAVE_STDDEF_H 356 #include <stddef.h> /* For ptrdiff_t. */ 357 #endif /* HAVE_STDDEF_H */ 358 #if HAVE_STDINT_H 359 #include <stdint.h> /* For intmax_t. */ 360 #endif /* HAVE_STDINT_H */ 361 362 /* Support for unsigned long long int. We may also need ULLONG_MAX. */ 363 #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ 364 #ifdef UINT_MAX 365 #define ULONG_MAX UINT_MAX 366 #else 367 #define ULONG_MAX INT_MAX 368 #endif /* defined(UINT_MAX) */ 369 #endif /* !defined(ULONG_MAX) */ 370 #ifdef ULLONG 371 #undef ULLONG 372 #endif /* defined(ULLONG) */ 373 #if HAVE_UNSIGNED_LONG_LONG_INT 374 #define ULLONG unsigned long long int 375 #ifndef ULLONG_MAX 376 #define ULLONG_MAX ULONG_MAX 377 #endif /* !defined(ULLONG_MAX) */ 378 #else 379 #define ULLONG unsigned long int 380 #ifdef ULLONG_MAX 381 #undef ULLONG_MAX 382 #endif /* defined(ULLONG_MAX) */ 383 #define ULLONG_MAX ULONG_MAX 384 #endif /* HAVE_LONG_LONG_INT */ 385 386 /* Support for uintmax_t. We also need UINTMAX_MAX. */ 387 #ifdef UINTMAX_T 388 #undef UINTMAX_T 389 #endif /* defined(UINTMAX_T) */ 390 #if HAVE_UINTMAX_T || defined(uintmax_t) 391 #define UINTMAX_T uintmax_t 392 #ifndef UINTMAX_MAX 393 #define UINTMAX_MAX ULLONG_MAX 394 #endif /* !defined(UINTMAX_MAX) */ 395 #else 396 #define UINTMAX_T ULLONG 397 #ifdef UINTMAX_MAX 398 #undef UINTMAX_MAX 399 #endif /* defined(UINTMAX_MAX) */ 400 #define UINTMAX_MAX ULLONG_MAX 401 #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ 402 403 /* Support for long double. */ 404 #ifndef LDOUBLE 405 #if HAVE_LONG_DOUBLE 406 #define LDOUBLE long double 407 #else 408 #define LDOUBLE double 409 #endif /* HAVE_LONG_DOUBLE */ 410 #endif /* !defined(LDOUBLE) */ 411 412 /* Support for long long int. */ 413 #ifndef LLONG 414 #if HAVE_LONG_LONG_INT 415 #define LLONG long long int 416 #else 417 #define LLONG long int 418 #endif /* HAVE_LONG_LONG_INT */ 419 #endif /* !defined(LLONG) */ 420 421 /* Support for intmax_t. */ 422 #ifndef INTMAX_T 423 #if HAVE_INTMAX_T || defined(intmax_t) 424 #define INTMAX_T intmax_t 425 #else 426 #define INTMAX_T LLONG 427 #endif /* HAVE_INTMAX_T || defined(intmax_t) */ 428 #endif /* !defined(INTMAX_T) */ 429 430 /* Support for uintptr_t. */ 431 #ifndef UINTPTR_T 432 #if HAVE_UINTPTR_T || defined(uintptr_t) 433 #define UINTPTR_T uintptr_t 434 #else 435 #define UINTPTR_T unsigned long int 436 #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ 437 #endif /* !defined(UINTPTR_T) */ 438 439 /* Support for ptrdiff_t. */ 440 #ifndef PTRDIFF_T 441 #if HAVE_PTRDIFF_T || defined(ptrdiff_t) 442 #define PTRDIFF_T ptrdiff_t 443 #else 444 #define PTRDIFF_T long int 445 #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ 446 #endif /* !defined(PTRDIFF_T) */ 447 448 /* 449 * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: 450 * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an 451 * unsigned type if necessary. This should work just fine in practice. 452 */ 453 #ifndef UPTRDIFF_T 454 #define UPTRDIFF_T PTRDIFF_T 455 #endif /* !defined(UPTRDIFF_T) */ 456 457 /* 458 * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). 459 * However, we'll simply use size_t and convert it to a signed type if 460 * necessary. This should work just fine in practice. 461 */ 462 #ifndef SSIZE_T 463 #define SSIZE_T size_t 464 #endif /* !defined(SSIZE_T) */ 465 466 /* Either ERANGE or E2BIG should be available everywhere. */ 467 #ifndef ERANGE 468 #define ERANGE E2BIG 469 #endif /* !defined(ERANGE) */ 470 #ifndef EOVERFLOW 471 #define EOVERFLOW ERANGE 472 #endif /* !defined(EOVERFLOW) */ 473 474 /* 475 * Buffer size to hold the octal string representation of UINT128_MAX without 476 * nul-termination ("3777777777777777777777777777777777777777777"). 477 */ 478 #ifdef MAX_CONVERT_LENGTH 479 #undef MAX_CONVERT_LENGTH 480 #endif /* defined(MAX_CONVERT_LENGTH) */ 481 #define MAX_CONVERT_LENGTH 43 482 483 /* Format read states. */ 484 #define PRINT_S_DEFAULT 0 485 #define PRINT_S_FLAGS 1 486 #define PRINT_S_WIDTH 2 487 #define PRINT_S_DOT 3 488 #define PRINT_S_PRECISION 4 489 #define PRINT_S_MOD 5 490 #define PRINT_S_CONV 6 491 492 /* Format flags. */ 493 #define PRINT_F_MINUS (1 << 0) 494 #define PRINT_F_PLUS (1 << 1) 495 #define PRINT_F_SPACE (1 << 2) 496 #define PRINT_F_NUM (1 << 3) 497 #define PRINT_F_ZERO (1 << 4) 498 #define PRINT_F_QUOTE (1 << 5) 499 #define PRINT_F_UP (1 << 6) 500 #define PRINT_F_UNSIGNED (1 << 7) 501 #define PRINT_F_TYPE_G (1 << 8) 502 #define PRINT_F_TYPE_E (1 << 9) 503 504 /* Conversion flags. */ 505 #define PRINT_C_CHAR 1 506 #define PRINT_C_SHORT 2 507 #define PRINT_C_LONG 3 508 #define PRINT_C_LLONG 4 509 #define PRINT_C_LDOUBLE 5 510 #define PRINT_C_SIZE 6 511 #define PRINT_C_PTRDIFF 7 512 #define PRINT_C_INTMAX 8 513 514 #ifndef MAX 515 #define MAX(x, y) ((x >= y) ? x : y) 516 #endif /* !defined(MAX) */ 517 #ifndef CHARTOINT 518 #define CHARTOINT(ch) (ch - '0') 519 #endif /* !defined(CHARTOINT) */ 520 #ifndef ISDIGIT 521 #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') 522 #endif /* !defined(ISDIGIT) */ 523 #ifndef ISNAN 524 #define ISNAN(x) (x != x) 525 #endif /* !defined(ISNAN) */ 526 #ifndef ISINF 527 #define ISINF(x) (x != 0.0 && x + x == x) 528 #endif /* !defined(ISINF) */ 529 530 #ifdef OUTCHAR 531 #undef OUTCHAR 532 #endif /* defined(OUTCHAR) */ 533 #define OUTCHAR(str, len, size, ch) \ 534 do { \ 535 if (len + 1 < size) \ 536 str[len] = ch; \ 537 (len)++; \ 538 } while (/* CONSTCOND */ 0) 539 540 static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); 541 static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); 542 static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); 543 static void printsep(char *, size_t *, size_t); 544 static int getnumsep(int); 545 static int getexponent(LDOUBLE); 546 static int convert(UINTMAX_T, char *, size_t, int, int); 547 static UINTMAX_T cast(LDOUBLE); 548 static UINTMAX_T myround(LDOUBLE); 549 static LDOUBLE mypow10(int); 550 551 int 552 rpl_vsnprintf(char *str, size_t size, const char *format, va_list args); 553 554 int 555 rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) 556 { 557 LDOUBLE fvalue; 558 INTMAX_T value; 559 unsigned char cvalue; 560 const char *strvalue; 561 INTMAX_T *intmaxptr; 562 PTRDIFF_T *ptrdiffptr; 563 SSIZE_T *sizeptr; 564 LLONG *llongptr; 565 long int *longptr; 566 int *intptr; 567 short int *shortptr; 568 signed char *charptr; 569 size_t len = 0; 570 int overflow = 0; 571 int base = 0; 572 int cflags = 0; 573 int flags = 0; 574 int width = 0; 575 int precision = -1; 576 int state = PRINT_S_DEFAULT; 577 char ch = *format++; 578 579 /* 580 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null 581 * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer 582 * even if a size larger than zero was specified. At least NetBSD's 583 * snprintf(3) does the same, as well as other versions of this file. 584 * (Though some of these versions will write to a non-NULL buffer even 585 * if a size of zero was specified, which violates the standard.) 586 */ 587 if (str == NULL && size != 0) 588 size = 0; 589 590 while (ch != '\0') 591 switch (state) { 592 case PRINT_S_DEFAULT: 593 if (ch == '%') 594 state = PRINT_S_FLAGS; 595 else 596 OUTCHAR(str, len, size, ch); 597 ch = *format++; 598 break; 599 case PRINT_S_FLAGS: 600 switch (ch) { 601 case '-': 602 flags |= PRINT_F_MINUS; 603 ch = *format++; 604 break; 605 case '+': 606 flags |= PRINT_F_PLUS; 607 ch = *format++; 608 break; 609 case ' ': 610 flags |= PRINT_F_SPACE; 611 ch = *format++; 612 break; 613 case '#': 614 flags |= PRINT_F_NUM; 615 ch = *format++; 616 break; 617 case '0': 618 flags |= PRINT_F_ZERO; 619 ch = *format++; 620 break; 621 case '\'': /* SUSv2 flag (not in C99). */ 622 flags |= PRINT_F_QUOTE; 623 ch = *format++; 624 break; 625 default: 626 state = PRINT_S_WIDTH; 627 break; 628 } 629 break; 630 case PRINT_S_WIDTH: 631 if (ISDIGIT(ch)) { 632 ch = CHARTOINT(ch); 633 if (width > (INT_MAX - ch) / 10) { 634 overflow = 1; 635 goto out; 636 } 637 width = 10 * width + ch; 638 ch = *format++; 639 } else if (ch == '*') { 640 /* 641 * C99 says: "A negative field width argument is 642 * taken as a `-' flag followed by a positive 643 * field width." (7.19.6.1, 5) 644 */ 645 if ((width = va_arg(args, int)) < 0) { 646 flags |= PRINT_F_MINUS; 647 width = -width; 648 } 649 ch = *format++; 650 state = PRINT_S_DOT; 651 } else 652 state = PRINT_S_DOT; 653 break; 654 case PRINT_S_DOT: 655 if (ch == '.') { 656 state = PRINT_S_PRECISION; 657 ch = *format++; 658 } else 659 state = PRINT_S_MOD; 660 break; 661 case PRINT_S_PRECISION: 662 if (precision == -1) 663 precision = 0; 664 if (ISDIGIT(ch)) { 665 ch = CHARTOINT(ch); 666 if (precision > (INT_MAX - ch) / 10) { 667 overflow = 1; 668 goto out; 669 } 670 precision = 10 * precision + ch; 671 ch = *format++; 672 } else if (ch == '*') { 673 /* 674 * C99 says: "A negative precision argument is 675 * taken as if the precision were omitted." 676 * (7.19.6.1, 5) 677 */ 678 if ((precision = va_arg(args, int)) < 0) 679 precision = -1; 680 ch = *format++; 681 state = PRINT_S_MOD; 682 } else 683 state = PRINT_S_MOD; 684 break; 685 case PRINT_S_MOD: 686 switch (ch) { 687 case 'h': 688 ch = *format++; 689 if (ch == 'h') { /* It's a char. */ 690 ch = *format++; 691 cflags = PRINT_C_CHAR; 692 } else 693 cflags = PRINT_C_SHORT; 694 break; 695 case 'l': 696 ch = *format++; 697 if (ch == 'l') { /* It's a long long. */ 698 ch = *format++; 699 cflags = PRINT_C_LLONG; 700 } else 701 cflags = PRINT_C_LONG; 702 break; 703 case 'L': 704 cflags = PRINT_C_LDOUBLE; 705 ch = *format++; 706 break; 707 case 'j': 708 cflags = PRINT_C_INTMAX; 709 ch = *format++; 710 break; 711 case 't': 712 cflags = PRINT_C_PTRDIFF; 713 ch = *format++; 714 break; 715 case 'z': 716 cflags = PRINT_C_SIZE; 717 ch = *format++; 718 break; 719 } 720 state = PRINT_S_CONV; 721 break; 722 case PRINT_S_CONV: 723 switch (ch) { 724 case 'd': 725 /* FALLTHROUGH */ 726 case 'i': 727 switch (cflags) { 728 case PRINT_C_CHAR: 729 value = (signed char)va_arg(args, int); 730 break; 731 case PRINT_C_SHORT: 732 value = (short int)va_arg(args, int); 733 break; 734 case PRINT_C_LONG: 735 value = va_arg(args, long int); 736 break; 737 case PRINT_C_LLONG: 738 value = va_arg(args, LLONG); 739 break; 740 case PRINT_C_SIZE: 741 value = va_arg(args, SSIZE_T); 742 break; 743 case PRINT_C_INTMAX: 744 value = va_arg(args, INTMAX_T); 745 break; 746 case PRINT_C_PTRDIFF: 747 value = va_arg(args, PTRDIFF_T); 748 break; 749 default: 750 value = va_arg(args, int); 751 break; 752 } 753 fmtint(str, &len, size, value, 10, width, 754 precision, flags); 755 break; 756 case 'X': 757 flags |= PRINT_F_UP; 758 /* FALLTHROUGH */ 759 case 'x': 760 base = 16; 761 /* FALLTHROUGH */ 762 case 'o': 763 if (base == 0) 764 base = 8; 765 /* FALLTHROUGH */ 766 case 'u': 767 if (base == 0) 768 base = 10; 769 flags |= PRINT_F_UNSIGNED; 770 switch (cflags) { 771 case PRINT_C_CHAR: 772 value = (unsigned char)va_arg(args, 773 unsigned int); 774 break; 775 case PRINT_C_SHORT: 776 value = (unsigned short int)va_arg(args, 777 unsigned int); 778 break; 779 case PRINT_C_LONG: 780 value = va_arg(args, unsigned long int); 781 break; 782 case PRINT_C_LLONG: 783 value = va_arg(args, ULLONG); 784 break; 785 case PRINT_C_SIZE: 786 value = va_arg(args, size_t); 787 break; 788 case PRINT_C_INTMAX: 789 value = va_arg(args, UINTMAX_T); 790 break; 791 case PRINT_C_PTRDIFF: 792 value = va_arg(args, UPTRDIFF_T); 793 break; 794 default: 795 value = va_arg(args, unsigned int); 796 break; 797 } 798 fmtint(str, &len, size, value, base, width, 799 precision, flags); 800 break; 801 case 'A': 802 /* Not yet supported, we'll use "%F". */ 803 /* FALLTHROUGH */ 804 case 'F': 805 flags |= PRINT_F_UP; 806 /* FALLTHROUGH */ 807 case 'a': 808 /* Not yet supported, we'll use "%f". */ 809 /* FALLTHROUGH */ 810 case 'f': 811 if (cflags == PRINT_C_LDOUBLE) 812 fvalue = va_arg(args, LDOUBLE); 813 else 814 fvalue = va_arg(args, double); 815 fmtflt(str, &len, size, fvalue, width, 816 precision, flags, &overflow); 817 if (overflow) 818 goto out; 819 break; 820 case 'E': 821 flags |= PRINT_F_UP; 822 /* FALLTHROUGH */ 823 case 'e': 824 flags |= PRINT_F_TYPE_E; 825 if (cflags == PRINT_C_LDOUBLE) 826 fvalue = va_arg(args, LDOUBLE); 827 else 828 fvalue = va_arg(args, double); 829 fmtflt(str, &len, size, fvalue, width, 830 precision, flags, &overflow); 831 if (overflow) 832 goto out; 833 break; 834 case 'G': 835 flags |= PRINT_F_UP; 836 /* FALLTHROUGH */ 837 case 'g': 838 flags |= PRINT_F_TYPE_G; 839 if (cflags == PRINT_C_LDOUBLE) 840 fvalue = va_arg(args, LDOUBLE); 841 else 842 fvalue = va_arg(args, double); 843 /* 844 * If the precision is zero, it is treated as 845 * one (cf. C99: 7.19.6.1, 8). 846 */ 847 if (precision == 0) 848 precision = 1; 849 fmtflt(str, &len, size, fvalue, width, 850 precision, flags, &overflow); 851 if (overflow) 852 goto out; 853 break; 854 case 'c': 855 cvalue = va_arg(args, int); 856 OUTCHAR(str, len, size, cvalue); 857 break; 858 case 's': 859 strvalue = va_arg(args, char *); 860 fmtstr(str, &len, size, strvalue, width, 861 precision, flags); 862 break; 863 case 'p': 864 /* 865 * C99 says: "The value of the pointer is 866 * converted to a sequence of printing 867 * characters, in an implementation-defined 868 * manner." (C99: 7.19.6.1, 8) 869 */ 870 if ((strvalue = va_arg(args, void *)) == NULL) 871 /* 872 * We use the glibc format. BSD prints 873 * "0x0", SysV "0". 874 */ 875 fmtstr(str, &len, size, "(nil)", width, 876 -1, flags); 877 else { 878 /* 879 * We use the BSD/glibc format. SysV 880 * omits the "0x" prefix (which we emit 881 * using the PRINT_F_NUM flag). 882 */ 883 flags |= PRINT_F_NUM; 884 flags |= PRINT_F_UNSIGNED; 885 fmtint(str, &len, size, 886 (UINTPTR_T)strvalue, 16, width, 887 precision, flags); 888 } 889 break; 890 case 'n': 891 switch (cflags) { 892 case PRINT_C_CHAR: 893 charptr = va_arg(args, signed char *); 894 *charptr = (signed char)len; 895 break; 896 case PRINT_C_SHORT: 897 shortptr = va_arg(args, short int *); 898 *shortptr = (short int)len; 899 break; 900 case PRINT_C_LONG: 901 longptr = va_arg(args, long int *); 902 *longptr = (long int)len; 903 break; 904 case PRINT_C_LLONG: 905 llongptr = va_arg(args, LLONG *); 906 *llongptr = (LLONG)len; 907 break; 908 case PRINT_C_SIZE: 909 /* 910 * C99 says that with the "z" length 911 * modifier, "a following `n' conversion 912 * specifier applies to a pointer to a 913 * signed integer type corresponding to 914 * size_t argument." (7.19.6.1, 7) 915 */ 916 sizeptr = va_arg(args, SSIZE_T *); 917 *sizeptr = (SSIZE_T)len; 918 break; 919 case PRINT_C_INTMAX: 920 intmaxptr = va_arg(args, INTMAX_T *); 921 *intmaxptr = (INTMAX_T)len; 922 break; 923 case PRINT_C_PTRDIFF: 924 ptrdiffptr = va_arg(args, PTRDIFF_T *); 925 *ptrdiffptr = (PTRDIFF_T)len; 926 break; 927 default: 928 intptr = va_arg(args, int *); 929 *intptr = (int)len; 930 break; 931 } 932 break; 933 case '%': /* Print a "%" character verbatim. */ 934 OUTCHAR(str, len, size, ch); 935 break; 936 default: /* Skip other characters. */ 937 break; 938 } 939 ch = *format++; 940 state = PRINT_S_DEFAULT; 941 base = cflags = flags = width = 0; 942 precision = -1; 943 break; 944 } 945 out: 946 if (len < size) 947 str[len] = '\0'; 948 else if (size > 0) 949 str[size - 1] = '\0'; 950 951 if (overflow || len >= INT_MAX) { 952 errno = overflow ? EOVERFLOW : ERANGE; 953 return -1; 954 } 955 return (int)len; 956 } 957 958 static void 959 fmtstr(char *str, size_t *len, size_t size, const char *value, int width, 960 int precision, int flags) 961 { 962 int padlen, strln; /* Amount to pad. */ 963 int noprecision = (precision == -1); 964 965 if (value == NULL) /* We're forgiving. */ 966 value = "(null)"; 967 968 /* If a precision was specified, don't read the string past it. */ 969 for (strln = 0; value[strln] != '\0' && 970 (noprecision || strln < precision); strln++) 971 continue; 972 973 if ((padlen = width - strln) < 0) 974 padlen = 0; 975 if (flags & PRINT_F_MINUS) /* Left justify. */ 976 padlen = -padlen; 977 978 while (padlen > 0) { /* Leading spaces. */ 979 OUTCHAR(str, *len, size, ' '); 980 padlen--; 981 } 982 while (*value != '\0' && (noprecision || precision-- > 0)) { 983 OUTCHAR(str, *len, size, *value); 984 value++; 985 } 986 while (padlen < 0) { /* Trailing spaces. */ 987 OUTCHAR(str, *len, size, ' '); 988 padlen++; 989 } 990 } 991 992 static void 993 fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, 994 int precision, int flags) 995 { 996 UINTMAX_T uvalue; 997 char iconvert[MAX_CONVERT_LENGTH]; 998 char sign = 0; 999 char hexprefix = 0; 1000 int spadlen = 0; /* Amount to space pad. */ 1001 int zpadlen = 0; /* Amount to zero pad. */ 1002 int pos; 1003 int separators = (flags & PRINT_F_QUOTE); 1004 int noprecision = (precision == -1); 1005 1006 if (flags & PRINT_F_UNSIGNED) 1007 uvalue = value; 1008 else { 1009 uvalue = (value >= 0) ? value : -value; 1010 if (value < 0) 1011 sign = '-'; 1012 else if (flags & PRINT_F_PLUS) /* Do a sign. */ 1013 sign = '+'; 1014 else if (flags & PRINT_F_SPACE) 1015 sign = ' '; 1016 } 1017 1018 pos = convert(uvalue, iconvert, sizeof(iconvert), base, 1019 flags & PRINT_F_UP); 1020 1021 if (flags & PRINT_F_NUM && uvalue != 0) { 1022 /* 1023 * C99 says: "The result is converted to an `alternative form'. 1024 * For `o' conversion, it increases the precision, if and only 1025 * if necessary, to force the first digit of the result to be a 1026 * zero (if the value and precision are both 0, a single 0 is 1027 * printed). For `x' (or `X') conversion, a nonzero result has 1028 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) 1029 */ 1030 switch (base) { 1031 case 8: 1032 if (precision <= pos) 1033 precision = pos + 1; 1034 break; 1035 case 16: 1036 hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; 1037 break; 1038 } 1039 } 1040 1041 if (separators) /* Get the number of group separators we'll print. */ 1042 separators = getnumsep(pos); 1043 1044 zpadlen = precision - pos - separators; 1045 spadlen = width /* Minimum field width. */ 1046 - separators /* Number of separators. */ 1047 - MAX(precision, pos) /* Number of integer digits. */ 1048 - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ 1049 - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ 1050 1051 if (zpadlen < 0) 1052 zpadlen = 0; 1053 if (spadlen < 0) 1054 spadlen = 0; 1055 1056 /* 1057 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is 1058 * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a 1059 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) 1060 */ 1061 if (flags & PRINT_F_MINUS) /* Left justify. */ 1062 spadlen = -spadlen; 1063 else if (flags & PRINT_F_ZERO && noprecision) { 1064 zpadlen += spadlen; 1065 spadlen = 0; 1066 } 1067 while (spadlen > 0) { /* Leading spaces. */ 1068 OUTCHAR(str, *len, size, ' '); 1069 spadlen--; 1070 } 1071 if (sign != 0) /* Sign. */ 1072 OUTCHAR(str, *len, size, sign); 1073 if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ 1074 OUTCHAR(str, *len, size, '0'); 1075 OUTCHAR(str, *len, size, hexprefix); 1076 } 1077 while (zpadlen > 0) { /* Leading zeros. */ 1078 OUTCHAR(str, *len, size, '0'); 1079 zpadlen--; 1080 } 1081 while (pos > 0) { /* The actual digits. */ 1082 pos--; 1083 OUTCHAR(str, *len, size, iconvert[pos]); 1084 if (separators > 0 && pos > 0 && pos % 3 == 0) 1085 printsep(str, len, size); 1086 } 1087 while (spadlen < 0) { /* Trailing spaces. */ 1088 OUTCHAR(str, *len, size, ' '); 1089 spadlen++; 1090 } 1091 } 1092 1093 static void 1094 fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, 1095 int precision, int flags, int *overflow) 1096 { 1097 LDOUBLE ufvalue; 1098 UINTMAX_T intpart; 1099 UINTMAX_T fracpart; 1100 UINTMAX_T mask; 1101 const char *infnan = NULL; 1102 char iconvert[MAX_CONVERT_LENGTH]; 1103 char fconvert[MAX_CONVERT_LENGTH]; 1104 char econvert[4]; /* "e-12" (without nul-termination). */ 1105 char esign = 0; 1106 char sign = 0; 1107 int leadfraczeros = 0; 1108 int exponent = 0; 1109 int emitpoint = 0; 1110 int omitzeros = 0; 1111 int omitcount = 0; 1112 int padlen = 0; 1113 int epos = 0; 1114 int fpos = 0; 1115 int ipos = 0; 1116 int separators = (flags & PRINT_F_QUOTE); 1117 int estyle = (flags & PRINT_F_TYPE_E); 1118 #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT 1119 struct lconv *lc = localeconv(); 1120 #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ 1121 1122 /* 1123 * AIX' man page says the default is 0, but C99 and at least Solaris' 1124 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX 1125 * defaults to 6. 1126 */ 1127 if (precision == -1) 1128 precision = 6; 1129 1130 if (fvalue < 0.0) 1131 sign = '-'; 1132 else if (flags & PRINT_F_PLUS) /* Do a sign. */ 1133 sign = '+'; 1134 else if (flags & PRINT_F_SPACE) 1135 sign = ' '; 1136 1137 if (ISNAN(fvalue)) 1138 infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; 1139 else if (ISINF(fvalue)) 1140 infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; 1141 1142 if (infnan != NULL) { 1143 if (sign != 0) 1144 iconvert[ipos++] = sign; 1145 while (*infnan != '\0') 1146 iconvert[ipos++] = *infnan++; 1147 fmtstr(str, len, size, iconvert, width, ipos, flags); 1148 return; 1149 } 1150 1151 /* "%e" (or "%E") or "%g" (or "%G") conversion. */ 1152 if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { 1153 if (flags & PRINT_F_TYPE_G) { 1154 /* 1155 * For "%g" (and "%G") conversions, the precision 1156 * specifies the number of significant digits, which 1157 * includes the digits in the integer part. The 1158 * conversion will or will not be using "e-style" (like 1159 * "%e" or "%E" conversions) depending on the precision 1160 * and on the exponent. However, the exponent can be 1161 * affected by rounding the converted value, so we'll 1162 * leave this decision for later. Until then, we'll 1163 * assume that we're going to do an "e-style" conversion 1164 * (in order to get the exponent calculated). For 1165 * "e-style", the precision must be decremented by one. 1166 */ 1167 precision--; 1168 /* 1169 * For "%g" (and "%G") conversions, trailing zeros are 1170 * removed from the fractional portion of the result 1171 * unless the "#" flag was specified. 1172 */ 1173 if (!(flags & PRINT_F_NUM)) 1174 omitzeros = 1; 1175 } 1176 exponent = getexponent(fvalue); 1177 estyle = 1; 1178 } 1179 1180 again: 1181 /* 1182 * Sorry, we only support 9, 19, or 38 digits (that is, the number of 1183 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value 1184 * minus one) past the decimal point due to our conversion method. 1185 */ 1186 switch (sizeof(UINTMAX_T)) { 1187 case 16: 1188 if (precision > 38) 1189 precision = 38; 1190 break; 1191 case 8: 1192 if (precision > 19) 1193 precision = 19; 1194 break; 1195 default: 1196 if (precision > 9) 1197 precision = 9; 1198 break; 1199 } 1200 1201 ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; 1202 if (estyle) /* We want exactly one integer digit. */ 1203 ufvalue /= mypow10(exponent); 1204 1205 if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { 1206 *overflow = 1; 1207 return; 1208 } 1209 1210 /* 1211 * Factor of ten with the number of digits needed for the fractional 1212 * part. For example, if the precision is 3, the mask will be 1000. 1213 */ 1214 mask = (UINTMAX_T)mypow10(precision); 1215 /* 1216 * We "cheat" by converting the fractional part to integer by 1217 * multiplying by a factor of ten. 1218 */ 1219 if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { 1220 /* 1221 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 1222 * (because precision = 3). Now, myround(1000 * 0.99962) will 1223 * return 1000. So, the integer part must be incremented by one 1224 * and the fractional part must be set to zero. 1225 */ 1226 intpart++; 1227 fracpart = 0; 1228 if (estyle && intpart == 10) { 1229 /* 1230 * The value was rounded up to ten, but we only want one 1231 * integer digit if using "e-style". So, the integer 1232 * part must be set to one and the exponent must be 1233 * incremented by one. 1234 */ 1235 intpart = 1; 1236 exponent++; 1237 } 1238 } 1239 1240 /* 1241 * Now that we know the real exponent, we can check whether or not to 1242 * use "e-style" for "%g" (and "%G") conversions. If we don't need 1243 * "e-style", the precision must be adjusted and the integer and 1244 * fractional parts must be recalculated from the original value. 1245 * 1246 * C99 says: "Let P equal the precision if nonzero, 6 if the precision 1247 * is omitted, or 1 if the precision is zero. Then, if a conversion 1248 * with style `E' would have an exponent of X: 1249 * 1250 * - if P > X >= -4, the conversion is with style `f' (or `F') and 1251 * precision P - (X + 1). 1252 * 1253 * - otherwise, the conversion is with style `e' (or `E') and precision 1254 * P - 1." (7.19.6.1, 8) 1255 * 1256 * Note that we had decremented the precision by one. 1257 */ 1258 if (flags & PRINT_F_TYPE_G && estyle && 1259 precision + 1 > exponent && exponent >= -4) { 1260 precision -= exponent; 1261 estyle = 0; 1262 goto again; 1263 } 1264 1265 if (estyle) { 1266 if (exponent < 0) { 1267 exponent = -exponent; 1268 esign = '-'; 1269 } else 1270 esign = '+'; 1271 1272 /* 1273 * Convert the exponent. The sizeof(econvert) is 4. So, the 1274 * econvert buffer can hold e.g. "e+99" and "e-99". We don't 1275 * support an exponent which contains more than two digits. 1276 * Therefore, the following stores are safe. 1277 */ 1278 epos = convert(exponent, econvert, 2, 10, 0); 1279 /* 1280 * C99 says: "The exponent always contains at least two digits, 1281 * and only as many more digits as necessary to represent the 1282 * exponent." (7.19.6.1, 8) 1283 */ 1284 if (epos == 1) 1285 econvert[epos++] = '0'; 1286 econvert[epos++] = esign; 1287 econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; 1288 } 1289 1290 /* Convert the integer part and the fractional part. */ 1291 ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); 1292 if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ 1293 fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); 1294 1295 leadfraczeros = precision - fpos; 1296 1297 if (omitzeros) { 1298 if (fpos > 0) /* Omit trailing fractional part zeros. */ 1299 while (omitcount < fpos && fconvert[omitcount] == '0') 1300 omitcount++; 1301 else { /* The fractional part is zero, omit it completely. */ 1302 omitcount = precision; 1303 leadfraczeros = 0; 1304 } 1305 precision -= omitcount; 1306 } 1307 1308 /* 1309 * Print a decimal point if either the fractional part is non-zero 1310 * and/or the "#" flag was specified. 1311 */ 1312 if (precision > 0 || flags & PRINT_F_NUM) 1313 emitpoint = 1; 1314 if (separators) /* Get the number of group separators we'll print. */ 1315 separators = getnumsep(ipos); 1316 1317 padlen = width /* Minimum field width. */ 1318 - ipos /* Number of integer digits. */ 1319 - epos /* Number of exponent characters. */ 1320 - precision /* Number of fractional digits. */ 1321 - separators /* Number of group separators. */ 1322 - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ 1323 - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ 1324 1325 if (padlen < 0) 1326 padlen = 0; 1327 1328 /* 1329 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is 1330 * ignored." (7.19.6.1, 6) 1331 */ 1332 if (flags & PRINT_F_MINUS) /* Left justifty. */ 1333 padlen = -padlen; 1334 else if (flags & PRINT_F_ZERO && padlen > 0) { 1335 if (sign != 0) { /* Sign. */ 1336 OUTCHAR(str, *len, size, sign); 1337 sign = 0; 1338 } 1339 while (padlen > 0) { /* Leading zeros. */ 1340 OUTCHAR(str, *len, size, '0'); 1341 padlen--; 1342 } 1343 } 1344 while (padlen > 0) { /* Leading spaces. */ 1345 OUTCHAR(str, *len, size, ' '); 1346 padlen--; 1347 } 1348 if (sign != 0) /* Sign. */ 1349 OUTCHAR(str, *len, size, sign); 1350 while (ipos > 0) { /* Integer part. */ 1351 ipos--; 1352 OUTCHAR(str, *len, size, iconvert[ipos]); 1353 if (separators > 0 && ipos > 0 && ipos % 3 == 0) 1354 printsep(str, len, size); 1355 } 1356 if (emitpoint) { /* Decimal point. */ 1357 #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT 1358 if (lc->decimal_point != NULL && *lc->decimal_point != '\0') 1359 OUTCHAR(str, *len, size, *lc->decimal_point); 1360 else /* We'll always print some decimal point character. */ 1361 #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ 1362 OUTCHAR(str, *len, size, '.'); 1363 } 1364 while (leadfraczeros > 0) { /* Leading fractional part zeros. */ 1365 OUTCHAR(str, *len, size, '0'); 1366 leadfraczeros--; 1367 } 1368 while (fpos > omitcount) { /* The remaining fractional part. */ 1369 fpos--; 1370 OUTCHAR(str, *len, size, fconvert[fpos]); 1371 } 1372 while (epos > 0) { /* Exponent. */ 1373 epos--; 1374 OUTCHAR(str, *len, size, econvert[epos]); 1375 } 1376 while (padlen < 0) { /* Trailing spaces. */ 1377 OUTCHAR(str, *len, size, ' '); 1378 padlen++; 1379 } 1380 } 1381 1382 static void 1383 printsep(char *str, size_t *len, size_t size) 1384 { 1385 #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP 1386 struct lconv *lc = localeconv(); 1387 int i; 1388 1389 if (lc->thousands_sep != NULL) 1390 for (i = 0; lc->thousands_sep[i] != '\0'; i++) 1391 OUTCHAR(str, *len, size, lc->thousands_sep[i]); 1392 else 1393 #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ 1394 OUTCHAR(str, *len, size, ','); 1395 } 1396 1397 static int 1398 getnumsep(int digits) 1399 { 1400 int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; 1401 #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP 1402 int strln; 1403 struct lconv *lc = localeconv(); 1404 1405 /* We support an arbitrary separator length (including zero). */ 1406 if (lc->thousands_sep != NULL) { 1407 for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) 1408 continue; 1409 separators *= strln; 1410 } 1411 #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ 1412 return separators; 1413 } 1414 1415 static int 1416 getexponent(LDOUBLE value) 1417 { 1418 LDOUBLE tmp = (value >= 0.0) ? value : -value; 1419 int exponent = 0; 1420 1421 /* 1422 * We check for 99 > exponent > -99 in order to work around possible 1423 * endless loops which could happen (at least) in the second loop (at 1424 * least) if we're called with an infinite value. However, we checked 1425 * for infinity before calling this function using our ISINF() macro, so 1426 * this might be somewhat paranoid. 1427 */ 1428 while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) 1429 tmp *= 10; 1430 while (tmp >= 10.0 && ++exponent < 99) 1431 tmp /= 10; 1432 1433 return exponent; 1434 } 1435 1436 static int 1437 convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) 1438 { 1439 const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; 1440 size_t pos = 0; 1441 1442 /* We return an unterminated buffer with the digits in reverse order. */ 1443 do { 1444 buf[pos++] = digits[value % base]; 1445 value /= base; 1446 } while (value != 0 && pos < size); 1447 1448 return (int)pos; 1449 } 1450 1451 static UINTMAX_T 1452 cast(LDOUBLE value) 1453 { 1454 UINTMAX_T result; 1455 1456 /* 1457 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be 1458 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), 1459 * it may be increased to the nearest higher representable value for the 1460 * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE 1461 * value although converting the latter to UINTMAX_T would overflow. 1462 */ 1463 if (value >= UINTMAX_MAX) 1464 return UINTMAX_MAX; 1465 1466 result = (UINTMAX_T)value; 1467 /* 1468 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to 1469 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates 1470 * the standard). Sigh. 1471 */ 1472 return (result <= value) ? result : result - 1; 1473 } 1474 1475 static UINTMAX_T 1476 myround(LDOUBLE value) 1477 { 1478 UINTMAX_T intpart = cast(value); 1479 1480 return ((value -= intpart) < 0.5) ? intpart : intpart + 1; 1481 } 1482 1483 static LDOUBLE 1484 mypow10(int exponent) 1485 { 1486 LDOUBLE result = 1; 1487 1488 while (exponent > 0) { 1489 result *= 10; 1490 exponent--; 1491 } 1492 while (exponent < 0) { 1493 result /= 10; 1494 exponent++; 1495 } 1496 return result; 1497 } 1498 #endif /* HW_WANT_RPL_VSNPRINTF */ 1499 1500 #if HW_WANT_RPL_VASPRINTF 1501 #if NEED_MYMEMCPY 1502 void * 1503 mymemcpy(void *dst, void *src, size_t len) 1504 { 1505 const char *from = src; 1506 char *to = dst; 1507 1508 /* No need for optimization, we use this only to replace va_copy(3). */ 1509 while (len-- > 0) 1510 *to++ = *from++; 1511 return dst; 1512 } 1513 #endif /* NEED_MYMEMCPY */ 1514 1515 int 1516 rpl_vasprintf(char **ret, const char *format, va_list ap); 1517 1518 int 1519 rpl_vasprintf(char **ret, const char *format, va_list ap) 1520 { 1521 size_t size; 1522 int len; 1523 va_list aq; 1524 1525 VA_COPY(aq, ap); 1526 len = vsnprintf(NULL, 0, format, aq); 1527 VA_END_COPY(aq); 1528 if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) 1529 return -1; 1530 return vsnprintf(*ret, size, format, ap); 1531 } 1532 #endif /* HW_WANT_RPL_VASPRINTF */ 1533 1534 #if HW_WANT_RPL_SNPRINTF 1535 #if HAVE_STDARG_H 1536 int 1537 rpl_snprintf(char *str, size_t size, const char *format, ...); 1538 1539 int 1540 rpl_snprintf(char *str, size_t size, const char *format, ...) 1541 #else 1542 int 1543 rpl_snprintf(va_alist) va_dcl 1544 #endif /* HAVE_STDARG_H */ 1545 { 1546 #if !HAVE_STDARG_H 1547 char *str; 1548 size_t size; 1549 char *format; 1550 #endif /* HAVE_STDARG_H */ 1551 va_list ap; 1552 int len; 1553 1554 VA_START(ap, format); 1555 VA_SHIFT(ap, str, char *); 1556 VA_SHIFT(ap, size, size_t); 1557 VA_SHIFT(ap, format, const char *); 1558 len = vsnprintf(str, size, format, ap); 1559 va_end(ap); 1560 return len; 1561 } 1562 #endif /* HW_WANT_RPL_SNPRINTF */ 1563 1564 #if HW_WANT_RPL_ASPRINTF 1565 #if HAVE_STDARG_H 1566 int 1567 rpl_asprintf(char **ret, const char *format, ...); 1568 1569 int 1570 rpl_asprintf(char **ret, const char *format, ...) 1571 #else 1572 int 1573 rpl_asprintf(va_alist) va_dcl 1574 #endif /* HAVE_STDARG_H */ 1575 { 1576 #if !HAVE_STDARG_H 1577 char **ret; 1578 char *format; 1579 #endif /* HAVE_STDARG_H */ 1580 va_list ap; 1581 int len; 1582 1583 VA_START(ap, format); 1584 VA_SHIFT(ap, ret, char **); 1585 VA_SHIFT(ap, format, const char *); 1586 len = vasprintf(ret, format, ap); 1587 va_end(ap); 1588 return len; 1589 } 1590 #endif /* HW_WANT_RPL_ASPRINTF */ 1591 #else /* Dummy declaration to avoid empty translation unit warnings. */ 1592 int main(void); 1593 #endif /* HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || [...] */ 1594 1595 #if TEST_SNPRINTF 1596 int 1597 main(void) 1598 { 1599 const char *float_fmt[] = { 1600 /* "%E" and "%e" formats. */ 1601 #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX 1602 "%.16e", 1603 "%22.16e", 1604 "%022.16e", 1605 "%-22.16e", 1606 "%#+'022.16e", 1607 #endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */ 1608 "foo|%#+0123.9E|bar", 1609 "%-123.9e", 1610 "%123.9e", 1611 "%+23.9e", 1612 "%+05.8e", 1613 "%-05.8e", 1614 "%05.8e", 1615 "%+5.8e", 1616 "%-5.8e", 1617 "% 5.8e", 1618 "%5.8e", 1619 "%+4.9e", 1620 #if !OS_LINUX /* glibc sometimes gets these wrong. */ 1621 "%+#010.0e", 1622 "%#10.1e", 1623 "%10.5e", 1624 "% 10.5e", 1625 "%5.0e", 1626 "%5.e", 1627 "%#5.0e", 1628 "%#5.e", 1629 "%3.2e", 1630 "%3.1e", 1631 "%-1.5e", 1632 "%1.5e", 1633 "%01.3e", 1634 "%1.e", 1635 "%.1e", 1636 "%#.0e", 1637 "%+.0e", 1638 "% .0e", 1639 "%.0e", 1640 "%#.e", 1641 "%+.e", 1642 "% .e", 1643 "%.e", 1644 "%4e", 1645 "%e", 1646 "%E", 1647 #endif /* !OS_LINUX */ 1648 /* "%F" and "%f" formats. */ 1649 #if !OS_BSD && !OS_IRIX 1650 "% '022f", 1651 "%+'022f", 1652 "%-'22f", 1653 "%'22f", 1654 #if HAVE_LONG_LONG_INT 1655 "%.16f", 1656 "%22.16f", 1657 "%022.16f", 1658 "%-22.16f", 1659 "%#+'022.16f", 1660 #endif /* HAVE_LONG_LONG_INT */ 1661 #endif /* !OS_BSD && !OS_IRIX */ 1662 "foo|%#+0123.9F|bar", 1663 "%-123.9f", 1664 "%123.9f", 1665 "%+23.9f", 1666 "%+#010.0f", 1667 "%#10.1f", 1668 "%10.5f", 1669 "% 10.5f", 1670 "%+05.8f", 1671 "%-05.8f", 1672 "%05.8f", 1673 "%+5.8f", 1674 "%-5.8f", 1675 "% 5.8f", 1676 "%5.8f", 1677 "%5.0f", 1678 "%5.f", 1679 "%#5.0f", 1680 "%#5.f", 1681 "%+4.9f", 1682 "%3.2f", 1683 "%3.1f", 1684 "%-1.5f", 1685 "%1.5f", 1686 "%01.3f", 1687 "%1.f", 1688 "%.1f", 1689 "%#.0f", 1690 "%+.0f", 1691 "% .0f", 1692 "%.0f", 1693 "%#.f", 1694 "%+.f", 1695 "% .f", 1696 "%.f", 1697 "%4f", 1698 "%f", 1699 "%F", 1700 /* "%G" and "%g" formats. */ 1701 #if !OS_BSD && !OS_IRIX && !OS_LINUX 1702 "% '022g", 1703 "%+'022g", 1704 "%-'22g", 1705 "%'22g", 1706 #if HAVE_LONG_LONG_INT 1707 "%.16g", 1708 "%22.16g", 1709 "%022.16g", 1710 "%-22.16g", 1711 "%#+'022.16g", 1712 #endif /* HAVE_LONG_LONG_INT */ 1713 #endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */ 1714 "foo|%#+0123.9G|bar", 1715 "%-123.9g", 1716 "%123.9g", 1717 "%+23.9g", 1718 "%+05.8g", 1719 "%-05.8g", 1720 "%05.8g", 1721 "%+5.8g", 1722 "%-5.8g", 1723 "% 5.8g", 1724 "%5.8g", 1725 "%+4.9g", 1726 #if !OS_LINUX /* glibc sometimes gets these wrong. */ 1727 "%+#010.0g", 1728 "%#10.1g", 1729 "%10.5g", 1730 "% 10.5g", 1731 "%5.0g", 1732 "%5.g", 1733 "%#5.0g", 1734 "%#5.g", 1735 "%3.2g", 1736 "%3.1g", 1737 "%-1.5g", 1738 "%1.5g", 1739 "%01.3g", 1740 "%1.g", 1741 "%.1g", 1742 "%#.0g", 1743 "%+.0g", 1744 "% .0g", 1745 "%.0g", 1746 "%#.g", 1747 "%+.g", 1748 "% .g", 1749 "%.g", 1750 "%4g", 1751 "%g", 1752 "%G", 1753 #endif /* !OS_LINUX */ 1754 NULL 1755 }; 1756 double float_val[] = { 1757 -4.136, 1758 -134.52, 1759 -5.04030201, 1760 -3410.01234, 1761 -999999.999999, 1762 -913450.29876, 1763 -913450.2, 1764 -91345.2, 1765 -9134.2, 1766 -913.2, 1767 -91.2, 1768 -9.2, 1769 -9.9, 1770 4.136, 1771 134.52, 1772 5.04030201, 1773 3410.01234, 1774 999999.999999, 1775 913450.29876, 1776 913450.2, 1777 91345.2, 1778 9134.2, 1779 913.2, 1780 91.2, 1781 9.2, 1782 9.9, 1783 9.96, 1784 9.996, 1785 9.9996, 1786 9.99996, 1787 9.999996, 1788 9.9999996, 1789 9.99999996, 1790 0.99999996, 1791 0.99999999, 1792 0.09999999, 1793 0.00999999, 1794 0.00099999, 1795 0.00009999, 1796 0.00000999, 1797 0.00000099, 1798 0.00000009, 1799 0.00000001, 1800 0.0000001, 1801 0.000001, 1802 0.00001, 1803 0.0001, 1804 0.001, 1805 0.01, 1806 0.1, 1807 1.0, 1808 1.5, 1809 -1.5, 1810 -1.0, 1811 -0.1, 1812 #if !OS_BSD /* BSD sometimes gets these wrong. */ 1813 #ifdef INFINITY 1814 INFINITY, 1815 -INFINITY, 1816 #endif /* defined(INFINITY) */ 1817 #ifdef NAN 1818 NAN, 1819 #endif /* defined(NAN) */ 1820 #endif /* !OS_BSD */ 1821 0 1822 }; 1823 const char *long_fmt[] = { 1824 "foo|%0123ld|bar", 1825 #if !OS_IRIX 1826 "% '0123ld", 1827 "%+'0123ld", 1828 "%-'123ld", 1829 "%'123ld", 1830 #endif /* !OS_IRiX */ 1831 "%123.9ld", 1832 "% 123.9ld", 1833 "%+123.9ld", 1834 "%-123.9ld", 1835 "%0123ld", 1836 "% 0123ld", 1837 "%+0123ld", 1838 "%-0123ld", 1839 "%10.5ld", 1840 "% 10.5ld", 1841 "%+10.5ld", 1842 "%-10.5ld", 1843 "%010ld", 1844 "% 010ld", 1845 "%+010ld", 1846 "%-010ld", 1847 "%4.2ld", 1848 "% 4.2ld", 1849 "%+4.2ld", 1850 "%-4.2ld", 1851 "%04ld", 1852 "% 04ld", 1853 "%+04ld", 1854 "%-04ld", 1855 "%5.5ld", 1856 "%+22.33ld", 1857 "%01.3ld", 1858 "%1.5ld", 1859 "%-1.5ld", 1860 "%44ld", 1861 "%4ld", 1862 "%4.0ld", 1863 "%4.ld", 1864 "%.44ld", 1865 "%.4ld", 1866 "%.0ld", 1867 "%.ld", 1868 "%ld", 1869 NULL 1870 }; 1871 long int long_val[] = { 1872 #ifdef LONG_MAX 1873 LONG_MAX, 1874 #endif /* LONG_MAX */ 1875 #ifdef LONG_MIN 1876 LONG_MIN, 1877 #endif /* LONG_MIN */ 1878 -91340, 1879 91340, 1880 341, 1881 134, 1882 0203, 1883 -1, 1884 1, 1885 0 1886 }; 1887 const char *ulong_fmt[] = { 1888 /* "%u" formats. */ 1889 "foo|%0123lu|bar", 1890 #if !OS_IRIX 1891 "% '0123lu", 1892 "%+'0123lu", 1893 "%-'123lu", 1894 "%'123lu", 1895 #endif /* !OS_IRiX */ 1896 "%123.9lu", 1897 "% 123.9lu", 1898 "%+123.9lu", 1899 "%-123.9lu", 1900 "%0123lu", 1901 "% 0123lu", 1902 "%+0123lu", 1903 "%-0123lu", 1904 "%5.5lu", 1905 "%+22.33lu", 1906 "%01.3lu", 1907 "%1.5lu", 1908 "%-1.5lu", 1909 "%44lu", 1910 "%lu", 1911 /* "%o" formats. */ 1912 "foo|%#0123lo|bar", 1913 "%#123.9lo", 1914 "%# 123.9lo", 1915 "%#+123.9lo", 1916 "%#-123.9lo", 1917 "%#0123lo", 1918 "%# 0123lo", 1919 "%#+0123lo", 1920 "%#-0123lo", 1921 "%#5.5lo", 1922 "%#+22.33lo", 1923 "%#01.3lo", 1924 "%#1.5lo", 1925 "%#-1.5lo", 1926 "%#44lo", 1927 "%#lo", 1928 "%123.9lo", 1929 "% 123.9lo", 1930 "%+123.9lo", 1931 "%-123.9lo", 1932 "%0123lo", 1933 "% 0123lo", 1934 "%+0123lo", 1935 "%-0123lo", 1936 "%5.5lo", 1937 "%+22.33lo", 1938 "%01.3lo", 1939 "%1.5lo", 1940 "%-1.5lo", 1941 "%44lo", 1942 "%lo", 1943 /* "%X" and "%x" formats. */ 1944 "foo|%#0123lX|bar", 1945 "%#123.9lx", 1946 "%# 123.9lx", 1947 "%#+123.9lx", 1948 "%#-123.9lx", 1949 "%#0123lx", 1950 "%# 0123lx", 1951 "%#+0123lx", 1952 "%#-0123lx", 1953 "%#5.5lx", 1954 "%#+22.33lx", 1955 "%#01.3lx", 1956 "%#1.5lx", 1957 "%#-1.5lx", 1958 "%#44lx", 1959 "%#lx", 1960 "%#lX", 1961 "%123.9lx", 1962 "% 123.9lx", 1963 "%+123.9lx", 1964 "%-123.9lx", 1965 "%0123lx", 1966 "% 0123lx", 1967 "%+0123lx", 1968 "%-0123lx", 1969 "%5.5lx", 1970 "%+22.33lx", 1971 "%01.3lx", 1972 "%1.5lx", 1973 "%-1.5lx", 1974 "%44lx", 1975 "%lx", 1976 "%lX", 1977 NULL 1978 }; 1979 unsigned long int ulong_val[] = { 1980 #ifdef ULONG_MAX 1981 ULONG_MAX, 1982 #endif /* ULONG_MAX */ 1983 91340, 1984 341, 1985 134, 1986 0203, 1987 1, 1988 0 1989 }; 1990 const char *llong_fmt[] = { 1991 "foo|%0123lld|bar", 1992 "%123.9lld", 1993 "% 123.9lld", 1994 "%+123.9lld", 1995 "%-123.9lld", 1996 "%0123lld", 1997 "% 0123lld", 1998 "%+0123lld", 1999 "%-0123lld", 2000 "%5.5lld", 2001 "%+22.33lld", 2002 "%01.3lld", 2003 "%1.5lld", 2004 "%-1.5lld", 2005 "%44lld", 2006 "%lld", 2007 NULL 2008 }; 2009 LLONG llong_val[] = { 2010 #ifdef LLONG_MAX 2011 LLONG_MAX, 2012 #endif /* LLONG_MAX */ 2013 #ifdef LLONG_MIN 2014 LLONG_MIN, 2015 #endif /* LLONG_MIN */ 2016 -91340, 2017 91340, 2018 341, 2019 134, 2020 0203, 2021 -1, 2022 1, 2023 0 2024 }; 2025 const char *string_fmt[] = { 2026 "foo|%10.10s|bar", 2027 "%-10.10s", 2028 "%10.10s", 2029 "%10.5s", 2030 "%5.10s", 2031 "%10.1s", 2032 "%1.10s", 2033 "%10.0s", 2034 "%0.10s", 2035 "%-42.5s", 2036 "%2.s", 2037 "%.10s", 2038 "%.1s", 2039 "%.0s", 2040 "%.s", 2041 "%4s", 2042 "%s", 2043 NULL 2044 }; 2045 const char *string_val[] = { 2046 "Hello", 2047 "Hello, world!", 2048 "Sound check: One, two, three.", 2049 "This string is a little longer than the other strings.", 2050 "1", 2051 "", 2052 NULL 2053 }; 2054 #if !OS_SYSV /* SysV uses a different format than we do. */ 2055 const char *pointer_fmt[] = { 2056 "foo|%p|bar", 2057 "%42p", 2058 "%p", 2059 NULL 2060 }; 2061 const char *pointer_val[] = { 2062 *pointer_fmt, 2063 *string_fmt, 2064 *string_val, 2065 NULL 2066 }; 2067 #endif /* !OS_SYSV */ 2068 char buf1[1024], buf2[1024]; 2069 double value, digits = 9.123456789012345678901234567890123456789; 2070 int i, j, r1, r2, failed = 0, num = 0; 2071 2072 /* 2073 * Use -DTEST_NILS in order to also test the conversion of nil values. Might 2074 * segfault on systems which don't support converting a NULL pointer with "%s" 2075 * and lets some test cases fail against BSD and glibc due to bugs in their 2076 * implementations. 2077 */ 2078 #ifndef TEST_NILS 2079 #define TEST_NILS 0 2080 #elif TEST_NILS 2081 #undef TEST_NILS 2082 #define TEST_NILS 1 2083 #endif /* !defined(TEST_NILS) */ 2084 #ifdef TEST 2085 #undef TEST 2086 #endif /* defined(TEST) */ 2087 #define TEST(fmt, val) \ 2088 do { \ 2089 for (i = 0; fmt[i] != NULL; i++) \ 2090 for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \ 2091 r1 = sprintf(buf1, fmt[i], val[j]); \ 2092 r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \ 2093 if (strcmp(buf1, buf2) != 0 || r1 != r2) { \ 2094 (void)printf("Results don't match, " \ 2095 "format string: %s\n" \ 2096 "\t sprintf(3): [%s] (%d)\n" \ 2097 "\tsnprintf(3): [%s] (%d)\n", \ 2098 fmt[i], buf1, r1, buf2, r2); \ 2099 failed++; \ 2100 } \ 2101 num++; \ 2102 } \ 2103 } while (/* CONSTCOND */ 0) 2104 2105 #if HAVE_LOCALE_H 2106 (void)setlocale(LC_ALL, ""); 2107 #endif /* HAVE_LOCALE_H */ 2108 2109 (void)puts("Testing our snprintf(3) against your system's sprintf(3)."); 2110 TEST(float_fmt, float_val); 2111 TEST(long_fmt, long_val); 2112 TEST(ulong_fmt, ulong_val); 2113 TEST(llong_fmt, llong_val); 2114 TEST(string_fmt, string_val); 2115 #if !OS_SYSV /* SysV uses a different format than we do. */ 2116 TEST(pointer_fmt, pointer_val); 2117 #endif /* !OS_SYSV */ 2118 (void)printf("Result: %d out of %d tests failed.\n", failed, num); 2119 2120 (void)fputs("Checking how many digits we support: ", stdout); 2121 for (i = 0; i < 100; i++) { 2122 value = pow(10, i) * digits; 2123 (void)sprintf(buf1, "%.1f", value); 2124 (void)snprintf(buf2, sizeof(buf2), "%.1f", value); 2125 if (strcmp(buf1, buf2) != 0) { 2126 (void)printf("apparently %d.\n", i); 2127 break; 2128 } 2129 } 2130 return (failed == 0) ? 0 : 1; 2131 } 2132 #endif /* TEST_SNPRINTF */ 2133 2134 /* vim: set joinspaces textwidth=80: */ 2135