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