net-snmp 5.7
|
00001 /* 00002 * Copyright Patrick Powell 1995 00003 * This code is based on code written by Patrick Powell (papowell@astart.com) 00004 * It may be used for any purpose as long as this notice remains intact 00005 * on all source code distributions 00006 */ 00007 00008 /************************************************************** 00009 * Original: 00010 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 00011 * A bombproof version of doprnt (dopr) included. 00012 * Sigh. This sort of thing is always nasty do deal with. Note that 00013 * the version here does not include floating point... 00014 * 00015 * snprintf() is used instead of sprintf() as it does limit checks 00016 * for string length. This covers a nasty loophole. 00017 * 00018 * The other functions are there to prevent NULL pointers from 00019 * causing nast effects. 00020 * 00021 * More Recently: 00022 * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 00023 * This was ugly. It is still ugly. I opted out of floating point 00024 * numbers, but the formatter understands just about everything 00025 * from the normal C string format, at least as far as I can tell from 00026 * the Solaris 2.5 printf(3S) man page. 00027 * 00028 * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 00029 * Ok, added some minimal floating point support, which means this 00030 * probably requires libm on most operating systems. Don't yet 00031 * support the exponent (e,E) and sigfig (g,G). Also, fmtint() 00032 * was pretty badly broken, it just wasn't being exercised in ways 00033 * which showed it, so that's been fixed. Also, formated the code 00034 * to mutt conventions, and removed dead code left over from the 00035 * original. Also, there is now a builtin-test, just compile with: 00036 * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm 00037 * and run snprintf for results. 00038 * 00039 * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i 00040 * The PGP code was using unsigned hexadecimal formats. 00041 * Unfortunately, unsigned formats simply didn't work. 00042 * 00043 * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 00044 * The original code assumed that both snprintf() and vsnprintf() were 00045 * missing. Some systems only have snprintf() but not vsnprintf(), so 00046 * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. 00047 * 00048 * Andrew Tridgell (tridge@samba.org) Oct 1998 00049 * fixed handling of %.0f 00050 * added test for HAVE_LONG_DOUBLE 00051 * 00052 **************************************************************/ 00053 00054 #include <net-snmp/net-snmp-config.h> 00055 00056 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) 00057 00058 #if HAVE_STRING_H 00059 #include <string.h> 00060 #else 00061 #include <strings.h> 00062 #endif 00063 #include <ctype.h> 00064 #include <sys/types.h> 00065 00066 # include <stdarg.h> 00067 # define VA_LOCAL_DECL va_list ap 00068 # define VA_START(f) va_start(ap, f) 00069 # define VA_SHIFT(v,t) ; /* no-op for ANSI */ 00070 # define VA_END va_end(ap) 00071 00072 #ifdef HAVE_LONG_DOUBLE 00073 #define LDOUBLE long double 00074 #else 00075 #define LDOUBLE double 00076 #endif 00077 00078 int snprintf(char *str, size_t count, const char *fmt, ...); 00079 int vsnprintf(char *str, size_t count, const char *fmt, 00080 va_list arg); 00081 00082 static void dopr(char *buffer, size_t maxlen, const char *format, 00083 va_list args); 00084 static void fmtstr(char *buffer, size_t * currlen, size_t maxlen, 00085 char *value, int flags, int min, int max); 00086 static void fmtint(char *buffer, size_t * currlen, size_t maxlen, 00087 long value, int base, int min, int max, int flags); 00088 static void fmtfp(char *buffer, size_t * currlen, size_t maxlen, 00089 LDOUBLE fvalue, int min, int max, int flags); 00090 static void dopr_outch(char *buffer, size_t * currlen, size_t maxlen, 00091 char c); 00092 00093 /* 00094 * dopr(): poor man's version of doprintf 00095 */ 00096 00097 /* 00098 * format read states 00099 */ 00100 #define DP_S_DEFAULT 0 00101 #define DP_S_FLAGS 1 00102 #define DP_S_MIN 2 00103 #define DP_S_DOT 3 00104 #define DP_S_MAX 4 00105 #define DP_S_MOD 5 00106 #define DP_S_CONV 6 00107 #define DP_S_DONE 7 00108 00109 /* 00110 * format flags - Bits 00111 */ 00112 #define DP_F_MINUS (1 << 0) 00113 #define DP_F_PLUS (1 << 1) 00114 #define DP_F_SPACE (1 << 2) 00115 #define DP_F_NUM (1 << 3) 00116 #define DP_F_ZERO (1 << 4) 00117 #define DP_F_UP (1 << 5) 00118 #define DP_F_UNSIGNED (1 << 6) 00119 00120 /* 00121 * Conversion Flags 00122 */ 00123 #define DP_C_SHORT 1 00124 #define DP_C_LONG 2 00125 #define DP_C_LDOUBLE 3 00126 00127 #define char_to_int(p) (p - '0') 00128 #define MAX(p,q) ((p >= q) ? p : q) 00129 00130 static void 00131 dopr(char *buffer, size_t maxlen, const char *format, va_list args) 00132 { 00133 char ch; 00134 long value; 00135 LDOUBLE fvalue; 00136 char *strvalue; 00137 int min; 00138 int max; 00139 int state; 00140 int flags; 00141 int cflags; 00142 size_t currlen; 00143 00144 state = DP_S_DEFAULT; 00145 currlen = flags = cflags = min = 0; 00146 max = -1; 00147 ch = *format++; 00148 00149 while (state != DP_S_DONE) { 00150 if ((ch == '\0') || (currlen >= maxlen)) 00151 state = DP_S_DONE; 00152 00153 switch (state) { 00154 case DP_S_DEFAULT: 00155 if (ch == '%') 00156 state = DP_S_FLAGS; 00157 else 00158 dopr_outch(buffer, &currlen, maxlen, ch); 00159 ch = *format++; 00160 break; 00161 case DP_S_FLAGS: 00162 switch (ch) { 00163 case '-': 00164 flags |= DP_F_MINUS; 00165 ch = *format++; 00166 break; 00167 case '+': 00168 flags |= DP_F_PLUS; 00169 ch = *format++; 00170 break; 00171 case ' ': 00172 flags |= DP_F_SPACE; 00173 ch = *format++; 00174 break; 00175 case '#': 00176 flags |= DP_F_NUM; 00177 ch = *format++; 00178 break; 00179 case '0': 00180 flags |= DP_F_ZERO; 00181 ch = *format++; 00182 break; 00183 default: 00184 state = DP_S_MIN; 00185 break; 00186 } 00187 break; 00188 case DP_S_MIN: 00189 if (isdigit(ch)) { 00190 min = 10 * min + char_to_int(ch); 00191 ch = *format++; 00192 } else if (ch == '*') { 00193 min = va_arg(args, int); 00194 ch = *format++; 00195 state = DP_S_DOT; 00196 } else 00197 state = DP_S_DOT; 00198 break; 00199 case DP_S_DOT: 00200 if (ch == '.') { 00201 state = DP_S_MAX; 00202 ch = *format++; 00203 } else 00204 state = DP_S_MOD; 00205 break; 00206 case DP_S_MAX: 00207 if (isdigit(ch)) { 00208 if (max < 0) 00209 max = 0; 00210 max = 10 * max + char_to_int(ch); 00211 ch = *format++; 00212 } else if (ch == '*') { 00213 max = va_arg(args, int); 00214 ch = *format++; 00215 state = DP_S_MOD; 00216 } else 00217 state = DP_S_MOD; 00218 break; 00219 case DP_S_MOD: 00220 /* 00221 * Currently, we don't support Long Long, bummer 00222 */ 00223 switch (ch) { 00224 case 'h': 00225 cflags = DP_C_SHORT; 00226 ch = *format++; 00227 break; 00228 case 'l': 00229 cflags = DP_C_LONG; 00230 ch = *format++; 00231 break; 00232 case 'L': 00233 cflags = DP_C_LDOUBLE; 00234 ch = *format++; 00235 break; 00236 default: 00237 break; 00238 } 00239 state = DP_S_CONV; 00240 break; 00241 case DP_S_CONV: 00242 switch (ch) { 00243 case 'd': 00244 case 'i': 00245 if (cflags == DP_C_SHORT) 00246 value = va_arg(args, short int); 00247 else if (cflags == DP_C_LONG) 00248 value = va_arg(args, long int); 00249 else 00250 value = va_arg(args, int); 00251 fmtint(buffer, &currlen, maxlen, value, 10, min, max, 00252 flags); 00253 break; 00254 case 'o': 00255 flags |= DP_F_UNSIGNED; 00256 if (cflags == DP_C_SHORT) 00257 value = va_arg(args, unsigned short int); 00258 else if (cflags == DP_C_LONG) 00259 value = va_arg(args, unsigned long int); 00260 else 00261 value = va_arg(args, unsigned int); 00262 fmtint(buffer, &currlen, maxlen, value, 8, min, max, 00263 flags); 00264 break; 00265 case 'u': 00266 flags |= DP_F_UNSIGNED; 00267 if (cflags == DP_C_SHORT) 00268 value = va_arg(args, unsigned short int); 00269 else if (cflags == DP_C_LONG) 00270 value = va_arg(args, unsigned long int); 00271 else 00272 value = va_arg(args, unsigned int); 00273 fmtint(buffer, &currlen, maxlen, value, 10, min, max, 00274 flags); 00275 break; 00276 case 'X': 00277 flags |= DP_F_UP; 00278 case 'x': 00279 flags |= DP_F_UNSIGNED; 00280 if (cflags == DP_C_SHORT) 00281 value = va_arg(args, unsigned short int); 00282 else if (cflags == DP_C_LONG) 00283 value = va_arg(args, unsigned long int); 00284 else 00285 value = va_arg(args, unsigned int); 00286 fmtint(buffer, &currlen, maxlen, value, 16, min, max, 00287 flags); 00288 break; 00289 case 'f': 00290 if (cflags == DP_C_LDOUBLE) 00291 fvalue = va_arg(args, LDOUBLE); 00292 else 00293 fvalue = va_arg(args, double); 00294 /* 00295 * um, floating point? 00296 */ 00297 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); 00298 break; 00299 case 'E': 00300 flags |= DP_F_UP; 00301 case 'e': 00302 if (cflags == DP_C_LDOUBLE) 00303 fvalue = va_arg(args, LDOUBLE); 00304 else 00305 fvalue = va_arg(args, double); 00306 break; 00307 case 'G': 00308 flags |= DP_F_UP; 00309 case 'g': 00310 if (cflags == DP_C_LDOUBLE) 00311 fvalue = va_arg(args, LDOUBLE); 00312 else 00313 fvalue = va_arg(args, double); 00314 break; 00315 case 'c': 00316 dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); 00317 break; 00318 case 's': 00319 strvalue = va_arg(args, char *); 00320 if (max < 0) 00321 max = maxlen; /* ie, no max */ 00322 fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, 00323 max); 00324 break; 00325 case 'p': 00326 strvalue = (char *) va_arg(args, void *); 00327 fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, 00328 max, flags); 00329 break; 00330 case 'n': 00331 if (cflags == DP_C_SHORT) { 00332 short int *num; 00333 num = va_arg(args, short int *); 00334 *num = currlen; 00335 } else if (cflags == DP_C_LONG) { 00336 long int *num; 00337 num = va_arg(args, long int *); 00338 *num = currlen; 00339 } else { 00340 int *num; 00341 num = va_arg(args, int *); 00342 *num = currlen; 00343 } 00344 break; 00345 case '%': 00346 dopr_outch(buffer, &currlen, maxlen, ch); 00347 break; 00348 case 'w': 00349 /* 00350 * not supported yet, treat as next char 00351 */ 00352 ch = *format++; 00353 break; 00354 default: 00355 /* 00356 * Unknown, skip 00357 */ 00358 break; 00359 } 00360 ch = *format++; 00361 state = DP_S_DEFAULT; 00362 flags = cflags = min = 0; 00363 max = -1; 00364 break; 00365 case DP_S_DONE: 00366 break; 00367 default: 00368 /* 00369 * hmm? 00370 */ 00371 break; /* some picky compilers need this */ 00372 } 00373 } 00374 if (currlen < maxlen - 1) 00375 buffer[currlen] = '\0'; 00376 else 00377 buffer[maxlen - 1] = '\0'; 00378 } 00379 00380 static void 00381 fmtstr(char *buffer, size_t * currlen, size_t maxlen, 00382 char *value, int flags, int min, int max) 00383 { 00384 int padlen, strln; /* amount to pad */ 00385 int cnt = 0; 00386 00387 if (value == 0) { 00388 value = "<NULL>"; 00389 } 00390 00391 for (strln = 0; value[strln]; ++strln); /* strlen */ 00392 padlen = min - strln; 00393 if (padlen < 0) 00394 padlen = 0; 00395 if (flags & DP_F_MINUS) 00396 padlen = -padlen; /* Left Justify */ 00397 00398 while ((padlen > 0) && (cnt < max)) { 00399 dopr_outch(buffer, currlen, maxlen, ' '); 00400 --padlen; 00401 ++cnt; 00402 } 00403 while (*value && (cnt < max)) { 00404 dopr_outch(buffer, currlen, maxlen, *value++); 00405 ++cnt; 00406 } 00407 while ((padlen < 0) && (cnt < max)) { 00408 dopr_outch(buffer, currlen, maxlen, ' '); 00409 ++padlen; 00410 ++cnt; 00411 } 00412 } 00413 00414 /* 00415 * Have to handle DP_F_NUM (ie 0x and 0 alternates) 00416 */ 00417 00418 static void 00419 fmtint(char *buffer, size_t * currlen, size_t maxlen, 00420 long value, int base, int min, int max, int flags) 00421 { 00422 int signvalue = 0; 00423 unsigned long uvalue; 00424 char convert[20]; 00425 int place = 0; 00426 int spadlen = 0; /* amount to space pad */ 00427 int zpadlen = 0; /* amount to zero pad */ 00428 int caps = 0; 00429 00430 if (max < 0) 00431 max = 0; 00432 00433 uvalue = value; 00434 00435 if (!(flags & DP_F_UNSIGNED)) { 00436 if (value < 0) { 00437 signvalue = '-'; 00438 uvalue = -value; 00439 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 00440 signvalue = '+'; 00441 else if (flags & DP_F_SPACE) 00442 signvalue = ' '; 00443 } 00444 00445 if (flags & DP_F_UP) 00446 caps = 1; /* Should characters be upper case? */ 00447 00448 do { 00449 convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 00450 [uvalue % (unsigned) base]; 00451 uvalue = (uvalue / (unsigned) base); 00452 } while (uvalue && (place < 20)); 00453 if (place == 20) 00454 place--; 00455 convert[place] = 0; 00456 00457 zpadlen = max - place; 00458 spadlen = min - MAX(max, place) - (signvalue ? 1 : 0); 00459 if (zpadlen < 0) 00460 zpadlen = 0; 00461 if (spadlen < 0) 00462 spadlen = 0; 00463 if (flags & DP_F_ZERO) { 00464 zpadlen = MAX(zpadlen, spadlen); 00465 spadlen = 0; 00466 } 00467 if (flags & DP_F_MINUS) 00468 spadlen = -spadlen; /* Left Justifty */ 00469 00470 #ifdef DEBUG_SNPRINTF 00471 dprint(1, 00472 (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", 00473 zpadlen, spadlen, min, max, place)); 00474 #endif 00475 00476 /* 00477 * Spaces 00478 */ 00479 while (spadlen > 0) { 00480 dopr_outch(buffer, currlen, maxlen, ' '); 00481 --spadlen; 00482 } 00483 00484 /* 00485 * Sign 00486 */ 00487 if (signvalue) 00488 dopr_outch(buffer, currlen, maxlen, signvalue); 00489 00490 /* 00491 * Zeros 00492 */ 00493 if (zpadlen > 0) { 00494 while (zpadlen > 0) { 00495 dopr_outch(buffer, currlen, maxlen, '0'); 00496 --zpadlen; 00497 } 00498 } 00499 00500 /* 00501 * Digits 00502 */ 00503 while (place > 0) 00504 dopr_outch(buffer, currlen, maxlen, convert[--place]); 00505 00506 /* 00507 * Left Justified spaces 00508 */ 00509 while (spadlen < 0) { 00510 dopr_outch(buffer, currlen, maxlen, ' '); 00511 ++spadlen; 00512 } 00513 } 00514 00515 static LDOUBLE 00516 abs_val(LDOUBLE value) 00517 { 00518 LDOUBLE result = value; 00519 00520 if (value < 0) 00521 result = -value; 00522 00523 return result; 00524 } 00525 00526 static LDOUBLE 00527 pow10(int exp) 00528 { 00529 LDOUBLE result = 1; 00530 00531 while (exp) { 00532 result *= 10; 00533 exp--; 00534 } 00535 00536 return result; 00537 } 00538 00539 static long 00540 round(LDOUBLE value) 00541 { 00542 long intpart; 00543 00544 intpart = value; 00545 value = value - intpart; 00546 if (value >= 0.5) 00547 intpart++; 00548 00549 return intpart; 00550 } 00551 00552 static void 00553 fmtfp(char *buffer, size_t * currlen, size_t maxlen, 00554 LDOUBLE fvalue, int min, int max, int flags) 00555 { 00556 int signvalue = 0; 00557 LDOUBLE ufvalue; 00558 char iconvert[20]; 00559 char fconvert[20]; 00560 int iplace = 0; 00561 int fplace = 0; 00562 int padlen = 0; /* amount to pad */ 00563 int zpadlen = 0; 00564 int caps = 0; 00565 long intpart; 00566 long fracpart; 00567 00568 /* 00569 * AIX manpage says the default is 0, but Solaris says the default 00570 * is 6, and sprintf on AIX defaults to 6 00571 */ 00572 if (max < 0) 00573 max = 6; 00574 00575 ufvalue = abs_val(fvalue); 00576 00577 if (fvalue < 0) 00578 signvalue = '-'; 00579 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 00580 signvalue = '+'; 00581 else if (flags & DP_F_SPACE) 00582 signvalue = ' '; 00583 00584 #if 0 00585 if (flags & DP_F_UP) 00586 caps = 1; /* Should characters be upper case? */ 00587 #endif 00588 00589 intpart = ufvalue; 00590 00591 /* 00592 * Sorry, we only support 9 digits past the decimal because of our 00593 * conversion method 00594 */ 00595 if (max > 9) 00596 max = 9; 00597 00598 /* 00599 * We "cheat" by converting the fractional part to integer by 00600 * * multiplying by a factor of 10 00601 */ 00602 fracpart = round((pow10(max)) * (ufvalue - intpart)); 00603 00604 if (fracpart >= pow10(max)) { 00605 intpart++; 00606 fracpart -= pow10(max); 00607 } 00608 #ifdef DEBUG_SNPRINTF 00609 dprint(1, 00610 (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); 00611 #endif 00612 00613 /* 00614 * Convert integer part 00615 */ 00616 do { 00617 iconvert[iplace++] = 00618 (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10]; 00619 intpart = (intpart / 10); 00620 } while (intpart && (iplace < 20)); 00621 if (iplace == 20) 00622 iplace--; 00623 iconvert[iplace] = 0; 00624 00625 /* 00626 * Convert fractional part 00627 */ 00628 do { 00629 fconvert[fplace++] = 00630 (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 00631 10]; 00632 fracpart = (fracpart / 10); 00633 } while (fracpart && (fplace < 20)); 00634 if (fplace == 20) 00635 fplace--; 00636 fconvert[fplace] = 0; 00637 00638 /* 00639 * -1 for decimal point, another -1 if we are printing a sign 00640 */ 00641 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 00642 zpadlen = max - fplace; 00643 if (zpadlen < 0) 00644 zpadlen = 0; 00645 if (padlen < 0) 00646 padlen = 0; 00647 if (flags & DP_F_MINUS) 00648 padlen = -padlen; /* Left Justifty */ 00649 00650 if ((flags & DP_F_ZERO) && (padlen > 0)) { 00651 if (signvalue) { 00652 dopr_outch(buffer, currlen, maxlen, signvalue); 00653 --padlen; 00654 signvalue = 0; 00655 } 00656 while (padlen > 0) { 00657 dopr_outch(buffer, currlen, maxlen, '0'); 00658 --padlen; 00659 } 00660 } 00661 while (padlen > 0) { 00662 dopr_outch(buffer, currlen, maxlen, ' '); 00663 --padlen; 00664 } 00665 if (signvalue) 00666 dopr_outch(buffer, currlen, maxlen, signvalue); 00667 00668 while (iplace > 0) 00669 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); 00670 00671 /* 00672 * Decimal point. This should probably use locale to find the correct 00673 * char to print out. 00674 */ 00675 if (max > 0) { 00676 dopr_outch(buffer, currlen, maxlen, '.'); 00677 00678 while (fplace > 0) 00679 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); 00680 } 00681 00682 while (zpadlen > 0) { 00683 dopr_outch(buffer, currlen, maxlen, '0'); 00684 --zpadlen; 00685 } 00686 00687 while (padlen < 0) { 00688 dopr_outch(buffer, currlen, maxlen, ' '); 00689 ++padlen; 00690 } 00691 } 00692 00693 static void 00694 dopr_outch(char *buffer, size_t * currlen, size_t maxlen, char c) 00695 { 00696 if (*currlen < maxlen) 00697 buffer[(*currlen)++] = c; 00698 } 00699 00700 #ifndef HAVE_VSNPRINTF 00701 int 00702 vsnprintf(char *str, size_t count, const char *fmt, va_list args) 00703 { 00704 str[0] = 0; 00705 dopr(str, count, fmt, args); 00706 return (strlen(str)); 00707 } 00708 #endif /* !HAVE_VSNPRINTF */ 00709 00710 #ifndef HAVE_SNPRINTF 00711 /* 00712 * VARARGS3 00713 */ 00714 int 00715 snprintf(char *str, size_t count, const char *fmt, ...) 00716 { 00717 VA_LOCAL_DECL; 00718 00719 VA_START(fmt); 00720 VA_SHIFT(str, char *); 00721 VA_SHIFT(count, size_t); 00722 VA_SHIFT(fmt, char *); 00723 (void) vsnprintf(str, count, fmt, ap); 00724 VA_END; 00725 return (strlen(str)); 00726 } 00727 #endif /* !HAVE_SNPRINTF */ 00728 00729 #ifdef TEST_SNPRINTF 00730 #ifndef LONG_STRING 00731 #define LONG_STRING 1024 00732 #endif 00733 int 00734 main(void) 00735 { 00736 char buf1[LONG_STRING]; 00737 char buf2[LONG_STRING]; 00738 char *fp_fmt[] = { 00739 "%-1.5f", 00740 "%1.5f", 00741 "%123.9f", 00742 "%10.5f", 00743 "% 10.5f", 00744 "%+22.9f", 00745 "%+4.9f", 00746 "%01.3f", 00747 "%4f", 00748 "%3.1f", 00749 "%3.2f", 00750 "%.0f", 00751 "%.1f", 00752 NULL 00753 }; 00754 double fp_nums[] = 00755 { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 00756 0.9996, 1.996, 4.136, 0 00757 }; 00758 char *int_fmt[] = { 00759 "%-1.5d", 00760 "%1.5d", 00761 "%123.9d", 00762 "%5.5d", 00763 "%10.5d", 00764 "% 10.5d", 00765 "%+22.33d", 00766 "%01.3d", 00767 "%4d", 00768 NULL 00769 }; 00770 long int_nums[] = { -1, 134, 91340, 341, 0203, 0 }; 00771 int x, y; 00772 int fail = 0; 00773 int num = 0; 00774 00775 printf("Testing snprintf format codes against system sprintf...\n"); 00776 00777 for (x = 0; fp_fmt[x] != NULL; x++) 00778 for (y = 0; fp_nums[y] != 0; y++) { 00779 snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); 00780 sprintf(buf2, fp_fmt[x], fp_nums[y]); 00781 if (strcmp(buf1, buf2)) { 00782 printf 00783 ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", 00784 fp_fmt[x], buf1, buf2); 00785 fail++; 00786 } 00787 num++; 00788 } 00789 00790 for (x = 0; int_fmt[x] != NULL; x++) 00791 for (y = 0; int_nums[y] != 0; y++) { 00792 snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); 00793 sprintf(buf2, int_fmt[x], int_nums[y]); 00794 if (strcmp(buf1, buf2)) { 00795 printf 00796 ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", 00797 int_fmt[x], buf1, buf2); 00798 fail++; 00799 } 00800 num++; 00801 } 00802 printf("%d tests failed out of %d.\n", fail, num); 00803 } 00804 #endif /* SNPRINTF_TEST */ 00805 00806 #else 00807 int snprintf_unused; /* Suppress "empty translation unit" warning */ 00808 #endif /* !HAVE_SNPRINTF */