1 /* vsprintf with automatic memory allocation. 2 Copyright (C) 1999, 2002-2005 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with this program; if not, write to the Free Software Foundation, 16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 17 18 /* Tell glibc's <stdio.h> to provide a prototype for snprintf(). 19 This must come before <config.h> because <config.h> may include 20 <features.h>, and once <features.h> has been included, it's too late. */ 21 #ifndef _GNU_SOURCE 22 # define _GNU_SOURCE 1 23 #endif 24 25 #ifdef HAVE_CONFIG_H 26 # include <config.h> 27 #endif 28 #ifdef __SSP__ 29 #undef HAVE_ALLOCA 30 #endif 31 #ifndef __NetBSD__ 32 #ifndef IN_LIBINTL 33 # include <alloca.h> 34 #endif 35 #endif 36 37 /* Specification. */ 38 #if WIDE_CHAR_VERSION 39 # include "vasnwprintf.h" 40 #else 41 # include "vasnprintf.h" 42 #endif 43 44 #include <stdio.h> /* snprintf(), sprintf() */ 45 #include <stdlib.h> /* abort(), malloc(), realloc(), free() */ 46 #include <string.h> /* memcpy(), strlen() */ 47 #include <errno.h> /* errno */ 48 #include <limits.h> /* CHAR_BIT, INT_MAX */ 49 #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ 50 #if WIDE_CHAR_VERSION 51 # include "wprintf-parse.h" 52 #else 53 # include "printf-parse.h" 54 #endif 55 56 /* Checked size_t computations. */ 57 #include "xsize.h" 58 59 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ 60 #ifndef EOVERFLOW 61 # define EOVERFLOW E2BIG 62 #endif 63 64 #ifdef HAVE_WCHAR_T 65 # ifdef HAVE_WCSLEN 66 # define local_wcslen wcslen 67 # else 68 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid 69 a dependency towards this library, here is a local substitute. 70 Define this substitute only once, even if this file is included 71 twice in the same compilation unit. */ 72 # ifndef local_wcslen_defined 73 # define local_wcslen_defined 1 74 static size_t 75 local_wcslen (const wchar_t *s) 76 { 77 const wchar_t *ptr; 78 79 for (ptr = s; *ptr != (wchar_t) 0; ptr++) 80 ; 81 return ptr - s; 82 } 83 # endif 84 # endif 85 #endif 86 87 #if WIDE_CHAR_VERSION 88 # define VASNPRINTF vasnwprintf 89 # define CHAR_T wchar_t 90 # define DIRECTIVE wchar_t_directive 91 # define DIRECTIVES wchar_t_directives 92 # define PRINTF_PARSE wprintf_parse 93 # define USE_SNPRINTF 1 94 # if HAVE_DECL__SNWPRINTF 95 /* On Windows, the function swprintf() has a different signature than 96 on Unix; we use the _snwprintf() function instead. */ 97 # define SNPRINTF _snwprintf 98 # else 99 /* Unix. */ 100 # define SNPRINTF swprintf 101 # endif 102 #else 103 # define VASNPRINTF vasnprintf 104 # define CHAR_T char 105 # define DIRECTIVE char_directive 106 # define DIRECTIVES char_directives 107 # define PRINTF_PARSE printf_parse 108 # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) 109 # if HAVE_DECL__SNPRINTF 110 /* Windows. */ 111 # define SNPRINTF _snprintf 112 # else 113 /* Unix. */ 114 # define SNPRINTF snprintf 115 # endif 116 #endif 117 118 CHAR_T * 119 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) 120 { 121 DIRECTIVES d; 122 arguments a; 123 124 if (PRINTF_PARSE (format, &d, &a) < 0) 125 { 126 errno = EINVAL; 127 return NULL; 128 } 129 130 #define CLEANUP() \ 131 free (d.dir); \ 132 if (a.arg) \ 133 free (a.arg); 134 135 if (printf_fetchargs (args, &a) < 0) 136 { 137 CLEANUP (); 138 errno = EINVAL; 139 return NULL; 140 } 141 142 { 143 size_t buf_neededlength; 144 CHAR_T *buf; 145 CHAR_T *buf_malloced; 146 const CHAR_T *cp; 147 size_t i; 148 DIRECTIVE *dp; 149 /* Output string accumulator. */ 150 CHAR_T *result; 151 size_t allocated; 152 size_t length; 153 154 /* Allocate a small buffer that will hold a directive passed to 155 sprintf or snprintf. */ 156 buf_neededlength = 157 xsum4 (7, d.max_width_length, d.max_precision_length, 6); 158 #if HAVE_ALLOCA 159 if (buf_neededlength < 4000 / sizeof (CHAR_T)) 160 { 161 buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); 162 buf_malloced = NULL; 163 } 164 else 165 #endif 166 { 167 size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); 168 if (size_overflow_p (buf_memsize)) 169 goto out_of_memory_1; 170 buf = (CHAR_T *) malloc (buf_memsize); 171 if (buf == NULL) 172 goto out_of_memory_1; 173 buf_malloced = buf; 174 } 175 176 if (resultbuf != NULL) 177 { 178 result = resultbuf; 179 allocated = *lengthp; 180 } 181 else 182 { 183 result = NULL; 184 allocated = 0; 185 } 186 length = 0; 187 /* Invariants: 188 result is either == resultbuf or == NULL or malloc-allocated. 189 If length > 0, then result != NULL. */ 190 191 /* Ensures that allocated >= needed. Aborts through a jump to 192 out_of_memory if needed is SIZE_MAX or otherwise too big. */ 193 #define ENSURE_ALLOCATION(needed) \ 194 if ((needed) > allocated) \ 195 { \ 196 size_t memory_size; \ 197 CHAR_T *memory; \ 198 \ 199 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ 200 if ((needed) > allocated) \ 201 allocated = (needed); \ 202 memory_size = xtimes (allocated, sizeof (CHAR_T)); \ 203 if (size_overflow_p (memory_size)) \ 204 goto out_of_memory; \ 205 if (result == resultbuf || result == NULL) \ 206 memory = (CHAR_T *) malloc (memory_size); \ 207 else \ 208 memory = (CHAR_T *) realloc (result, memory_size); \ 209 if (memory == NULL) \ 210 goto out_of_memory; \ 211 if (result == resultbuf && length > 0) \ 212 memcpy (memory, result, length * sizeof (CHAR_T)); \ 213 result = memory; \ 214 } 215 216 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) 217 { 218 if (cp != dp->dir_start) 219 { 220 size_t n = dp->dir_start - cp; 221 size_t augmented_length = xsum (length, n); 222 223 ENSURE_ALLOCATION (augmented_length); 224 memcpy (result + length, cp, n * sizeof (CHAR_T)); 225 length = augmented_length; 226 } 227 if (i == d.count) 228 break; 229 230 /* Execute a single directive. */ 231 if (dp->conversion == '%') 232 { 233 size_t augmented_length; 234 235 if (!(dp->arg_index == ARG_NONE)) 236 abort (); 237 augmented_length = xsum (length, 1); 238 ENSURE_ALLOCATION (augmented_length); 239 result[length] = '%'; 240 length = augmented_length; 241 } 242 else 243 { 244 if (!(dp->arg_index != ARG_NONE)) 245 abort (); 246 247 if (dp->conversion == 'n') 248 { 249 switch (a.arg[dp->arg_index].type) 250 { 251 case TYPE_COUNT_SCHAR_POINTER: 252 *a.arg[dp->arg_index].a.a_count_schar_pointer = length; 253 break; 254 case TYPE_COUNT_SHORT_POINTER: 255 *a.arg[dp->arg_index].a.a_count_short_pointer = length; 256 break; 257 case TYPE_COUNT_INT_POINTER: 258 *a.arg[dp->arg_index].a.a_count_int_pointer = length; 259 break; 260 case TYPE_COUNT_LONGINT_POINTER: 261 *a.arg[dp->arg_index].a.a_count_longint_pointer = length; 262 break; 263 #ifdef HAVE_LONG_LONG 264 case TYPE_COUNT_LONGLONGINT_POINTER: 265 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; 266 break; 267 #endif 268 default: 269 abort (); 270 } 271 } 272 else 273 { 274 arg_type type = a.arg[dp->arg_index].type; 275 CHAR_T *p; 276 unsigned int prefix_count; 277 int prefixes[2]; 278 #if !USE_SNPRINTF 279 size_t tmp_length; 280 CHAR_T tmpbuf[700]; 281 CHAR_T *tmp; 282 283 /* Allocate a temporary buffer of sufficient size for calling 284 sprintf. */ 285 { 286 size_t width; 287 size_t precision; 288 289 width = 0; 290 if (dp->width_start != dp->width_end) 291 { 292 if (dp->width_arg_index != ARG_NONE) 293 { 294 int arg; 295 296 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 297 abort (); 298 arg = a.arg[dp->width_arg_index].a.a_int; 299 width = (arg < 0 ? (unsigned int) (-arg) : arg); 300 } 301 else 302 { 303 const CHAR_T *digitp = dp->width_start; 304 305 do 306 width = xsum (xtimes (width, 10), *digitp++ - '0'); 307 while (digitp != dp->width_end); 308 } 309 } 310 311 precision = 6; 312 if (dp->precision_start != dp->precision_end) 313 { 314 if (dp->precision_arg_index != ARG_NONE) 315 { 316 int arg; 317 318 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 319 abort (); 320 arg = a.arg[dp->precision_arg_index].a.a_int; 321 precision = (arg < 0 ? 0 : arg); 322 } 323 else 324 { 325 const CHAR_T *digitp = dp->precision_start + 1; 326 327 precision = 0; 328 while (digitp != dp->precision_end) 329 precision = xsum (xtimes (precision, 10), *digitp++ - '0'); 330 } 331 } 332 333 switch (dp->conversion) 334 { 335 336 case 'd': case 'i': case 'u': 337 # ifdef HAVE_LONG_LONG 338 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 339 tmp_length = 340 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 341 * 0.30103 /* binary -> decimal */ 342 * 2 /* estimate for FLAG_GROUP */ 343 ) 344 + 1 /* turn floor into ceil */ 345 + 1; /* account for leading sign */ 346 else 347 # endif 348 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 349 tmp_length = 350 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 351 * 0.30103 /* binary -> decimal */ 352 * 2 /* estimate for FLAG_GROUP */ 353 ) 354 + 1 /* turn floor into ceil */ 355 + 1; /* account for leading sign */ 356 else 357 tmp_length = 358 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 359 * 0.30103 /* binary -> decimal */ 360 * 2 /* estimate for FLAG_GROUP */ 361 ) 362 + 1 /* turn floor into ceil */ 363 + 1; /* account for leading sign */ 364 break; 365 366 case 'o': 367 # ifdef HAVE_LONG_LONG 368 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 369 tmp_length = 370 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 371 * 0.333334 /* binary -> octal */ 372 ) 373 + 1 /* turn floor into ceil */ 374 + 1; /* account for leading sign */ 375 else 376 # endif 377 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 378 tmp_length = 379 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 380 * 0.333334 /* binary -> octal */ 381 ) 382 + 1 /* turn floor into ceil */ 383 + 1; /* account for leading sign */ 384 else 385 tmp_length = 386 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 387 * 0.333334 /* binary -> octal */ 388 ) 389 + 1 /* turn floor into ceil */ 390 + 1; /* account for leading sign */ 391 break; 392 393 case 'x': case 'X': 394 # ifdef HAVE_LONG_LONG 395 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 396 tmp_length = 397 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 398 * 0.25 /* binary -> hexadecimal */ 399 ) 400 + 1 /* turn floor into ceil */ 401 + 2; /* account for leading sign or alternate form */ 402 else 403 # endif 404 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 405 tmp_length = 406 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 407 * 0.25 /* binary -> hexadecimal */ 408 ) 409 + 1 /* turn floor into ceil */ 410 + 2; /* account for leading sign or alternate form */ 411 else 412 tmp_length = 413 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 414 * 0.25 /* binary -> hexadecimal */ 415 ) 416 + 1 /* turn floor into ceil */ 417 + 2; /* account for leading sign or alternate form */ 418 break; 419 420 case 'f': case 'F': 421 # ifdef HAVE_LONG_DOUBLE 422 if (type == TYPE_LONGDOUBLE) 423 tmp_length = 424 (unsigned int) (LDBL_MAX_EXP 425 * 0.30103 /* binary -> decimal */ 426 * 2 /* estimate for FLAG_GROUP */ 427 ) 428 + 1 /* turn floor into ceil */ 429 + 10; /* sign, decimal point etc. */ 430 else 431 # endif 432 tmp_length = 433 (unsigned int) (DBL_MAX_EXP 434 * 0.30103 /* binary -> decimal */ 435 * 2 /* estimate for FLAG_GROUP */ 436 ) 437 + 1 /* turn floor into ceil */ 438 + 10; /* sign, decimal point etc. */ 439 tmp_length = xsum (tmp_length, precision); 440 break; 441 442 case 'e': case 'E': case 'g': case 'G': 443 case 'a': case 'A': 444 tmp_length = 445 12; /* sign, decimal point, exponent etc. */ 446 tmp_length = xsum (tmp_length, precision); 447 break; 448 449 case 'c': 450 # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION 451 if (type == TYPE_WIDE_CHAR) 452 tmp_length = MB_CUR_MAX; 453 else 454 # endif 455 tmp_length = 1; 456 break; 457 458 case 's': 459 # ifdef HAVE_WCHAR_T 460 if (type == TYPE_WIDE_STRING) 461 { 462 tmp_length = 463 local_wcslen (a.arg[dp->arg_index].a.a_wide_string); 464 465 # if !WIDE_CHAR_VERSION 466 tmp_length = xtimes (tmp_length, MB_CUR_MAX); 467 # endif 468 } 469 else 470 # endif 471 tmp_length = strlen (a.arg[dp->arg_index].a.a_string); 472 break; 473 474 case 'p': 475 tmp_length = 476 (unsigned int) (sizeof (void *) * CHAR_BIT 477 * 0.25 /* binary -> hexadecimal */ 478 ) 479 + 1 /* turn floor into ceil */ 480 + 2; /* account for leading 0x */ 481 break; 482 483 default: 484 abort (); 485 } 486 487 if (tmp_length < width) 488 tmp_length = width; 489 490 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ 491 } 492 493 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) 494 tmp = tmpbuf; 495 else 496 { 497 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); 498 499 if (size_overflow_p (tmp_memsize)) 500 /* Overflow, would lead to out of memory. */ 501 goto out_of_memory; 502 tmp = (CHAR_T *) malloc (tmp_memsize); 503 if (tmp == NULL) 504 /* Out of memory. */ 505 goto out_of_memory; 506 } 507 #endif 508 509 /* Construct the format string for calling snprintf or 510 sprintf. */ 511 p = buf; 512 *p++ = '%'; 513 if (dp->flags & FLAG_GROUP) 514 *p++ = '\''; 515 if (dp->flags & FLAG_LEFT) 516 *p++ = '-'; 517 if (dp->flags & FLAG_SHOWSIGN) 518 *p++ = '+'; 519 if (dp->flags & FLAG_SPACE) 520 *p++ = ' '; 521 if (dp->flags & FLAG_ALT) 522 *p++ = '#'; 523 if (dp->flags & FLAG_ZERO) 524 *p++ = '0'; 525 if (dp->width_start != dp->width_end) 526 { 527 size_t n = dp->width_end - dp->width_start; 528 memcpy (p, dp->width_start, n * sizeof (CHAR_T)); 529 p += n; 530 } 531 if (dp->precision_start != dp->precision_end) 532 { 533 size_t n = dp->precision_end - dp->precision_start; 534 memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); 535 p += n; 536 } 537 538 switch (type) 539 { 540 #ifdef HAVE_LONG_LONG 541 case TYPE_LONGLONGINT: 542 case TYPE_ULONGLONGINT: 543 *p++ = 'l'; 544 /*FALLTHROUGH*/ 545 #endif 546 case TYPE_LONGINT: 547 case TYPE_ULONGINT: 548 #ifdef HAVE_WINT_T 549 case TYPE_WIDE_CHAR: 550 #endif 551 #ifdef HAVE_WCHAR_T 552 case TYPE_WIDE_STRING: 553 #endif 554 *p++ = 'l'; 555 break; 556 #ifdef HAVE_LONG_DOUBLE 557 case TYPE_LONGDOUBLE: 558 *p++ = 'L'; 559 break; 560 #endif 561 default: 562 break; 563 } 564 *p = dp->conversion; 565 #if USE_SNPRINTF 566 p[1] = '%'; 567 p[2] = 'n'; 568 p[3] = '\0'; 569 #else 570 p[1] = '\0'; 571 #endif 572 573 /* Construct the arguments for calling snprintf or sprintf. */ 574 prefix_count = 0; 575 if (dp->width_arg_index != ARG_NONE) 576 { 577 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 578 abort (); 579 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; 580 } 581 if (dp->precision_arg_index != ARG_NONE) 582 { 583 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 584 abort (); 585 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; 586 } 587 588 #if USE_SNPRINTF 589 /* Prepare checking whether snprintf returns the count 590 via %n. */ 591 ENSURE_ALLOCATION (xsum (length, 1)); 592 result[length] = '\0'; 593 #endif 594 595 for (;;) 596 { 597 size_t maxlen; 598 int count; 599 int retcount; 600 601 maxlen = allocated - length; 602 count = -1; 603 retcount = 0; 604 605 #if USE_SNPRINTF 606 # define SNPRINTF_BUF(arg) \ 607 switch (prefix_count) \ 608 { \ 609 case 0: \ 610 retcount = SNPRINTF (result + length, maxlen, buf, \ 611 arg, &count); \ 612 break; \ 613 case 1: \ 614 retcount = SNPRINTF (result + length, maxlen, buf, \ 615 prefixes[0], arg, &count); \ 616 break; \ 617 case 2: \ 618 retcount = SNPRINTF (result + length, maxlen, buf, \ 619 prefixes[0], prefixes[1], arg, \ 620 &count); \ 621 break; \ 622 default: \ 623 abort (); \ 624 } 625 #else 626 # define SNPRINTF_BUF(arg) \ 627 switch (prefix_count) \ 628 { \ 629 case 0: \ 630 count = sprintf (tmp, buf, arg); \ 631 break; \ 632 case 1: \ 633 count = sprintf (tmp, buf, prefixes[0], arg); \ 634 break; \ 635 case 2: \ 636 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ 637 arg); \ 638 break; \ 639 default: \ 640 abort (); \ 641 } 642 #endif 643 644 switch (type) 645 { 646 case TYPE_SCHAR: 647 { 648 int arg = a.arg[dp->arg_index].a.a_schar; 649 SNPRINTF_BUF (arg); 650 } 651 break; 652 case TYPE_UCHAR: 653 { 654 unsigned int arg = a.arg[dp->arg_index].a.a_uchar; 655 SNPRINTF_BUF (arg); 656 } 657 break; 658 case TYPE_SHORT: 659 { 660 int arg = a.arg[dp->arg_index].a.a_short; 661 SNPRINTF_BUF (arg); 662 } 663 break; 664 case TYPE_USHORT: 665 { 666 unsigned int arg = a.arg[dp->arg_index].a.a_ushort; 667 SNPRINTF_BUF (arg); 668 } 669 break; 670 case TYPE_INT: 671 { 672 int arg = a.arg[dp->arg_index].a.a_int; 673 SNPRINTF_BUF (arg); 674 } 675 break; 676 case TYPE_UINT: 677 { 678 unsigned int arg = a.arg[dp->arg_index].a.a_uint; 679 SNPRINTF_BUF (arg); 680 } 681 break; 682 case TYPE_LONGINT: 683 { 684 long int arg = a.arg[dp->arg_index].a.a_longint; 685 SNPRINTF_BUF (arg); 686 } 687 break; 688 case TYPE_ULONGINT: 689 { 690 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; 691 SNPRINTF_BUF (arg); 692 } 693 break; 694 #ifdef HAVE_LONG_LONG 695 case TYPE_LONGLONGINT: 696 { 697 long long int arg = a.arg[dp->arg_index].a.a_longlongint; 698 SNPRINTF_BUF (arg); 699 } 700 break; 701 case TYPE_ULONGLONGINT: 702 { 703 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; 704 SNPRINTF_BUF (arg); 705 } 706 break; 707 #endif 708 case TYPE_DOUBLE: 709 { 710 double arg = a.arg[dp->arg_index].a.a_double; 711 SNPRINTF_BUF (arg); 712 } 713 break; 714 #ifdef HAVE_LONG_DOUBLE 715 case TYPE_LONGDOUBLE: 716 { 717 long double arg = a.arg[dp->arg_index].a.a_longdouble; 718 SNPRINTF_BUF (arg); 719 } 720 break; 721 #endif 722 case TYPE_CHAR: 723 { 724 int arg = a.arg[dp->arg_index].a.a_char; 725 SNPRINTF_BUF (arg); 726 } 727 break; 728 #ifdef HAVE_WINT_T 729 case TYPE_WIDE_CHAR: 730 { 731 wint_t arg = a.arg[dp->arg_index].a.a_wide_char; 732 SNPRINTF_BUF (arg); 733 } 734 break; 735 #endif 736 case TYPE_STRING: 737 { 738 const char *arg = a.arg[dp->arg_index].a.a_string; 739 SNPRINTF_BUF (arg); 740 } 741 break; 742 #ifdef HAVE_WCHAR_T 743 case TYPE_WIDE_STRING: 744 { 745 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; 746 SNPRINTF_BUF (arg); 747 } 748 break; 749 #endif 750 case TYPE_POINTER: 751 { 752 void *arg = a.arg[dp->arg_index].a.a_pointer; 753 SNPRINTF_BUF (arg); 754 } 755 break; 756 default: 757 abort (); 758 } 759 760 #if USE_SNPRINTF 761 /* Portability: Not all implementations of snprintf() 762 are ISO C 99 compliant. Determine the number of 763 bytes that snprintf() has produced or would have 764 produced. */ 765 if (count >= 0) 766 { 767 /* Verify that snprintf() has NUL-terminated its 768 result. */ 769 if (count < maxlen && result[length + count] != '\0') 770 abort (); 771 /* Portability hack. */ 772 if (retcount > count) 773 count = retcount; 774 } 775 else 776 { 777 /* snprintf() doesn't understand the '%n' 778 directive. */ 779 if (p[1] != '\0') 780 { 781 /* Don't use the '%n' directive; instead, look 782 at the snprintf() return value. */ 783 p[1] = '\0'; 784 continue; 785 } 786 else 787 { 788 /* Look at the snprintf() return value. */ 789 if (retcount < 0) 790 { 791 /* HP-UX 10.20 snprintf() is doubly deficient: 792 It doesn't understand the '%n' directive, 793 *and* it returns -1 (rather than the length 794 that would have been required) when the 795 buffer is too small. */ 796 size_t bigger_need = 797 xsum (xtimes (allocated, 2), 12); 798 ENSURE_ALLOCATION (bigger_need); 799 continue; 800 } 801 else 802 count = retcount; 803 } 804 } 805 #endif 806 807 /* Attempt to handle failure. */ 808 if (count < 0) 809 { 810 if (!(result == resultbuf || result == NULL)) 811 free (result); 812 if (buf_malloced != NULL) 813 free (buf_malloced); 814 CLEANUP (); 815 errno = EINVAL; 816 return NULL; 817 } 818 819 #if !USE_SNPRINTF 820 if (count >= tmp_length) 821 /* tmp_length was incorrectly calculated - fix the 822 code above! */ 823 abort (); 824 #endif 825 826 /* Make room for the result. */ 827 if (count >= maxlen) 828 { 829 /* Need at least count bytes. But allocate 830 proportionally, to avoid looping eternally if 831 snprintf() reports a too small count. */ 832 size_t n = 833 xmax (xsum (length, count), xtimes (allocated, 2)); 834 835 ENSURE_ALLOCATION (n); 836 #if USE_SNPRINTF 837 continue; 838 #endif 839 } 840 841 #if USE_SNPRINTF 842 /* The snprintf() result did fit. */ 843 #else 844 /* Append the sprintf() result. */ 845 memcpy (result + length, tmp, count * sizeof (CHAR_T)); 846 if (tmp != tmpbuf) 847 free (tmp); 848 #endif 849 850 length += count; 851 break; 852 } 853 } 854 } 855 } 856 857 /* Add the final NUL. */ 858 ENSURE_ALLOCATION (xsum (length, 1)); 859 result[length] = '\0'; 860 861 if (result != resultbuf && length + 1 < allocated) 862 { 863 /* Shrink the allocated memory if possible. */ 864 CHAR_T *memory; 865 866 memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); 867 if (memory != NULL) 868 result = memory; 869 } 870 871 if (buf_malloced != NULL) 872 free (buf_malloced); 873 CLEANUP (); 874 *lengthp = length; 875 if (length > INT_MAX) 876 goto length_overflow; 877 return result; 878 879 length_overflow: 880 /* We could produce such a big string, but its length doesn't fit into 881 an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in 882 this case. */ 883 if (result != resultbuf) 884 free (result); 885 errno = EOVERFLOW; 886 return NULL; 887 888 out_of_memory: 889 if (!(result == resultbuf || result == NULL)) 890 free (result); 891 if (buf_malloced != NULL) 892 free (buf_malloced); 893 out_of_memory_1: 894 CLEANUP (); 895 errno = ENOMEM; 896 return NULL; 897 } 898 } 899 900 #undef SNPRINTF 901 #undef USE_SNPRINTF 902 #undef PRINTF_PARSE 903 #undef DIRECTIVES 904 #undef DIRECTIVE 905 #undef CHAR_T 906 #undef VASNPRINTF 907