1 1.1 tv /* 2 1.1 tv * Copyright (c) 1995-2001 Kungliga Tekniska Hgskolan 3 1.1 tv * (Royal Institute of Technology, Stockholm, Sweden). 4 1.1 tv * All rights reserved. 5 1.1 tv * 6 1.1 tv * Redistribution and use in source and binary forms, with or without 7 1.1 tv * modification, are permitted provided that the following conditions 8 1.1 tv * are met: 9 1.1 tv * 10 1.1 tv * 1. Redistributions of source code must retain the above copyright 11 1.1 tv * notice, this list of conditions and the following disclaimer. 12 1.1 tv * 13 1.1 tv * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 tv * notice, this list of conditions and the following disclaimer in the 15 1.1 tv * documentation and/or other materials provided with the distribution. 16 1.1 tv * 17 1.1 tv * 3. Neither the name of the Institute nor the names of its contributors 18 1.1 tv * may be used to endorse or promote products derived from this software 19 1.1 tv * without specific prior written permission. 20 1.1 tv * 21 1.1 tv * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 1.1 tv * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 1.1 tv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 tv * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 1.1 tv * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.1 tv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 1.1 tv * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 1.1 tv * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 1.1 tv * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 1.1 tv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 1.1 tv * SUCH DAMAGE. 32 1.1 tv */ 33 1.1 tv 34 1.1 tv /* From heimdal lib/roken/snprintf.c. */ 35 1.1 tv 36 1.3 lukem #if HAVE_NBTOOL_CONFIG_H 37 1.3 lukem #include "nbtool_config.h" 38 1.3 lukem #endif 39 1.3 lukem 40 1.2 tv #if 0 41 1.3 lukem RCSID("$Id: snprintf.c,v 1.3 2003/10/27 00:12:43 lukem Exp $"); 42 1.1 tv #endif 43 1.1 tv #include <stdio.h> 44 1.1 tv #include <stdarg.h> 45 1.1 tv #include <stdlib.h> 46 1.1 tv #include <string.h> 47 1.1 tv #include <ctype.h> 48 1.1 tv #if 0 49 1.1 tv #include <roken.h> 50 1.1 tv #endif 51 1.1 tv 52 1.1 tv #undef min 53 1.1 tv #define min(a,b) ((a) < (b) ? (a) : (b)) 54 1.1 tv #undef max 55 1.1 tv #define max(a,b) ((a) > (b) ? (a) : (b)) 56 1.1 tv 57 1.1 tv enum format_flags { 58 1.1 tv minus_flag = 1, 59 1.1 tv plus_flag = 2, 60 1.1 tv space_flag = 4, 61 1.1 tv alternate_flag = 8, 62 1.1 tv zero_flag = 16 63 1.1 tv }; 64 1.1 tv 65 1.1 tv /* 66 1.1 tv * Common state 67 1.1 tv */ 68 1.1 tv 69 1.1 tv struct state { 70 1.1 tv unsigned char *str; 71 1.1 tv unsigned char *s; 72 1.1 tv unsigned char *theend; 73 1.1 tv size_t sz; 74 1.1 tv size_t max_sz; 75 1.1 tv void (*append_char)(struct state *, unsigned char); 76 1.1 tv /* XXX - methods */ 77 1.1 tv }; 78 1.1 tv 79 1.1 tv #if TEST_SNPRINTF 80 1.1 tv #include "snprintf-test.h" 81 1.1 tv #endif /* TEST_SNPRINTF */ 82 1.1 tv 83 1.1 tv #if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF) 84 1.1 tv static int 85 1.1 tv sn_reserve (struct state *state, size_t n) 86 1.1 tv { 87 1.1 tv return state->s + n > state->theend; 88 1.1 tv } 89 1.1 tv 90 1.1 tv static void 91 1.1 tv sn_append_char (struct state *state, unsigned char c) 92 1.1 tv { 93 1.1 tv if (!sn_reserve (state, 1)) 94 1.1 tv *state->s++ = c; 95 1.1 tv } 96 1.1 tv #endif 97 1.1 tv 98 1.1 tv static int 99 1.1 tv as_reserve (struct state *state, size_t n) 100 1.1 tv { 101 1.1 tv if (state->s + n > state->theend) { 102 1.1 tv int off = state->s - state->str; 103 1.1 tv unsigned char *tmp; 104 1.1 tv 105 1.1 tv if (state->max_sz && state->sz >= state->max_sz) 106 1.1 tv return 1; 107 1.1 tv 108 1.1 tv state->sz = max(state->sz * 2, state->sz + n); 109 1.1 tv if (state->max_sz) 110 1.1 tv state->sz = min(state->sz, state->max_sz); 111 1.1 tv tmp = realloc (state->str, state->sz); 112 1.1 tv if (tmp == NULL) 113 1.1 tv return 1; 114 1.1 tv state->str = tmp; 115 1.1 tv state->s = state->str + off; 116 1.1 tv state->theend = state->str + state->sz - 1; 117 1.1 tv } 118 1.1 tv return 0; 119 1.1 tv } 120 1.1 tv 121 1.1 tv static void 122 1.1 tv as_append_char (struct state *state, unsigned char c) 123 1.1 tv { 124 1.1 tv if(!as_reserve (state, 1)) 125 1.1 tv *state->s++ = c; 126 1.1 tv } 127 1.1 tv 128 1.1 tv /* longest integer types */ 129 1.1 tv 130 1.1 tv #ifdef HAVE_LONG_LONG 131 1.1 tv typedef unsigned long long u_longest; 132 1.1 tv typedef long long longest; 133 1.1 tv #else 134 1.1 tv typedef unsigned long u_longest; 135 1.1 tv typedef long longest; 136 1.1 tv #endif 137 1.1 tv 138 1.1 tv /* 139 1.1 tv * is # supposed to do anything? 140 1.1 tv */ 141 1.1 tv 142 1.1 tv static int 143 1.1 tv use_alternative (int flags, u_longest num, unsigned base) 144 1.1 tv { 145 1.1 tv return flags & alternate_flag && (base == 16 || base == 8) && num != 0; 146 1.1 tv } 147 1.1 tv 148 1.1 tv static int 149 1.1 tv append_number(struct state *state, 150 1.1 tv u_longest num, unsigned base, char *rep, 151 1.1 tv int width, int prec, int flags, int minusp) 152 1.1 tv { 153 1.1 tv int len = 0; 154 1.1 tv int i; 155 1.1 tv u_longest n = num; 156 1.1 tv 157 1.1 tv /* given precision, ignore zero flag */ 158 1.1 tv if(prec != -1) 159 1.1 tv flags &= ~zero_flag; 160 1.1 tv else 161 1.1 tv prec = 1; 162 1.1 tv /* zero value with zero precision -> "" */ 163 1.1 tv if(prec == 0 && n == 0) 164 1.1 tv return 0; 165 1.1 tv do{ 166 1.1 tv (*state->append_char)(state, rep[n % base]); 167 1.1 tv ++len; 168 1.1 tv n /= base; 169 1.1 tv } while(n); 170 1.1 tv prec -= len; 171 1.1 tv /* pad with prec zeros */ 172 1.1 tv while(prec-- > 0){ 173 1.1 tv (*state->append_char)(state, '0'); 174 1.1 tv ++len; 175 1.1 tv } 176 1.1 tv /* add length of alternate prefix (added later) to len */ 177 1.1 tv if(use_alternative(flags, num, base)) 178 1.1 tv len += base / 8; 179 1.1 tv /* pad with zeros */ 180 1.1 tv if(flags & zero_flag){ 181 1.1 tv width -= len; 182 1.1 tv if(minusp || (flags & space_flag) || (flags & plus_flag)) 183 1.1 tv width--; 184 1.1 tv while(width-- > 0){ 185 1.1 tv (*state->append_char)(state, '0'); 186 1.1 tv len++; 187 1.1 tv } 188 1.1 tv } 189 1.1 tv /* add alternate prefix */ 190 1.1 tv if(use_alternative(flags, num, base)){ 191 1.1 tv if(base == 16) 192 1.1 tv (*state->append_char)(state, rep[10] + 23); /* XXX */ 193 1.1 tv (*state->append_char)(state, '0'); 194 1.1 tv } 195 1.1 tv /* add sign */ 196 1.1 tv if(minusp){ 197 1.1 tv (*state->append_char)(state, '-'); 198 1.1 tv ++len; 199 1.1 tv } else if(flags & plus_flag) { 200 1.1 tv (*state->append_char)(state, '+'); 201 1.1 tv ++len; 202 1.1 tv } else if(flags & space_flag) { 203 1.1 tv (*state->append_char)(state, ' '); 204 1.1 tv ++len; 205 1.1 tv } 206 1.1 tv if(flags & minus_flag) 207 1.1 tv /* swap before padding with spaces */ 208 1.1 tv for(i = 0; i < len / 2; i++){ 209 1.1 tv char c = state->s[-i-1]; 210 1.1 tv state->s[-i-1] = state->s[-len+i]; 211 1.1 tv state->s[-len+i] = c; 212 1.1 tv } 213 1.1 tv width -= len; 214 1.1 tv while(width-- > 0){ 215 1.1 tv (*state->append_char)(state, ' '); 216 1.1 tv ++len; 217 1.1 tv } 218 1.1 tv if(!(flags & minus_flag)) 219 1.1 tv /* swap after padding with spaces */ 220 1.1 tv for(i = 0; i < len / 2; i++){ 221 1.1 tv char c = state->s[-i-1]; 222 1.1 tv state->s[-i-1] = state->s[-len+i]; 223 1.1 tv state->s[-len+i] = c; 224 1.1 tv } 225 1.1 tv return len; 226 1.1 tv } 227 1.1 tv 228 1.1 tv /* 229 1.1 tv * return length 230 1.1 tv */ 231 1.1 tv 232 1.1 tv static int 233 1.1 tv append_string (struct state *state, 234 1.1 tv const unsigned char *arg, 235 1.1 tv int width, 236 1.1 tv int prec, 237 1.1 tv int flags) 238 1.1 tv { 239 1.1 tv int len = 0; 240 1.1 tv 241 1.1 tv if(arg == NULL) 242 1.1 tv arg = (const unsigned char*)"(null)"; 243 1.1 tv 244 1.1 tv if(prec != -1) 245 1.1 tv width -= prec; 246 1.1 tv else 247 1.1 tv width -= strlen((const char *)arg); 248 1.1 tv if(!(flags & minus_flag)) 249 1.1 tv while(width-- > 0) { 250 1.1 tv (*state->append_char) (state, ' '); 251 1.1 tv ++len; 252 1.1 tv } 253 1.1 tv if (prec != -1) { 254 1.1 tv while (*arg && prec--) { 255 1.1 tv (*state->append_char) (state, *arg++); 256 1.1 tv ++len; 257 1.1 tv } 258 1.1 tv } else { 259 1.1 tv while (*arg) { 260 1.1 tv (*state->append_char) (state, *arg++); 261 1.1 tv ++len; 262 1.1 tv } 263 1.1 tv } 264 1.1 tv if(flags & minus_flag) 265 1.1 tv while(width-- > 0) { 266 1.1 tv (*state->append_char) (state, ' '); 267 1.1 tv ++len; 268 1.1 tv } 269 1.1 tv return len; 270 1.1 tv } 271 1.1 tv 272 1.1 tv static int 273 1.1 tv append_char(struct state *state, 274 1.1 tv unsigned char arg, 275 1.1 tv int width, 276 1.1 tv int flags) 277 1.1 tv { 278 1.1 tv int len = 0; 279 1.1 tv 280 1.1 tv while(!(flags & minus_flag) && --width > 0) { 281 1.1 tv (*state->append_char) (state, ' ') ; 282 1.1 tv ++len; 283 1.1 tv } 284 1.1 tv (*state->append_char) (state, arg); 285 1.1 tv ++len; 286 1.1 tv while((flags & minus_flag) && --width > 0) { 287 1.1 tv (*state->append_char) (state, ' '); 288 1.1 tv ++len; 289 1.1 tv } 290 1.1 tv return 0; 291 1.1 tv } 292 1.1 tv 293 1.1 tv /* 294 1.1 tv * This can't be made into a function... 295 1.1 tv */ 296 1.1 tv 297 1.1 tv #ifdef HAVE_LONG_LONG 298 1.1 tv 299 1.1 tv #define PARSE_INT_FORMAT(res, arg, unsig) \ 300 1.1 tv if (long_long_flag) \ 301 1.1 tv res = (unsig long long)va_arg(arg, unsig long long); \ 302 1.1 tv else if (long_flag) \ 303 1.1 tv res = (unsig long)va_arg(arg, unsig long); \ 304 1.1 tv else if (short_flag) \ 305 1.1 tv res = (unsig short)va_arg(arg, unsig int); \ 306 1.1 tv else \ 307 1.1 tv res = (unsig int)va_arg(arg, unsig int) 308 1.1 tv 309 1.1 tv #else 310 1.1 tv 311 1.1 tv #define PARSE_INT_FORMAT(res, arg, unsig) \ 312 1.1 tv if (long_flag) \ 313 1.1 tv res = (unsig long)va_arg(arg, unsig long); \ 314 1.1 tv else if (short_flag) \ 315 1.1 tv res = (unsig short)va_arg(arg, unsig int); \ 316 1.1 tv else \ 317 1.1 tv res = (unsig int)va_arg(arg, unsig int) 318 1.1 tv 319 1.1 tv #endif 320 1.1 tv 321 1.1 tv /* 322 1.1 tv * zyxprintf - return length, as snprintf 323 1.1 tv */ 324 1.1 tv 325 1.1 tv static int 326 1.1 tv xyzprintf (struct state *state, const char *char_format, va_list ap) 327 1.1 tv { 328 1.1 tv const unsigned char *format = (const unsigned char *)char_format; 329 1.1 tv unsigned char c; 330 1.1 tv int len = 0; 331 1.1 tv 332 1.1 tv while((c = *format++)) { 333 1.1 tv if (c == '%') { 334 1.1 tv int flags = 0; 335 1.1 tv int width = 0; 336 1.1 tv int prec = -1; 337 1.1 tv int long_long_flag = 0; 338 1.1 tv int long_flag = 0; 339 1.1 tv int short_flag = 0; 340 1.1 tv 341 1.1 tv /* flags */ 342 1.1 tv while((c = *format++)){ 343 1.1 tv if(c == '-') 344 1.1 tv flags |= minus_flag; 345 1.1 tv else if(c == '+') 346 1.1 tv flags |= plus_flag; 347 1.1 tv else if(c == ' ') 348 1.1 tv flags |= space_flag; 349 1.1 tv else if(c == '#') 350 1.1 tv flags |= alternate_flag; 351 1.1 tv else if(c == '0') 352 1.1 tv flags |= zero_flag; 353 1.1 tv else 354 1.1 tv break; 355 1.1 tv } 356 1.1 tv 357 1.1 tv if((flags & space_flag) && (flags & plus_flag)) 358 1.1 tv flags ^= space_flag; 359 1.1 tv 360 1.1 tv if((flags & minus_flag) && (flags & zero_flag)) 361 1.1 tv flags ^= zero_flag; 362 1.1 tv 363 1.1 tv /* width */ 364 1.1 tv if (isdigit(c)) 365 1.1 tv do { 366 1.1 tv width = width * 10 + c - '0'; 367 1.1 tv c = *format++; 368 1.1 tv } while(isdigit(c)); 369 1.1 tv else if(c == '*') { 370 1.1 tv width = va_arg(ap, int); 371 1.1 tv c = *format++; 372 1.1 tv } 373 1.1 tv 374 1.1 tv /* precision */ 375 1.1 tv if (c == '.') { 376 1.1 tv prec = 0; 377 1.1 tv c = *format++; 378 1.1 tv if (isdigit(c)) 379 1.1 tv do { 380 1.1 tv prec = prec * 10 + c - '0'; 381 1.1 tv c = *format++; 382 1.1 tv } while(isdigit(c)); 383 1.1 tv else if (c == '*') { 384 1.1 tv prec = va_arg(ap, int); 385 1.1 tv c = *format++; 386 1.1 tv } 387 1.1 tv } 388 1.1 tv 389 1.1 tv /* size */ 390 1.1 tv 391 1.1 tv if (c == 'h') { 392 1.1 tv short_flag = 1; 393 1.1 tv c = *format++; 394 1.1 tv } else if (c == 'l') { 395 1.1 tv long_flag = 1; 396 1.1 tv c = *format++; 397 1.1 tv if (c == 'l') { 398 1.1 tv long_long_flag = 1; 399 1.1 tv c = *format++; 400 1.1 tv } 401 1.1 tv } 402 1.1 tv 403 1.1 tv switch (c) { 404 1.1 tv case 'c' : 405 1.1 tv append_char(state, va_arg(ap, int), width, flags); 406 1.1 tv ++len; 407 1.1 tv break; 408 1.1 tv case 's' : 409 1.1 tv len += append_string(state, 410 1.1 tv va_arg(ap, unsigned char*), 411 1.1 tv width, 412 1.1 tv prec, 413 1.1 tv flags); 414 1.1 tv break; 415 1.1 tv case 'd' : 416 1.1 tv case 'i' : { 417 1.1 tv longest arg; 418 1.1 tv u_longest num; 419 1.1 tv int minusp = 0; 420 1.1 tv 421 1.1 tv PARSE_INT_FORMAT(arg, ap, signed); 422 1.1 tv 423 1.1 tv if (arg < 0) { 424 1.1 tv minusp = 1; 425 1.1 tv num = -arg; 426 1.1 tv } else 427 1.1 tv num = arg; 428 1.1 tv 429 1.1 tv len += append_number (state, num, 10, "0123456789", 430 1.1 tv width, prec, flags, minusp); 431 1.1 tv break; 432 1.1 tv } 433 1.1 tv case 'u' : { 434 1.1 tv u_longest arg; 435 1.1 tv 436 1.1 tv PARSE_INT_FORMAT(arg, ap, unsigned); 437 1.1 tv 438 1.1 tv len += append_number (state, arg, 10, "0123456789", 439 1.1 tv width, prec, flags, 0); 440 1.1 tv break; 441 1.1 tv } 442 1.1 tv case 'o' : { 443 1.1 tv u_longest arg; 444 1.1 tv 445 1.1 tv PARSE_INT_FORMAT(arg, ap, unsigned); 446 1.1 tv 447 1.1 tv len += append_number (state, arg, 010, "01234567", 448 1.1 tv width, prec, flags, 0); 449 1.1 tv break; 450 1.1 tv } 451 1.1 tv case 'x' : { 452 1.1 tv u_longest arg; 453 1.1 tv 454 1.1 tv PARSE_INT_FORMAT(arg, ap, unsigned); 455 1.1 tv 456 1.1 tv len += append_number (state, arg, 0x10, "0123456789abcdef", 457 1.1 tv width, prec, flags, 0); 458 1.1 tv break; 459 1.1 tv } 460 1.1 tv case 'X' :{ 461 1.1 tv u_longest arg; 462 1.1 tv 463 1.1 tv PARSE_INT_FORMAT(arg, ap, unsigned); 464 1.1 tv 465 1.1 tv len += append_number (state, arg, 0x10, "0123456789ABCDEF", 466 1.1 tv width, prec, flags, 0); 467 1.1 tv break; 468 1.1 tv } 469 1.1 tv case 'p' : { 470 1.1 tv unsigned long arg = (unsigned long)va_arg(ap, void*); 471 1.1 tv 472 1.1 tv len += append_number (state, arg, 0x10, "0123456789ABCDEF", 473 1.1 tv width, prec, flags, 0); 474 1.1 tv break; 475 1.1 tv } 476 1.1 tv case 'n' : { 477 1.1 tv int *arg = va_arg(ap, int*); 478 1.1 tv *arg = state->s - state->str; 479 1.1 tv break; 480 1.1 tv } 481 1.1 tv case '\0' : 482 1.1 tv --format; 483 1.1 tv /* FALLTHROUGH */ 484 1.1 tv case '%' : 485 1.1 tv (*state->append_char)(state, c); 486 1.1 tv ++len; 487 1.1 tv break; 488 1.1 tv default : 489 1.1 tv (*state->append_char)(state, '%'); 490 1.1 tv (*state->append_char)(state, c); 491 1.1 tv len += 2; 492 1.1 tv break; 493 1.1 tv } 494 1.1 tv } else { 495 1.1 tv (*state->append_char) (state, c); 496 1.1 tv ++len; 497 1.1 tv } 498 1.1 tv } 499 1.1 tv return len; 500 1.1 tv } 501 1.1 tv 502 1.1 tv #if !defined(HAVE_SNPRINTF) || defined(TEST_SNPRINTF) 503 1.1 tv int 504 1.1 tv snprintf (char *str, size_t sz, const char *format, ...) 505 1.1 tv { 506 1.1 tv va_list args; 507 1.1 tv int ret; 508 1.1 tv 509 1.1 tv va_start(args, format); 510 1.1 tv ret = vsnprintf (str, sz, format, args); 511 1.1 tv va_end(args); 512 1.1 tv 513 1.1 tv #ifdef PARANOIA 514 1.1 tv { 515 1.1 tv int ret2; 516 1.1 tv char *tmp; 517 1.1 tv 518 1.1 tv tmp = malloc (sz); 519 1.1 tv if (tmp == NULL) 520 1.1 tv abort (); 521 1.1 tv 522 1.1 tv va_start(args, format); 523 1.1 tv ret2 = vsprintf (tmp, format, args); 524 1.1 tv va_end(args); 525 1.1 tv if (ret != ret2 || strcmp(str, tmp)) 526 1.1 tv abort (); 527 1.1 tv free (tmp); 528 1.1 tv } 529 1.1 tv #endif 530 1.1 tv 531 1.1 tv return ret; 532 1.1 tv } 533 1.1 tv #endif 534 1.1 tv 535 1.1 tv #if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF) 536 1.1 tv int 537 1.1 tv asprintf (char **ret, const char *format, ...) 538 1.1 tv { 539 1.1 tv va_list args; 540 1.1 tv int val; 541 1.1 tv 542 1.1 tv va_start(args, format); 543 1.1 tv val = vasprintf (ret, format, args); 544 1.1 tv 545 1.1 tv #ifdef PARANOIA 546 1.1 tv { 547 1.1 tv int ret2; 548 1.1 tv char *tmp; 549 1.1 tv tmp = malloc (val + 1); 550 1.1 tv if (tmp == NULL) 551 1.1 tv abort (); 552 1.1 tv 553 1.1 tv ret2 = vsprintf (tmp, format, args); 554 1.1 tv if (val != ret2 || strcmp(*ret, tmp)) 555 1.1 tv abort (); 556 1.1 tv free (tmp); 557 1.1 tv } 558 1.1 tv #endif 559 1.1 tv 560 1.1 tv va_end(args); 561 1.1 tv return val; 562 1.1 tv } 563 1.1 tv #endif 564 1.1 tv 565 1.1 tv #if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF) 566 1.1 tv int 567 1.1 tv asnprintf (char **ret, size_t max_sz, const char *format, ...) 568 1.1 tv { 569 1.1 tv va_list args; 570 1.1 tv int val; 571 1.1 tv 572 1.1 tv va_start(args, format); 573 1.1 tv val = vasnprintf (ret, max_sz, format, args); 574 1.1 tv 575 1.1 tv #ifdef PARANOIA 576 1.1 tv { 577 1.1 tv int ret2; 578 1.1 tv char *tmp; 579 1.1 tv tmp = malloc (val + 1); 580 1.1 tv if (tmp == NULL) 581 1.1 tv abort (); 582 1.1 tv 583 1.1 tv ret2 = vsprintf (tmp, format, args); 584 1.1 tv if (val != ret2 || strcmp(*ret, tmp)) 585 1.1 tv abort (); 586 1.1 tv free (tmp); 587 1.1 tv } 588 1.1 tv #endif 589 1.1 tv 590 1.1 tv va_end(args); 591 1.1 tv return val; 592 1.1 tv } 593 1.1 tv #endif 594 1.1 tv 595 1.1 tv #if !defined(HAVE_VASPRINTF) || defined(TEST_SNPRINTF) 596 1.1 tv int 597 1.1 tv vasprintf (char **ret, const char *format, va_list args) 598 1.1 tv { 599 1.1 tv return vasnprintf (ret, 0, format, args); 600 1.1 tv } 601 1.1 tv #endif 602 1.1 tv 603 1.1 tv 604 1.1 tv #if !defined(HAVE_VASNPRINTF) || defined(TEST_SNPRINTF) 605 1.1 tv int 606 1.1 tv vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) 607 1.1 tv { 608 1.1 tv int st; 609 1.1 tv struct state state; 610 1.1 tv 611 1.1 tv state.max_sz = max_sz; 612 1.1 tv state.sz = 1; 613 1.1 tv state.str = malloc(state.sz); 614 1.1 tv if (state.str == NULL) { 615 1.1 tv *ret = NULL; 616 1.1 tv return -1; 617 1.1 tv } 618 1.1 tv state.s = state.str; 619 1.1 tv state.theend = state.s + state.sz - 1; 620 1.1 tv state.append_char = as_append_char; 621 1.1 tv 622 1.1 tv st = xyzprintf (&state, format, args); 623 1.1 tv if (st > state.sz) { 624 1.1 tv free (state.str); 625 1.1 tv *ret = NULL; 626 1.1 tv return -1; 627 1.1 tv } else { 628 1.1 tv char *tmp; 629 1.1 tv 630 1.1 tv *state.s = '\0'; 631 1.1 tv tmp = realloc (state.str, st+1); 632 1.1 tv if (tmp == NULL) { 633 1.1 tv free (state.str); 634 1.1 tv *ret = NULL; 635 1.1 tv return -1; 636 1.1 tv } 637 1.1 tv *ret = tmp; 638 1.1 tv return st; 639 1.1 tv } 640 1.1 tv } 641 1.1 tv #endif 642 1.1 tv 643 1.1 tv #if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF) 644 1.1 tv int 645 1.1 tv vsnprintf (char *str, size_t sz, const char *format, va_list args) 646 1.1 tv { 647 1.1 tv struct state state; 648 1.1 tv int ret; 649 1.1 tv unsigned char *ustr = (unsigned char *)str; 650 1.1 tv 651 1.1 tv state.max_sz = 0; 652 1.1 tv state.sz = sz; 653 1.1 tv state.str = ustr; 654 1.1 tv state.s = ustr; 655 1.1 tv state.theend = ustr + sz - (sz > 0); 656 1.1 tv state.append_char = sn_append_char; 657 1.1 tv 658 1.1 tv ret = xyzprintf (&state, format, args); 659 1.1 tv if (state.s != NULL) 660 1.1 tv *state.s = '\0'; 661 1.1 tv return ret; 662 1.1 tv } 663 1.1 tv #endif 664