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