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