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