1 /* 2 * Copyright Patrick Powell 1995 3 * This code is based on code written by Patrick Powell (papowell (at) astart.com) 4 * It may be used for any purpose as long as this notice remains intact 5 * on all source code distributions 6 */ 7 8 /************************************************************** 9 * Original: 10 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 11 * A bombproof version of doprnt (dopr) included. 12 * Sigh. This sort of thing is always nasty do deal with. Note that 13 * the version here does not include floating point... 14 * 15 * snprintf() is used instead of sprintf() as it does limit checks 16 * for string length. This covers a nasty loophole. 17 * 18 * The other functions are there to prevent NULL pointers from 19 * causing nast effects. 20 * 21 * More Recently: 22 * Brandon Long <blong (at) fiction.net> 9/15/96 for mutt 0.43 23 * This was ugly. It is still ugly. I opted out of floating point 24 * numbers, but the formatter understands just about everything 25 * from the normal C string format, at least as far as I can tell from 26 * the Solaris 2.5 printf(3S) man page. 27 * 28 * Brandon Long <blong (at) fiction.net> 10/22/97 for mutt 0.87.1 29 * Ok, added some minimal floating point support, which means this 30 * probably requires libm on most operating systems. Don't yet 31 * support the exponent (e,E) and sigfig (g,G). Also, fmtint() 32 * was pretty badly broken, it just wasn't being exercised in ways 33 * which showed it, so that's been fixed. Also, formated the code 34 * to mutt conventions, and removed dead code left over from the 35 * original. Also, there is now a builtin-test, just compile with: 36 * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm 37 * and run snprintf for results. 38 * 39 * Thomas Roessler <roessler (at) guug.de> 01/27/98 for mutt 0.89i 40 * The PGP code was using unsigned hexadecimal formats. 41 * Unfortunately, unsigned formats simply didn't work. 42 * 43 * Michael Elkins <me (at) cs.hmc.edu> 03/05/98 for mutt 0.90.8 44 * The original code assumed that both snprintf() and vsnprintf() were 45 * missing. Some systems only have snprintf() but not vsnprintf(), so 46 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. 47 * 48 * Andrew Tridgell (tridge (at) samba.org) Oct 1998 49 * fixed handling of %.0f 50 * added test for HAVE_LONG_DOUBLE 51 * 52 * Russ Allbery <rra (at) stanford.edu> 2000-08-26 53 * fixed return value to comply with C99 54 * fixed handling of snprintf(NULL, ...) 55 * 56 **************************************************************/ 57 58 #include "cs_config.h" 59 60 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) 61 62 #include <string.h> 63 #include <ctype.h> 64 #include <sys/types.h> 65 66 /* Define this as a fall through, HAVE_STDARG_H is probably already set */ 67 68 #define HAVE_VARARGS_H 69 70 71 /* varargs declarations: */ 72 73 #if defined(HAVE_STDARG_H) 74 # include <stdarg.h> 75 # define HAVE_STDARGS /* let's hope that works everywhere (mj) */ 76 # define VA_LOCAL_DECL va_list ap 77 # define VA_START(f) va_start(ap, f) 78 # define VA_SHIFT(v,t) ; /* no-op for ANSI */ 79 # define VA_END va_end(ap) 80 #else 81 # if defined(HAVE_VARARGS_H) 82 # include <varargs.h> 83 # undef HAVE_STDARGS 84 # define VA_LOCAL_DECL va_list ap 85 # define VA_START(f) va_start(ap) /* f is ignored! */ 86 # define VA_SHIFT(v,t) v = va_arg(ap,t) 87 # define VA_END va_end(ap) 88 # else 89 /*XX ** NO VARARGS ** XX*/ 90 # endif 91 #endif 92 93 #ifdef HAVE_LONG_DOUBLE 94 #define LDOUBLE long double 95 #else 96 #define LDOUBLE double 97 #endif 98 99 int snprintf (char *str, size_t count, const char *fmt, ...); 100 int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); 101 102 static int dopr (char *buffer, size_t maxlen, const char *format, 103 va_list args); 104 static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, 105 char *value, int flags, int min, int max); 106 static int fmtint (char *buffer, size_t *currlen, size_t maxlen, 107 long value, int base, int min, int max, int flags); 108 static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, 109 LDOUBLE fvalue, int min, int max, int flags); 110 static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); 111 112 /* 113 * dopr(): poor man's version of doprintf 114 */ 115 116 /* format read states */ 117 #define DP_S_DEFAULT 0 118 #define DP_S_FLAGS 1 119 #define DP_S_MIN 2 120 #define DP_S_DOT 3 121 #define DP_S_MAX 4 122 #define DP_S_MOD 5 123 #define DP_S_CONV 6 124 #define DP_S_DONE 7 125 126 /* format flags - Bits */ 127 #define DP_F_MINUS (1 << 0) 128 #define DP_F_PLUS (1 << 1) 129 #define DP_F_SPACE (1 << 2) 130 #define DP_F_NUM (1 << 3) 131 #define DP_F_ZERO (1 << 4) 132 #define DP_F_UP (1 << 5) 133 #define DP_F_UNSIGNED (1 << 6) 134 135 /* Conversion Flags */ 136 #define DP_C_SHORT 1 137 #define DP_C_LONG 2 138 #define DP_C_LDOUBLE 3 139 140 #define char_to_int(p) (p - '0') 141 #define MAX(p,q) ((p >= q) ? p : q) 142 #define MIN(p,q) ((p <= q) ? p : q) 143 144 static int dopr (char *buffer, size_t maxlen, const char *format, va_list args) 145 { 146 char ch; 147 long value; 148 LDOUBLE fvalue; 149 char *strvalue; 150 int min; 151 int max; 152 int state; 153 int flags; 154 int cflags; 155 int total; 156 size_t currlen; 157 158 state = DP_S_DEFAULT; 159 currlen = flags = cflags = min = 0; 160 max = -1; 161 ch = *format++; 162 total = 0; 163 164 while (state != DP_S_DONE) 165 { 166 if (ch == '\0') 167 state = DP_S_DONE; 168 169 switch(state) 170 { 171 case DP_S_DEFAULT: 172 if (ch == '%') 173 state = DP_S_FLAGS; 174 else 175 total += dopr_outch (buffer, &currlen, maxlen, ch); 176 ch = *format++; 177 break; 178 case DP_S_FLAGS: 179 switch (ch) 180 { 181 case '-': 182 flags |= DP_F_MINUS; 183 ch = *format++; 184 break; 185 case '+': 186 flags |= DP_F_PLUS; 187 ch = *format++; 188 break; 189 case ' ': 190 flags |= DP_F_SPACE; 191 ch = *format++; 192 break; 193 case '#': 194 flags |= DP_F_NUM; 195 ch = *format++; 196 break; 197 case '0': 198 flags |= DP_F_ZERO; 199 ch = *format++; 200 break; 201 default: 202 state = DP_S_MIN; 203 break; 204 } 205 break; 206 case DP_S_MIN: 207 if (isdigit(ch)) 208 { 209 min = 10*min + char_to_int (ch); 210 ch = *format++; 211 } 212 else if (ch == '*') 213 { 214 min = va_arg (args, int); 215 ch = *format++; 216 state = DP_S_DOT; 217 } 218 else 219 state = DP_S_DOT; 220 break; 221 case DP_S_DOT: 222 if (ch == '.') 223 { 224 state = DP_S_MAX; 225 ch = *format++; 226 } 227 else 228 state = DP_S_MOD; 229 break; 230 case DP_S_MAX: 231 if (isdigit(ch)) 232 { 233 if (max < 0) 234 max = 0; 235 max = 10*max + char_to_int (ch); 236 ch = *format++; 237 } 238 else if (ch == '*') 239 { 240 max = va_arg (args, int); 241 ch = *format++; 242 state = DP_S_MOD; 243 } 244 else 245 state = DP_S_MOD; 246 break; 247 case DP_S_MOD: 248 /* Currently, we don't support Long Long, bummer */ 249 switch (ch) 250 { 251 case 'h': 252 cflags = DP_C_SHORT; 253 ch = *format++; 254 break; 255 case 'l': 256 cflags = DP_C_LONG; 257 ch = *format++; 258 break; 259 case 'L': 260 cflags = DP_C_LDOUBLE; 261 ch = *format++; 262 break; 263 default: 264 break; 265 } 266 state = DP_S_CONV; 267 break; 268 case DP_S_CONV: 269 switch (ch) 270 { 271 case 'd': 272 case 'i': 273 if (cflags == DP_C_SHORT) 274 value = va_arg (args, short int); 275 else if (cflags == DP_C_LONG) 276 value = va_arg (args, long int); 277 else 278 value = va_arg (args, int); 279 total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); 280 break; 281 case 'o': 282 flags |= DP_F_UNSIGNED; 283 if (cflags == DP_C_SHORT) 284 value = va_arg (args, unsigned short int); 285 else if (cflags == DP_C_LONG) 286 value = va_arg (args, unsigned long int); 287 else 288 value = va_arg (args, unsigned int); 289 total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); 290 break; 291 case 'u': 292 flags |= DP_F_UNSIGNED; 293 if (cflags == DP_C_SHORT) 294 value = va_arg (args, unsigned short int); 295 else if (cflags == DP_C_LONG) 296 value = va_arg (args, unsigned long int); 297 else 298 value = va_arg (args, unsigned int); 299 total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); 300 break; 301 case 'X': 302 flags |= DP_F_UP; 303 case 'x': 304 flags |= DP_F_UNSIGNED; 305 if (cflags == DP_C_SHORT) 306 value = va_arg (args, unsigned short int); 307 else if (cflags == DP_C_LONG) 308 value = va_arg (args, unsigned long int); 309 else 310 value = va_arg (args, unsigned int); 311 total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); 312 break; 313 case 'f': 314 if (cflags == DP_C_LDOUBLE) 315 fvalue = va_arg (args, LDOUBLE); 316 else 317 fvalue = va_arg (args, double); 318 /* um, floating point? */ 319 total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); 320 break; 321 case 'E': 322 flags |= DP_F_UP; 323 case 'e': 324 if (cflags == DP_C_LDOUBLE) 325 fvalue = va_arg (args, LDOUBLE); 326 else 327 fvalue = va_arg (args, double); 328 break; 329 case 'G': 330 flags |= DP_F_UP; 331 case 'g': 332 if (cflags == DP_C_LDOUBLE) 333 fvalue = va_arg (args, LDOUBLE); 334 else 335 fvalue = va_arg (args, double); 336 break; 337 case 'c': 338 total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); 339 break; 340 case 's': 341 strvalue = va_arg (args, char *); 342 total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); 343 break; 344 case 'p': 345 strvalue = va_arg (args, void *); 346 total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, 347 max, flags); 348 break; 349 case 'n': 350 if (cflags == DP_C_SHORT) 351 { 352 short int *num; 353 num = va_arg (args, short int *); 354 *num = currlen; 355 } 356 else if (cflags == DP_C_LONG) 357 { 358 long int *num; 359 num = va_arg (args, long int *); 360 *num = currlen; 361 } 362 else 363 { 364 int *num; 365 num = va_arg (args, int *); 366 *num = currlen; 367 } 368 break; 369 case '%': 370 total += dopr_outch (buffer, &currlen, maxlen, ch); 371 break; 372 case 'w': 373 /* not supported yet, treat as next char */ 374 ch = *format++; 375 break; 376 default: 377 /* Unknown, skip */ 378 break; 379 } 380 ch = *format++; 381 state = DP_S_DEFAULT; 382 flags = cflags = min = 0; 383 max = -1; 384 break; 385 case DP_S_DONE: 386 break; 387 default: 388 /* hmm? */ 389 break; /* some picky compilers need this */ 390 } 391 } 392 if (buffer != NULL) 393 { 394 if (currlen < maxlen - 1) 395 buffer[currlen] = '\0'; 396 else 397 buffer[maxlen - 1] = '\0'; 398 } 399 return total; 400 } 401 402 static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, 403 char *value, int flags, int min, int max) 404 { 405 int padlen, strln; /* amount to pad */ 406 int cnt = 0; 407 int total = 0; 408 409 if (value == 0) 410 { 411 value = "<NULL>"; 412 } 413 414 for (strln = 0; value[strln]; ++strln); /* strlen */ 415 if (max >= 0 && max < strln) 416 strln = max; 417 padlen = min - strln; 418 if (padlen < 0) 419 padlen = 0; 420 if (flags & DP_F_MINUS) 421 padlen = -padlen; /* Left Justify */ 422 423 while (padlen > 0) 424 { 425 total += dopr_outch (buffer, currlen, maxlen, ' '); 426 --padlen; 427 } 428 while (*value && ((max < 0) || (cnt < max))) 429 { 430 total += dopr_outch (buffer, currlen, maxlen, *value++); 431 ++cnt; 432 } 433 while (padlen < 0) 434 { 435 total += dopr_outch (buffer, currlen, maxlen, ' '); 436 ++padlen; 437 } 438 return total; 439 } 440 441 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ 442 443 static int fmtint (char *buffer, size_t *currlen, size_t maxlen, 444 long value, int base, int min, int max, int flags) 445 { 446 int signvalue = 0; 447 unsigned long uvalue; 448 char convert[20]; 449 int place = 0; 450 int spadlen = 0; /* amount to space pad */ 451 int zpadlen = 0; /* amount to zero pad */ 452 int caps = 0; 453 int total = 0; 454 455 if (max < 0) 456 max = 0; 457 458 uvalue = value; 459 460 if(!(flags & DP_F_UNSIGNED)) 461 { 462 if( value < 0 ) { 463 signvalue = '-'; 464 uvalue = -value; 465 } 466 else 467 if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 468 signvalue = '+'; 469 else 470 if (flags & DP_F_SPACE) 471 signvalue = ' '; 472 } 473 474 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ 475 476 do { 477 convert[place++] = 478 (caps? "0123456789ABCDEF":"0123456789abcdef") 479 [uvalue % (unsigned)base ]; 480 uvalue = (uvalue / (unsigned)base ); 481 } while(uvalue && (place < 20)); 482 if (place == 20) place--; 483 convert[place] = 0; 484 485 zpadlen = max - place; 486 spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); 487 if (zpadlen < 0) zpadlen = 0; 488 if (spadlen < 0) spadlen = 0; 489 if (flags & DP_F_ZERO) 490 { 491 zpadlen = MAX(zpadlen, spadlen); 492 spadlen = 0; 493 } 494 if (flags & DP_F_MINUS) 495 spadlen = -spadlen; /* Left Justifty */ 496 497 #ifdef DEBUG_SNPRINTF 498 dprint (1, (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", 499 zpadlen, spadlen, min, max, place)); 500 #endif 501 502 /* Spaces */ 503 while (spadlen > 0) 504 { 505 total += dopr_outch (buffer, currlen, maxlen, ' '); 506 --spadlen; 507 } 508 509 /* Sign */ 510 if (signvalue) 511 total += dopr_outch (buffer, currlen, maxlen, signvalue); 512 513 /* Zeros */ 514 if (zpadlen > 0) 515 { 516 while (zpadlen > 0) 517 { 518 total += dopr_outch (buffer, currlen, maxlen, '0'); 519 --zpadlen; 520 } 521 } 522 523 /* Digits */ 524 while (place > 0) 525 total += dopr_outch (buffer, currlen, maxlen, convert[--place]); 526 527 /* Left Justified spaces */ 528 while (spadlen < 0) { 529 total += dopr_outch (buffer, currlen, maxlen, ' '); 530 ++spadlen; 531 } 532 533 return total; 534 } 535 536 static LDOUBLE abs_val (LDOUBLE value) 537 { 538 LDOUBLE result = value; 539 540 if (value < 0) 541 result = -value; 542 543 return result; 544 } 545 546 static LDOUBLE pow10 (int exp) 547 { 548 LDOUBLE result = 1; 549 550 while (exp) 551 { 552 result *= 10; 553 exp--; 554 } 555 556 return result; 557 } 558 559 static long round (LDOUBLE value) 560 { 561 long intpart; 562 563 intpart = value; 564 value = value - intpart; 565 if (value >= 0.5) 566 intpart++; 567 568 return intpart; 569 } 570 571 static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, 572 LDOUBLE fvalue, int min, int max, int flags) 573 { 574 int signvalue = 0; 575 LDOUBLE ufvalue; 576 char iconvert[20]; 577 char fconvert[20]; 578 int iplace = 0; 579 int fplace = 0; 580 int padlen = 0; /* amount to pad */ 581 int zpadlen = 0; 582 int caps = 0; 583 int total = 0; 584 long intpart; 585 long fracpart; 586 587 /* 588 * AIX manpage says the default is 0, but Solaris says the default 589 * is 6, and sprintf on AIX defaults to 6 590 */ 591 if (max < 0) 592 max = 6; 593 594 ufvalue = abs_val (fvalue); 595 596 if (fvalue < 0) 597 signvalue = '-'; 598 else 599 if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 600 signvalue = '+'; 601 else 602 if (flags & DP_F_SPACE) 603 signvalue = ' '; 604 605 #if 0 606 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ 607 #endif 608 609 intpart = ufvalue; 610 611 /* 612 * Sorry, we only support 9 digits past the decimal because of our 613 * conversion method 614 */ 615 if (max > 9) 616 max = 9; 617 618 /* We "cheat" by converting the fractional part to integer by 619 * multiplying by a factor of 10 620 */ 621 fracpart = round ((pow10 (max)) * (ufvalue - intpart)); 622 623 if (fracpart >= pow10 (max)) 624 { 625 intpart++; 626 fracpart -= pow10 (max); 627 } 628 629 #ifdef DEBUG_SNPRINTF 630 dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); 631 #endif 632 633 /* Convert integer part */ 634 do { 635 iconvert[iplace++] = 636 (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; 637 intpart = (intpart / 10); 638 } while(intpart && (iplace < 20)); 639 if (iplace == 20) iplace--; 640 iconvert[iplace] = 0; 641 642 /* Convert fractional part */ 643 do { 644 fconvert[fplace++] = 645 (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; 646 fracpart = (fracpart / 10); 647 } while(fracpart && (fplace < 20)); 648 if (fplace == 20) fplace--; 649 fconvert[fplace] = 0; 650 651 /* -1 for decimal point, another -1 if we are printing a sign */ 652 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 653 zpadlen = max - fplace; 654 if (zpadlen < 0) 655 zpadlen = 0; 656 if (padlen < 0) 657 padlen = 0; 658 if (flags & DP_F_MINUS) 659 padlen = -padlen; /* Left Justifty */ 660 661 if ((flags & DP_F_ZERO) && (padlen > 0)) 662 { 663 if (signvalue) 664 { 665 total += dopr_outch (buffer, currlen, maxlen, signvalue); 666 --padlen; 667 signvalue = 0; 668 } 669 while (padlen > 0) 670 { 671 total += dopr_outch (buffer, currlen, maxlen, '0'); 672 --padlen; 673 } 674 } 675 while (padlen > 0) 676 { 677 total += dopr_outch (buffer, currlen, maxlen, ' '); 678 --padlen; 679 } 680 if (signvalue) 681 total += dopr_outch (buffer, currlen, maxlen, signvalue); 682 683 while (iplace > 0) 684 total += dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); 685 686 /* 687 * Decimal point. This should probably use locale to find the correct 688 * char to print out. 689 */ 690 if (max > 0) 691 { 692 total += dopr_outch (buffer, currlen, maxlen, '.'); 693 694 while (fplace > 0) 695 total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); 696 } 697 698 while (zpadlen > 0) 699 { 700 total += dopr_outch (buffer, currlen, maxlen, '0'); 701 --zpadlen; 702 } 703 704 while (padlen < 0) 705 { 706 total += dopr_outch (buffer, currlen, maxlen, ' '); 707 ++padlen; 708 } 709 710 return total; 711 } 712 713 static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) 714 { 715 if (*currlen + 1 < maxlen) 716 buffer[(*currlen)++] = c; 717 return 1; 718 } 719 720 #ifndef HAVE_VSNPRINTF 721 int vsnprintf (char *str, size_t count, const char *fmt, va_list args) 722 { 723 if (str != NULL) 724 str[0] = 0; 725 return dopr(str, count, fmt, args); 726 } 727 #endif /* !HAVE_VSNPRINTF */ 728 729 #ifndef HAVE_SNPRINTF 730 /* VARARGS3 */ 731 #ifdef HAVE_STDARGS 732 int snprintf (char *str,size_t count,const char *fmt,...) 733 #else 734 int snprintf (va_alist) va_dcl 735 #endif 736 { 737 #ifndef HAVE_STDARGS 738 char *str; 739 size_t count; 740 char *fmt; 741 #endif 742 VA_LOCAL_DECL; 743 int total; 744 745 VA_START (fmt); 746 VA_SHIFT (str, char *); 747 VA_SHIFT (count, size_t ); 748 VA_SHIFT (fmt, char *); 749 total = vsnprintf(str, count, fmt, ap); 750 VA_END; 751 return total; 752 } 753 #endif /* !HAVE_SNPRINTF */ 754 755 #ifdef TEST_SNPRINTF 756 #ifndef LONG_STRING 757 #define LONG_STRING 1024 758 #endif 759 int main (void) 760 { 761 char buf1[LONG_STRING]; 762 char buf2[LONG_STRING]; 763 char *fp_fmt[] = { 764 "%-1.5f", 765 "%1.5f", 766 "%123.9f", 767 "%10.5f", 768 "% 10.5f", 769 "%+22.9f", 770 "%+4.9f", 771 "%01.3f", 772 "%4f", 773 "%3.1f", 774 "%3.2f", 775 "%.0f", 776 "%.1f", 777 NULL 778 }; 779 double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 780 0.9996, 1.996, 4.136, 0}; 781 char *int_fmt[] = { 782 "%-1.5d", 783 "%1.5d", 784 "%123.9d", 785 "%5.5d", 786 "%10.5d", 787 "% 10.5d", 788 "%+22.33d", 789 "%01.3d", 790 "%4d", 791 NULL 792 }; 793 long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; 794 int x, y; 795 int fail = 0; 796 int num = 0; 797 798 printf ("Testing snprintf format codes against system sprintf...\n"); 799 800 for (x = 0; fp_fmt[x] != NULL ; x++) 801 for (y = 0; fp_nums[y] != 0 ; y++) 802 { 803 snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]); 804 sprintf (buf2, fp_fmt[x], fp_nums[y]); 805 if (strcmp (buf1, buf2)) 806 { 807 printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", 808 fp_fmt[x], buf1, buf2); 809 fail++; 810 } 811 num++; 812 } 813 814 for (x = 0; int_fmt[x] != NULL ; x++) 815 for (y = 0; int_nums[y] != 0 ; y++) 816 { 817 snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]); 818 sprintf (buf2, int_fmt[x], int_nums[y]); 819 if (strcmp (buf1, buf2)) 820 { 821 printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", 822 int_fmt[x], buf1, buf2); 823 fail++; 824 } 825 num++; 826 } 827 printf ("%d tests failed out of %d.\n", fail, num); 828 } 829 #endif /* SNPRINTF_TEST */ 830 831 #endif /* !HAVE_SNPRINTF */ 832 833