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