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#ifndef _WIN32 20/* Tell glibc's <stdio.h> to provide a prototype for snprintf(). 21 This must come before <config.h> because <config.h> may include 22 <features.h>, and once <features.h> has been included, it's too late. */ 23#ifndef _GNU_SOURCE 24# define _GNU_SOURCE 1 25#endif 26#endif 27 28#ifdef HAVE_CONFIG_H 29# include <config.h> 30#endif 31#include "glib/galloca.h" 32 33#include "g-gnulib.h" 34 35/* Specification. */ 36#include "vasnprintf.h" 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#include "printf-parse.h" 45 46#ifdef HAVE_WCHAR_T 47# ifdef HAVE_WCSLEN 48# define local_wcslen wcslen 49# else 50 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid 51 a dependency towards this library, here is a local substitute. 52 Define this substitute only once, even if this file is included 53 twice in the same compilation unit. */ 54# ifndef local_wcslen_defined 55# define local_wcslen_defined 1 56static size_t 57local_wcslen (const wchar_t *s) 58{ 59 const wchar_t *ptr; 60 61 for (ptr = s; *ptr != (wchar_t) 0; ptr++) 62 ; 63 return ptr - s; 64} 65# endif 66# endif 67#endif 68 69/* For those losing systems which don't have 'alloca' we have to add 70 some additional code emulating it. */ 71#ifdef HAVE_ALLOCA 72# define freea(p) /* nothing */ 73#else 74# define alloca(n) malloc (n) 75# define freea(p) free (p) 76#endif 77 78#ifndef HAVE_LONG_LONG_FORMAT 79static int 80print_long_long (char *buf, 81 int len, 82 int width, 83 int precision, 84 unsigned long flags, 85 char conversion, 86 unsigned long long number) 87{ 88 int negative = FALSE; 89 char buffer[128]; 90 char *bufferend; 91 char *pointer; 92 int base; 93 static const char *upper = "0123456789ABCDEFX"; 94 static const char *lower = "0123456789abcdefx"; 95 const char *digits; 96 int i; 97 char *p; 98 int count; 99 100#define EMIT(c) \ 101 if (p - buf == len - 1) \ 102 { \ 103 *p++ = '\0'; \ 104 return len; \ 105 } \ 106 else \ 107 *p++ = c; 108 109 p = buf; 110 111 switch (conversion) 112 { 113 case 'o': 114 base = 8; 115 digits = lower; 116 negative = FALSE; 117 break; 118 case 'x': 119 base = 16; 120 digits = lower; 121 negative = FALSE; 122 break; 123 case 'X': 124 base = 16; 125 digits = upper; 126 negative = FALSE; 127 break; 128 default: 129 base = 10; 130 digits = lower; 131 negative = (long long)number < 0; 132 if (negative) 133 number = -((long long)number); 134 break; 135 } 136 137 /* Build number */ 138 pointer = bufferend = &buffer[sizeof(buffer) - 1]; 139 *pointer-- = '\0'; 140 for (i = 1; i < (int)sizeof(buffer); i++) 141 { 142 *pointer-- = digits[number % base]; 143 number /= base; 144 if (number == 0) 145 break; 146 } 147 148 /* Adjust width */ 149 width -= (bufferend - pointer) - 1; 150 151 /* Adjust precision */ 152 if (precision != -1) 153 { 154 precision -= (bufferend - pointer) - 1; 155 if (precision < 0) 156 precision = 0; 157 flags |= FLAG_ZERO; 158 } 159 160 /* Adjust width further */ 161 if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE)) 162 width--; 163 if (flags & FLAG_ALT) 164 { 165 switch (base) 166 { 167 case 16: 168 width -= 2; 169 break; 170 case 8: 171 width--; 172 break; 173 default: 174 break; 175 } 176 } 177 178 /* Output prefixes spaces if needed */ 179 if (! ((flags & FLAG_LEFT) || 180 ((flags & FLAG_ZERO) && (precision == -1)))) 181 { 182 count = (precision == -1) ? 0 : precision; 183 while (width-- > count) 184 *p++ = ' '; 185 } 186 187 /* width has been adjusted for signs and alternatives */ 188 if (negative) 189 { 190 EMIT ('-'); 191 } 192 else if (flags & FLAG_SHOWSIGN) 193 { 194 EMIT('+'); 195 } 196 else if (flags & FLAG_SPACE) 197 { 198 EMIT(' '); 199 } 200 201 if (flags & FLAG_ALT) 202 { 203 switch (base) 204 { 205 case 8: 206 EMIT('0'); 207 break; 208 case 16: 209 EMIT('0'); 210 EMIT(digits[16]); 211 break; 212 default: 213 break; 214 } /* switch base */ 215 } 216 217 /* Output prefixed zero padding if needed */ 218 if (flags & FLAG_ZERO) 219 { 220 if (precision == -1) 221 precision = width; 222 while (precision-- > 0) 223 { 224 EMIT('0'); 225 width--; 226 } 227 } 228 229 /* Output the number itself */ 230 while (*(++pointer)) 231 { 232 EMIT(*pointer); 233 } 234 235 /* Output trailing spaces if needed */ 236 if (flags & FLAG_LEFT) 237 { 238 while (width-- > 0) 239 EMIT(' '); 240 } 241 242 EMIT('\0'); 243 244 return p - buf - 1; 245} 246#endif 247 248char * 249vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) 250{ 251 char_directives d; 252 arguments a; 253 254 if (printf_parse (format, &d, &a) < 0) 255 { 256 errno = EINVAL; 257 return NULL; 258 } 259 260#define CLEANUP() \ 261 free (d.dir); \ 262 if (a.arg) \ 263 free (a.arg); 264 265 if (printf_fetchargs (args, &a) < 0) 266 { 267 CLEANUP (); 268 errno = EINVAL; 269 return NULL; 270 } 271 272 { 273 char *buf = 274 (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6); 275 const char *cp; 276 unsigned int i; 277 char_directive *dp; 278 /* Output string accumulator. */ 279 char *result; 280 size_t allocated; 281 size_t length; 282 283 if (resultbuf != NULL) 284 { 285 result = resultbuf; 286 allocated = *lengthp; 287 } 288 else 289 { 290 result = NULL; 291 allocated = 0; 292 } 293 length = 0; 294 /* Invariants: 295 result is either == resultbuf or == NULL or malloc-allocated. 296 If length > 0, then result != NULL. */ 297 298#define ENSURE_ALLOCATION(needed) \ 299 if ((needed) > allocated) \ 300 { \ 301 char *memory; \ 302 \ 303 allocated = (allocated > 0 ? 2 * allocated : 12); \ 304 if ((needed) > allocated) \ 305 allocated = (needed); \ 306 if (result == resultbuf || result == NULL) \ 307 memory = (char *) malloc (allocated); \ 308 else \ 309 memory = (char *) realloc (result, allocated); \ 310 \ 311 if (memory == NULL) \ 312 { \ 313 if (!(result == resultbuf || result == NULL)) \ 314 free (result); \ 315 freea (buf); \ 316 CLEANUP (); \ 317 errno = ENOMEM; \ 318 return NULL; \ 319 } \ 320 if (result == resultbuf && length > 0) \ 321 memcpy (memory, result, length); \ 322 result = memory; \ 323 } 324 325 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) 326 { 327 if (cp != dp->dir_start) 328 { 329 size_t n = dp->dir_start - cp; 330 331 ENSURE_ALLOCATION (length + n); 332 memcpy (result + length, cp, n); 333 length += n; 334 } 335 if (i == d.count) 336 break; 337 338 /* Execute a single directive. */ 339 if (dp->conversion == '%') 340 { 341 if (!(dp->arg_index < 0)) 342 abort (); 343 ENSURE_ALLOCATION (length + 1); 344 result[length] = '%'; 345 length += 1; 346 } 347 else 348 { 349 if (!(dp->arg_index >= 0)) 350 abort (); 351 352 if (dp->conversion == 'n') 353 { 354 switch (a.arg[dp->arg_index].type) 355 { 356 case TYPE_COUNT_SCHAR_POINTER: 357 *a.arg[dp->arg_index].a.a_count_schar_pointer = length; 358 break; 359 case TYPE_COUNT_SHORT_POINTER: 360 *a.arg[dp->arg_index].a.a_count_short_pointer = length; 361 break; 362 case TYPE_COUNT_INT_POINTER: 363 *a.arg[dp->arg_index].a.a_count_int_pointer = length; 364 break; 365 case TYPE_COUNT_LONGINT_POINTER: 366 *a.arg[dp->arg_index].a.a_count_longint_pointer = length; 367 break; 368#ifdef HAVE_LONG_LONG 369 case TYPE_COUNT_LONGLONGINT_POINTER: 370 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; 371 break; 372#endif 373 default: 374 abort (); 375 } 376 } 377 else 378 { 379 arg_type type = a.arg[dp->arg_index].type; 380 char *p; 381 unsigned int prefix_count; 382 int prefixes[2]; 383#if !HAVE_SNPRINTF 384 unsigned int tmp_length; 385 char tmpbuf[700]; 386 char *tmp; 387 388 /* Allocate a temporary buffer of sufficient size for calling 389 sprintf. */ 390 { 391 unsigned int width; 392 unsigned int precision; 393 394 width = 0; 395 if (dp->width_start != dp->width_end) 396 { 397 if (dp->width_arg_index >= 0) 398 { 399 int arg; 400 401 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 402 abort (); 403 arg = a.arg[dp->width_arg_index].a.a_int; 404 width = (arg < 0 ? -arg : arg); 405 } 406 else 407 { 408 const char *digitp = dp->width_start; 409 410 do 411 width = width * 10 + (*digitp++ - '0'); 412 while (digitp != dp->width_end); 413 } 414 } 415 416 precision = 6; 417 if (dp->precision_start != dp->precision_end) 418 { 419 if (dp->precision_arg_index >= 0) 420 { 421 int arg; 422 423 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 424 abort (); 425 arg = a.arg[dp->precision_arg_index].a.a_int; 426 precision = (arg < 0 ? 0 : arg); 427 } 428 else 429 { 430 const char *digitp = dp->precision_start + 1; 431 432 precision = 0; 433 while (digitp != dp->precision_end) 434 precision = precision * 10 + (*digitp++ - '0'); 435 } 436 } 437 438 switch (dp->conversion) 439 { 440 case 'd': case 'i': case 'u': 441# ifdef HAVE_LONG_LONG 442 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 443 tmp_length = 444 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 445 * 0.30103 /* binary -> decimal */ 446 * 2 /* estimate for FLAG_GROUP */ 447 ) 448 + 1 /* turn floor into ceil */ 449 + 1; /* account for leading sign */ 450 else 451# endif 452 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 453 tmp_length = 454 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 455 * 0.30103 /* binary -> decimal */ 456 * 2 /* estimate for FLAG_GROUP */ 457 ) 458 + 1 /* turn floor into ceil */ 459 + 1; /* account for leading sign */ 460 else 461 tmp_length = 462 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 463 * 0.30103 /* binary -> decimal */ 464 * 2 /* estimate for FLAG_GROUP */ 465 ) 466 + 1 /* turn floor into ceil */ 467 + 1; /* account for leading sign */ 468 break; 469 470 case 'o': 471# ifdef HAVE_LONG_LONG 472 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 473 tmp_length = 474 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 475 * 0.333334 /* binary -> octal */ 476 ) 477 + 1 /* turn floor into ceil */ 478 + 1; /* account for leading sign */ 479 else 480# endif 481 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 482 tmp_length = 483 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 484 * 0.333334 /* binary -> octal */ 485 ) 486 + 1 /* turn floor into ceil */ 487 + 1; /* account for leading sign */ 488 else 489 tmp_length = 490 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 491 * 0.333334 /* binary -> octal */ 492 ) 493 + 1 /* turn floor into ceil */ 494 + 1; /* account for leading sign */ 495 break; 496 497 case 'x': case 'X': 498# ifdef HAVE_LONG_LONG 499 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 500 tmp_length = 501 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 502 * 0.25 /* binary -> hexadecimal */ 503 ) 504 + 1 /* turn floor into ceil */ 505 + 2; /* account for leading sign or alternate form */ 506 else 507# endif 508# ifdef HAVE_INT64_AND_I64 509 if (type == TYPE_INT64 || type == TYPE_UINT64) 510 tmp_length = 511 (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT 512 * 0.25 /* binary -> hexadecimal */ 513 ) 514 + 1 /* turn floor into ceil */ 515 + 2; /* account for leading sign or alternate form */ 516 else 517# endif 518 if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 519 tmp_length = 520 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 521 * 0.25 /* binary -> hexadecimal */ 522 ) 523 + 1 /* turn floor into ceil */ 524 + 2; /* account for leading sign or alternate form */ 525 else 526 tmp_length = 527 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 528 * 0.25 /* binary -> hexadecimal */ 529 ) 530 + 1 /* turn floor into ceil */ 531 + 2; /* account for leading sign or alternate form */ 532 break; 533 534 case 'f': case 'F': 535# ifdef HAVE_LONG_DOUBLE 536 if (type == TYPE_LONGDOUBLE) 537 tmp_length = 538 (unsigned int) (LDBL_MAX_EXP 539 * 0.30103 /* binary -> decimal */ 540 * 2 /* estimate for FLAG_GROUP */ 541 ) 542 + 1 /* turn floor into ceil */ 543 + precision 544 + 10; /* sign, decimal point etc. */ 545 else 546# endif 547 tmp_length = 548 (unsigned int) (DBL_MAX_EXP 549 * 0.30103 /* binary -> decimal */ 550 * 2 /* estimate for FLAG_GROUP */ 551 ) 552 + 1 /* turn floor into ceil */ 553 + precision 554 + 10; /* sign, decimal point etc. */ 555 break; 556 557 case 'e': case 'E': case 'g': case 'G': 558 case 'a': case 'A': 559 tmp_length = 560 precision 561 + 12; /* sign, decimal point, exponent etc. */ 562 break; 563 564 case 'c': 565# ifdef HAVE_WINT_T 566 if (type == TYPE_WIDE_CHAR) 567 tmp_length = MB_CUR_MAX; 568 else 569# endif 570 tmp_length = 1; 571 break; 572 573 case 's': 574# ifdef HAVE_WCHAR_T 575 if (type == TYPE_WIDE_STRING) 576 tmp_length = 577 (a.arg[dp->arg_index].a.a_wide_string == NULL 578 ? 6 /* wcslen(L"(null)") */ 579 : local_wcslen (a.arg[dp->arg_index].a.a_wide_string)) 580 * MB_CUR_MAX; 581 else 582# endif 583 tmp_length = a.arg[dp->arg_index].a.a_string == NULL 584 ? 6 /* strlen("(null)") */ 585 : strlen (a.arg[dp->arg_index].a.a_string); 586 break; 587 588 case 'p': 589 tmp_length = 590 (unsigned int) (sizeof (void *) * CHAR_BIT 591 * 0.25 /* binary -> hexadecimal */ 592 ) 593 + 1 /* turn floor into ceil */ 594 + 2; /* account for leading 0x */ 595 break; 596 597 default: 598 abort (); 599 } 600 601 if (tmp_length < width) 602 tmp_length = width; 603 604 tmp_length++; /* account for trailing NUL */ 605 } 606 607 if (tmp_length <= sizeof (tmpbuf)) 608 tmp = tmpbuf; 609 else 610 { 611 tmp = (char *) malloc (tmp_length); 612 if (tmp == NULL) 613 { 614 /* Out of memory. */ 615 if (!(result == resultbuf || result == NULL)) 616 free (result); 617 freea (buf); 618 CLEANUP (); 619 errno = ENOMEM; 620 return NULL; 621 } 622 } 623#endif 624 625 /* Construct the format string for calling snprintf or 626 sprintf. */ 627 p = buf; 628 *p++ = '%'; 629 if (dp->flags & FLAG_GROUP) 630 *p++ = '\''; 631 if (dp->flags & FLAG_LEFT) 632 *p++ = '-'; 633 if (dp->flags & FLAG_SHOWSIGN) 634 *p++ = '+'; 635 if (dp->flags & FLAG_SPACE) 636 *p++ = ' '; 637 if (dp->flags & FLAG_ALT) 638 *p++ = '#'; 639 if (dp->flags & FLAG_ZERO) 640 *p++ = '0'; 641 if (dp->width_start != dp->width_end) 642 { 643 size_t n = dp->width_end - dp->width_start; 644 memcpy (p, dp->width_start, n); 645 p += n; 646 } 647 if (dp->precision_start != dp->precision_end) 648 { 649 size_t n = dp->precision_end - dp->precision_start; 650 memcpy (p, dp->precision_start, n); 651 p += n; 652 } 653 654 switch (type) 655 { 656#ifdef HAVE_INT64_AND_I64 657 case TYPE_INT64: 658 case TYPE_UINT64: 659 *p++ = 'I'; 660 *p++ = '6'; 661 *p++ = '4'; 662 break; 663#endif 664#ifdef HAVE_LONG_LONG 665 case TYPE_LONGLONGINT: 666 case TYPE_ULONGLONGINT: 667#ifdef HAVE_INT64_AND_I64 /* The system (sn)printf uses %I64. Also assume 668 * that long long == __int64. 669 */ 670 *p++ = 'I'; 671 *p++ = '6'; 672 *p++ = '4'; 673 break; 674#else 675 *p++ = 'l'; 676 /*FALLTHROUGH*/ 677#endif 678#endif 679 case TYPE_LONGINT: 680 case TYPE_ULONGINT: 681#ifdef HAVE_WINT_T 682 case TYPE_WIDE_CHAR: 683#endif 684#ifdef HAVE_WCHAR_T 685 case TYPE_WIDE_STRING: 686#endif 687 *p++ = 'l'; 688 break; 689#ifdef HAVE_LONG_DOUBLE 690 case TYPE_LONGDOUBLE: 691 *p++ = 'L'; 692 break; 693#endif 694 default: 695 break; 696 } 697 *p = dp->conversion; 698#if HAVE_SNPRINTF 699 p[1] = '%'; 700 p[2] = 'n'; 701 p[3] = '\0'; 702#else 703 p[1] = '\0'; 704#endif 705 706 /* Construct the arguments for calling snprintf or sprintf. */ 707 prefix_count = 0; 708 if (dp->width_arg_index >= 0) 709 { 710 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 711 abort (); 712 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; 713 } 714 if (dp->precision_arg_index >= 0) 715 { 716 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 717 abort (); 718 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; 719 } 720 721#if HAVE_SNPRINTF 722 /* Prepare checking whether snprintf returns the count 723 via %n. */ 724 ENSURE_ALLOCATION (length + 1); 725 result[length] = '\0'; 726#endif 727 728 for (;;) 729 { 730 size_t maxlen; 731 int count; 732 int retcount; 733 734 maxlen = allocated - length; 735 count = -1; 736 retcount = 0; 737 738#if HAVE_SNPRINTF 739#define SNPRINTF_BUF(arg) \ 740 switch (prefix_count) \ 741 { \ 742 case 0: \ 743 retcount = snprintf (result + length, maxlen, buf, \ 744 arg, &count); \ 745 break; \ 746 case 1: \ 747 retcount = snprintf (result + length, maxlen, buf, \ 748 prefixes[0], arg, &count); \ 749 break; \ 750 case 2: \ 751 retcount = snprintf (result + length, maxlen, buf, \ 752 prefixes[0], prefixes[1], arg, \ 753 &count); \ 754 break; \ 755 default: \ 756 abort (); \ 757 } 758#else 759#define SNPRINTF_BUF(arg) \ 760 switch (prefix_count) \ 761 { \ 762 case 0: \ 763 count = sprintf (tmp, buf, arg); \ 764 break; \ 765 case 1: \ 766 count = sprintf (tmp, buf, prefixes[0], arg); \ 767 break; \ 768 case 2: \ 769 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ 770 arg); \ 771 break; \ 772 default: \ 773 abort (); \ 774 } 775#endif 776 777 switch (type) 778 { 779 case TYPE_SCHAR: 780 { 781 int arg = a.arg[dp->arg_index].a.a_schar; 782 SNPRINTF_BUF (arg); 783 } 784 break; 785 case TYPE_UCHAR: 786 { 787 unsigned int arg = a.arg[dp->arg_index].a.a_uchar; 788 SNPRINTF_BUF (arg); 789 } 790 break; 791 case TYPE_SHORT: 792 { 793 int arg = a.arg[dp->arg_index].a.a_short; 794 SNPRINTF_BUF (arg); 795 } 796 break; 797 case TYPE_USHORT: 798 { 799 unsigned int arg = a.arg[dp->arg_index].a.a_ushort; 800 SNPRINTF_BUF (arg); 801 } 802 break; 803 case TYPE_INT: 804 { 805 int arg = a.arg[dp->arg_index].a.a_int; 806 SNPRINTF_BUF (arg); 807 } 808 break; 809 case TYPE_UINT: 810 { 811 unsigned int arg = a.arg[dp->arg_index].a.a_uint; 812 SNPRINTF_BUF (arg); 813 } 814 break; 815 case TYPE_LONGINT: 816 { 817 long int arg = a.arg[dp->arg_index].a.a_longint; 818 SNPRINTF_BUF (arg); 819 } 820 break; 821 case TYPE_ULONGINT: 822 { 823 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; 824 SNPRINTF_BUF (arg); 825 } 826 break; 827#ifdef HAVE_INT64_AND_I64 828 case TYPE_INT64: 829 { 830 __int64 arg = a.arg[dp->arg_index].a.a_int64; 831 SNPRINTF_BUF (arg); 832 } 833 break; 834 case TYPE_UINT64: 835 { 836 unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64; 837 SNPRINTF_BUF (arg); 838 } 839 break; 840#endif 841#ifdef HAVE_LONG_LONG 842#ifndef HAVE_LONG_LONG_FORMAT 843 case TYPE_LONGLONGINT: 844 case TYPE_ULONGLONGINT: 845 { 846 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; 847 int width; 848 int precision; 849 850 width = 0; 851 if (dp->width_start != dp->width_end) 852 { 853 if (dp->width_arg_index >= 0) 854 { 855 int arg; 856 857 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 858 abort (); 859 arg = a.arg[dp->width_arg_index].a.a_int; 860 width = (arg < 0 ? -arg : arg); 861 } 862 else 863 { 864 const char *digitp = dp->width_start; 865 866 do 867 width = width * 10 + (*digitp++ - '0'); 868 while (digitp != dp->width_end); 869 } 870 } 871 872 precision = -1; 873 if (dp->precision_start != dp->precision_end) 874 { 875 if (dp->precision_arg_index >= 0) 876 { 877 int arg; 878 879 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 880 abort (); 881 arg = a.arg[dp->precision_arg_index].a.a_int; 882 precision = (arg < 0 ? 0 : arg); 883 } 884 else 885 { 886 const char *digitp = dp->precision_start + 1; 887 888 precision = 0; 889 do 890 precision = precision * 10 + (*digitp++ - '0'); 891 while (digitp != dp->precision_end); 892 } 893 } 894 895#if HAVE_SNPRINTF 896 count = print_long_long (result + length, maxlen, 897 width, precision, 898 dp->flags, 899 dp->conversion, 900 arg); 901#else 902 count = print_long_long (tmp, tmp_length, 903 width, precision, 904 dp->flags, 905 dp->conversion, 906 arg); 907#endif 908 } 909 break; 910#else 911 case TYPE_LONGLONGINT: 912 { 913 long long int arg = a.arg[dp->arg_index].a.a_longlongint; 914 SNPRINTF_BUF (arg); 915 } 916 break; 917 case TYPE_ULONGLONGINT: 918 { 919 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; 920 SNPRINTF_BUF (arg); 921 } 922 break; 923#endif 924#endif 925 case TYPE_DOUBLE: 926 { 927 double arg = a.arg[dp->arg_index].a.a_double; 928 SNPRINTF_BUF (arg); 929 } 930 break; 931#ifdef HAVE_LONG_DOUBLE 932 case TYPE_LONGDOUBLE: 933 { 934 long double arg = a.arg[dp->arg_index].a.a_longdouble; 935 SNPRINTF_BUF (arg); 936 } 937 break; 938#endif 939 case TYPE_CHAR: 940 { 941 int arg = a.arg[dp->arg_index].a.a_char; 942 SNPRINTF_BUF (arg); 943 } 944 break; 945#ifdef HAVE_WINT_T 946 case TYPE_WIDE_CHAR: 947 { 948 wint_t arg = a.arg[dp->arg_index].a.a_wide_char; 949 SNPRINTF_BUF (arg); 950 } 951 break; 952#endif 953 case TYPE_STRING: 954 { 955 const char *arg = a.arg[dp->arg_index].a.a_string == NULL 956 ? "(null)" 957 : a.arg[dp->arg_index].a.a_string; 958 SNPRINTF_BUF (arg); 959 } 960 break; 961#ifdef HAVE_WCHAR_T 962 case TYPE_WIDE_STRING: 963 { 964 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string == NULL 965 ? L"(null)" 966 : a.arg[dp->arg_index].a.a_wide_string; 967 SNPRINTF_BUF (arg); 968 } 969 break; 970#endif 971 case TYPE_POINTER: 972 { 973 void *arg = a.arg[dp->arg_index].a.a_pointer; 974 SNPRINTF_BUF (arg); 975 } 976 break; 977 default: 978 abort (); 979 } 980 981#if HAVE_SNPRINTF 982 /* Portability: Not all implementations of snprintf() 983 are ISO C 99 compliant. Determine the number of 984 bytes that snprintf() has produced or would have 985 produced. */ 986 if (count >= 0) 987 { 988 /* Verify that snprintf() has NUL-terminated its 989 result. */ 990 if (count < maxlen && result[length + count] != '\0') 991 abort (); 992 /* Portability hack. */ 993 if (retcount > count) 994 count = retcount; 995 } 996 else 997 { 998 /* snprintf() doesn't understand the '%n' 999 directive. */ 1000 if (p[1] != '\0') 1001 { 1002 /* Don't use the '%n' directive; instead, look 1003 at the snprintf() return value. */ 1004 p[1] = '\0'; 1005 continue; 1006 } 1007 count = retcount; 1008 } 1009#endif 1010 1011 /* Attempt to handle failure. */ 1012 if (count < 0) 1013 { 1014 if (!(result == resultbuf || result == NULL)) 1015 free (result); 1016 freea (buf); 1017 CLEANUP (); 1018 errno = EINVAL; 1019 return NULL; 1020 } 1021 1022#if !HAVE_SNPRINTF 1023 if (count >= tmp_length) 1024 /* tmp_length was incorrectly calculated - fix the 1025 code above! */ 1026 abort (); 1027#endif 1028 1029 /* Make room for the result. */ 1030 if (count >= maxlen) 1031 { 1032 /* Need at least count bytes. But allocate 1033 proportionally, to avoid looping eternally if 1034 snprintf() reports a too small count. */ 1035 size_t n = length + count; 1036 1037 if (n < 2 * allocated) 1038 n = 2 * allocated; 1039 1040 ENSURE_ALLOCATION (n); 1041#if HAVE_SNPRINTF 1042 continue; 1043#endif 1044 } 1045 1046#if HAVE_SNPRINTF 1047 /* The snprintf() result did fit. */ 1048#else 1049 /* Append the sprintf() result. */ 1050 memcpy (result + length, tmp, count); 1051 if (tmp != tmpbuf) 1052 free (tmp); 1053#endif 1054 1055 length += count; 1056 break; 1057 } 1058 } 1059 } 1060 } 1061 1062 /* Add the final NUL. */ 1063 ENSURE_ALLOCATION (length + 1); 1064 result[length] = '\0'; 1065 1066 if (result != resultbuf && length + 1 < allocated) 1067 { 1068 /* Shrink the allocated memory if possible. */ 1069 char *memory; 1070 1071 memory = (char *) realloc (result, length + 1); 1072 if (memory != NULL) 1073 result = memory; 1074 } 1075 1076 freea (buf); 1077 CLEANUP (); 1078 *lengthp = length; 1079 return result; 1080 } 1081} 1082