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