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