net-snmp
5.4.1
|
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 #if HAVE_STDARG_H 00067 # include <stdarg.h> 00068 # define HAVE_STDARGS /* let's hope that works everywhere (mj) */ 00069 # define VA_LOCAL_DECL va_list ap 00070 # define VA_START(f) va_start(ap, f) 00071 # define VA_SHIFT(v,t) ; /* no-op for ANSI */ 00072 # define VA_END va_end(ap) 00073 #elif HAVE_VARARGS_H 00074 # include <varargs.h> 00075 # undef HAVE_STDARGS 00076 # define VA_LOCAL_DECL va_list ap 00077 # define VA_START(f) va_start(ap) /* f is ignored! */ 00078 # define VA_SHIFT(v,t) v = va_arg(ap,t) 00079 # define VA_END va_end(ap) 00080 #else 00081 /* 00082 * XX ** NO VARARGS ** XX 00083 */ 00084 #endif 00085 00086 #ifdef HAVE_LONG_DOUBLE 00087 #define LDOUBLE long double 00088 #else 00089 #define LDOUBLE double 00090 #endif 00091 00092 int snprintf(char *str, size_t count, const char *fmt, ...); 00093 int vsnprintf(char *str, size_t count, const char *fmt, 00094 va_list arg); 00095 00096 static void dopr(char *buffer, size_t maxlen, const char *format, 00097 va_list args); 00098 static void fmtstr(char *buffer, size_t * currlen, size_t maxlen, 00099 char *value, int flags, int min, int max); 00100 static void fmtint(char *buffer, size_t * currlen, size_t maxlen, 00101 long value, int base, int min, int max, int flags); 00102 static void fmtfp(char *buffer, size_t * currlen, size_t maxlen, 00103 LDOUBLE fvalue, int min, int max, int flags); 00104 static void dopr_outch(char *buffer, size_t * currlen, size_t maxlen, 00105 char c); 00106 00107 /* 00108 * dopr(): poor man's version of doprintf 00109 */ 00110 00111 /* 00112 * format read states 00113 */ 00114 #define DP_S_DEFAULT 0 00115 #define DP_S_FLAGS 1 00116 #define DP_S_MIN 2 00117 #define DP_S_DOT 3 00118 #define DP_S_MAX 4 00119 #define DP_S_MOD 5 00120 #define DP_S_CONV 6 00121 #define DP_S_DONE 7 00122 00123 /* 00124 * format flags - Bits 00125 */ 00126 #define DP_F_MINUS (1 << 0) 00127 #define DP_F_PLUS (1 << 1) 00128 #define DP_F_SPACE (1 << 2) 00129 #define DP_F_NUM (1 << 3) 00130 #define DP_F_ZERO (1 << 4) 00131 #define DP_F_UP (1 << 5) 00132 #define DP_F_UNSIGNED (1 << 6) 00133 00134 /* 00135 * Conversion Flags 00136 */ 00137 #define DP_C_SHORT 1 00138 #define DP_C_LONG 2 00139 #define DP_C_LDOUBLE 3 00140 00141 #define char_to_int(p) (p - '0') 00142 #define MAX(p,q) ((p >= q) ? p : q) 00143 00144 static void 00145 dopr(char *buffer, size_t maxlen, const char *format, va_list args) 00146 { 00147 char ch; 00148 long value; 00149 LDOUBLE fvalue; 00150 char *strvalue; 00151 int min; 00152 int max; 00153 int state; 00154 int flags; 00155 int cflags; 00156 size_t currlen; 00157 00158 state = DP_S_DEFAULT; 00159 currlen = flags = cflags = min = 0; 00160 max = -1; 00161 ch = *format++; 00162 00163 while (state != DP_S_DONE) { 00164 if ((ch == '\0') || (currlen >= maxlen)) 00165 state = DP_S_DONE; 00166 00167 switch (state) { 00168 case DP_S_DEFAULT: 00169 if (ch == '%') 00170 state = DP_S_FLAGS; 00171 else 00172 dopr_outch(buffer, &currlen, maxlen, ch); 00173 ch = *format++; 00174 break; 00175 case DP_S_FLAGS: 00176 switch (ch) { 00177 case '-': 00178 flags |= DP_F_MINUS; 00179 ch = *format++; 00180 break; 00181 case '+': 00182 flags |= DP_F_PLUS; 00183 ch = *format++; 00184 break; 00185 case ' ': 00186 flags |= DP_F_SPACE; 00187 ch = *format++; 00188 break; 00189 case '#': 00190 flags |= DP_F_NUM; 00191 ch = *format++; 00192 break; 00193 case '0': 00194 flags |= DP_F_ZERO; 00195 ch = *format++; 00196 break; 00197 default: 00198 state = DP_S_MIN; 00199 break; 00200 } 00201 break; 00202 case DP_S_MIN: 00203 if (isdigit(ch)) { 00204 min = 10 * min + char_to_int(ch); 00205 ch = *format++; 00206 } else if (ch == '*') { 00207 min = va_arg(args, int); 00208 ch = *format++; 00209 state = DP_S_DOT; 00210 } else 00211 state = DP_S_DOT; 00212 break; 00213 case DP_S_DOT: 00214 if (ch == '.') { 00215 state = DP_S_MAX; 00216 ch = *format++; 00217 } else 00218 state = DP_S_MOD; 00219 break; 00220 case DP_S_MAX: 00221 if (isdigit(ch)) { 00222 if (max < 0) 00223 max = 0; 00224 max = 10 * max + char_to_int(ch); 00225 ch = *format++; 00226 } else if (ch == '*') { 00227 max = va_arg(args, int); 00228 ch = *format++; 00229 state = DP_S_MOD; 00230 } else 00231 state = DP_S_MOD; 00232 break; 00233 case DP_S_MOD: 00234 /* 00235 * Currently, we don't support Long Long, bummer 00236 */ 00237 switch (ch) { 00238 case 'h': 00239 cflags = DP_C_SHORT; 00240 ch = *format++; 00241 break; 00242 case 'l': 00243 cflags = DP_C_LONG; 00244 ch = *format++; 00245 break; 00246 case 'L': 00247 cflags = DP_C_LDOUBLE; 00248 ch = *format++; 00249 break; 00250 default: 00251 break; 00252 } 00253 state = DP_S_CONV; 00254 break; 00255 case DP_S_CONV: 00256 switch (ch) { 00257 case 'd': 00258 case 'i': 00259 if (cflags == DP_C_SHORT) 00260 value = va_arg(args, short int); 00261 else if (cflags == DP_C_LONG) 00262 value = va_arg(args, long int); 00263 else 00264 value = va_arg(args, int); 00265 fmtint(buffer, &currlen, maxlen, value, 10, min, max, 00266 flags); 00267 break; 00268 case 'o': 00269 flags |= DP_F_UNSIGNED; 00270 if (cflags == DP_C_SHORT) 00271 value = va_arg(args, unsigned short int); 00272 else if (cflags == DP_C_LONG) 00273 value = va_arg(args, unsigned long int); 00274 else 00275 value = va_arg(args, unsigned int); 00276 fmtint(buffer, &currlen, maxlen, value, 8, min, max, 00277 flags); 00278 break; 00279 case 'u': 00280 flags |= DP_F_UNSIGNED; 00281 if (cflags == DP_C_SHORT) 00282 value = va_arg(args, unsigned short int); 00283 else if (cflags == DP_C_LONG) 00284 value = va_arg(args, unsigned long int); 00285 else 00286 value = va_arg(args, unsigned int); 00287 fmtint(buffer, &currlen, maxlen, value, 10, min, max, 00288 flags); 00289 break; 00290 case 'X': 00291 flags |= DP_F_UP; 00292 case 'x': 00293 flags |= DP_F_UNSIGNED; 00294 if (cflags == DP_C_SHORT) 00295 value = va_arg(args, unsigned short int); 00296 else if (cflags == DP_C_LONG) 00297 value = va_arg(args, unsigned long int); 00298 else 00299 value = va_arg(args, unsigned int); 00300 fmtint(buffer, &currlen, maxlen, value, 16, min, max, 00301 flags); 00302 break; 00303 case 'f': 00304 if (cflags == DP_C_LDOUBLE) 00305 fvalue = va_arg(args, LDOUBLE); 00306 else 00307 fvalue = va_arg(args, double); 00308 /* 00309 * um, floating point? 00310 */ 00311 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); 00312 break; 00313 case 'E': 00314 flags |= DP_F_UP; 00315 case 'e': 00316 if (cflags == DP_C_LDOUBLE) 00317 fvalue = va_arg(args, LDOUBLE); 00318 else 00319 fvalue = va_arg(args, double); 00320 break; 00321 case 'G': 00322 flags |= DP_F_UP; 00323 case 'g': 00324 if (cflags == DP_C_LDOUBLE) 00325 fvalue = va_arg(args, LDOUBLE); 00326 else 00327 fvalue = va_arg(args, double); 00328 break; 00329 case 'c': 00330 dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); 00331 break; 00332 case 's': 00333 strvalue = va_arg(args, char *); 00334 if (max < 0) 00335 max = maxlen; /* ie, no max */ 00336 fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, 00337 max); 00338 break; 00339 case 'p': 00340 strvalue = (char *) va_arg(args, void *); 00341 fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, 00342 max, flags); 00343 break; 00344 case 'n': 00345 if (cflags == DP_C_SHORT) { 00346 short int *num; 00347 num = va_arg(args, short int *); 00348 *num = currlen; 00349 } else if (cflags == DP_C_LONG) { 00350 long int *num; 00351 num = va_arg(args, long int *); 00352 *num = currlen; 00353 } else { 00354 int *num; 00355 num = va_arg(args, int *); 00356 *num = currlen; 00357 } 00358 break; 00359 case '%': 00360 dopr_outch(buffer, &currlen, maxlen, ch); 00361 break; 00362 case 'w': 00363 /* 00364 * not supported yet, treat as next char 00365 */ 00366 ch = *format++; 00367 break; 00368 default: 00369 /* 00370 * Unknown, skip 00371 */ 00372 break; 00373 } 00374 ch = *format++; 00375 state = DP_S_DEFAULT; 00376 flags = cflags = min = 0; 00377 max = -1; 00378 break; 00379 case DP_S_DONE: 00380 break; 00381 default: 00382 /* 00383 * hmm? 00384 */ 00385 break; /* some picky compilers need this */ 00386 } 00387 } 00388 if (currlen < maxlen - 1) 00389 buffer[currlen] = '\0'; 00390 else 00391 buffer[maxlen - 1] = '\0'; 00392 } 00393 00394 static void 00395 fmtstr(char *buffer, size_t * currlen, size_t maxlen, 00396 char *value, int flags, int min, int max) 00397 { 00398 int padlen, strln; /* amount to pad */ 00399 int cnt = 0; 00400 00401 if (value == 0) { 00402 value = "<NULL>"; 00403 } 00404 00405 for (strln = 0; value[strln]; ++strln); /* strlen */ 00406 padlen = min - strln; 00407 if (padlen < 0) 00408 padlen = 0; 00409 if (flags & DP_F_MINUS) 00410 padlen = -padlen; /* Left Justify */ 00411 00412 while ((padlen > 0) && (cnt < max)) { 00413 dopr_outch(buffer, currlen, maxlen, ' '); 00414 --padlen; 00415 ++cnt; 00416 } 00417 while (*value && (cnt < max)) { 00418 dopr_outch(buffer, currlen, maxlen, *value++); 00419 ++cnt; 00420 } 00421 while ((padlen < 0) && (cnt < max)) { 00422 dopr_outch(buffer, currlen, maxlen, ' '); 00423 ++padlen; 00424 ++cnt; 00425 } 00426 } 00427 00428 /* 00429 * Have to handle DP_F_NUM (ie 0x and 0 alternates) 00430 */ 00431 00432 static void 00433 fmtint(char *buffer, size_t * currlen, size_t maxlen, 00434 long value, int base, int min, int max, int flags) 00435 { 00436 int signvalue = 0; 00437 unsigned long uvalue; 00438 char convert[20]; 00439 int place = 0; 00440 int spadlen = 0; /* amount to space pad */ 00441 int zpadlen = 0; /* amount to zero pad */ 00442 int caps = 0; 00443 00444 if (max < 0) 00445 max = 0; 00446 00447 uvalue = value; 00448 00449 if (!(flags & DP_F_UNSIGNED)) { 00450 if (value < 0) { 00451 signvalue = '-'; 00452 uvalue = -value; 00453 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 00454 signvalue = '+'; 00455 else if (flags & DP_F_SPACE) 00456 signvalue = ' '; 00457 } 00458 00459 if (flags & DP_F_UP) 00460 caps = 1; /* Should characters be upper case? */ 00461 00462 do { 00463 convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 00464 [uvalue % (unsigned) base]; 00465 uvalue = (uvalue / (unsigned) base); 00466 } while (uvalue && (place < 20)); 00467 if (place == 20) 00468 place--; 00469 convert[place] = 0; 00470 00471 zpadlen = max - place; 00472 spadlen = min - MAX(max, place) - (signvalue ? 1 : 0); 00473 if (zpadlen < 0) 00474 zpadlen = 0; 00475 if (spadlen < 0) 00476 spadlen = 0; 00477 if (flags & DP_F_ZERO) { 00478 zpadlen = MAX(zpadlen, spadlen); 00479 spadlen = 0; 00480 } 00481 if (flags & DP_F_MINUS) 00482 spadlen = -spadlen; /* Left Justifty */ 00483 00484 #ifdef DEBUG_SNPRINTF 00485 dprint(1, 00486 (debugfile, "zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", 00487 zpadlen, spadlen, min, max, place)); 00488 #endif 00489 00490 /* 00491 * Spaces 00492 */ 00493 while (spadlen > 0) { 00494 dopr_outch(buffer, currlen, maxlen, ' '); 00495 --spadlen; 00496 } 00497 00498 /* 00499 * Sign 00500 */ 00501 if (signvalue) 00502 dopr_outch(buffer, currlen, maxlen, signvalue); 00503 00504 /* 00505 * Zeros 00506 */ 00507 if (zpadlen > 0) { 00508 while (zpadlen > 0) { 00509 dopr_outch(buffer, currlen, maxlen, '0'); 00510 --zpadlen; 00511 } 00512 } 00513 00514 /* 00515 * Digits 00516 */ 00517 while (place > 0) 00518 dopr_outch(buffer, currlen, maxlen, convert[--place]); 00519 00520 /* 00521 * Left Justified spaces 00522 */ 00523 while (spadlen < 0) { 00524 dopr_outch(buffer, currlen, maxlen, ' '); 00525 ++spadlen; 00526 } 00527 } 00528 00529 static LDOUBLE 00530 abs_val(LDOUBLE value) 00531 { 00532 LDOUBLE result = value; 00533 00534 if (value < 0) 00535 result = -value; 00536 00537 return result; 00538 } 00539 00540 static LDOUBLE 00541 pow10(int exp) 00542 { 00543 LDOUBLE result = 1; 00544 00545 while (exp) { 00546 result *= 10; 00547 exp--; 00548 } 00549 00550 return result; 00551 } 00552 00553 static long 00554 round(LDOUBLE value) 00555 { 00556 long intpart; 00557 00558 intpart = value; 00559 value = value - intpart; 00560 if (value >= 0.5) 00561 intpart++; 00562 00563 return intpart; 00564 } 00565 00566 static void 00567 fmtfp(char *buffer, size_t * currlen, size_t maxlen, 00568 LDOUBLE fvalue, int min, int max, int flags) 00569 { 00570 int signvalue = 0; 00571 LDOUBLE ufvalue; 00572 char iconvert[20]; 00573 char fconvert[20]; 00574 int iplace = 0; 00575 int fplace = 0; 00576 int padlen = 0; /* amount to pad */ 00577 int zpadlen = 0; 00578 int caps = 0; 00579 long intpart; 00580 long fracpart; 00581 00582 /* 00583 * AIX manpage says the default is 0, but Solaris says the default 00584 * is 6, and sprintf on AIX defaults to 6 00585 */ 00586 if (max < 0) 00587 max = 6; 00588 00589 ufvalue = abs_val(fvalue); 00590 00591 if (fvalue < 0) 00592 signvalue = '-'; 00593 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 00594 signvalue = '+'; 00595 else if (flags & DP_F_SPACE) 00596 signvalue = ' '; 00597 00598 #if 0 00599 if (flags & DP_F_UP) 00600 caps = 1; /* Should characters be upper case? */ 00601 #endif 00602 00603 intpart = ufvalue; 00604 00605 /* 00606 * Sorry, we only support 9 digits past the decimal because of our 00607 * conversion method 00608 */ 00609 if (max > 9) 00610 max = 9; 00611 00612 /* 00613 * We "cheat" by converting the fractional part to integer by 00614 * * multiplying by a factor of 10 00615 */ 00616 fracpart = round((pow10(max)) * (ufvalue - intpart)); 00617 00618 if (fracpart >= pow10(max)) { 00619 intpart++; 00620 fracpart -= pow10(max); 00621 } 00622 #ifdef DEBUG_SNPRINTF 00623 dprint(1, 00624 (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); 00625 #endif 00626 00627 /* 00628 * Convert integer part 00629 */ 00630 do { 00631 iconvert[iplace++] = 00632 (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10]; 00633 intpart = (intpart / 10); 00634 } while (intpart && (iplace < 20)); 00635 if (iplace == 20) 00636 iplace--; 00637 iconvert[iplace] = 0; 00638 00639 /* 00640 * Convert fractional part 00641 */ 00642 do { 00643 fconvert[fplace++] = 00644 (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 00645 10]; 00646 fracpart = (fracpart / 10); 00647 } while (fracpart && (fplace < 20)); 00648 if (fplace == 20) 00649 fplace--; 00650 fconvert[fplace] = 0; 00651 00652 /* 00653 * -1 for decimal point, another -1 if we are printing a sign 00654 */ 00655 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 00656 zpadlen = max - fplace; 00657 if (zpadlen < 0) 00658 zpadlen = 0; 00659 if (padlen < 0) 00660 padlen = 0; 00661 if (flags & DP_F_MINUS) 00662 padlen = -padlen; /* Left Justifty */ 00663 00664 if ((flags & DP_F_ZERO) && (padlen > 0)) { 00665 if (signvalue) { 00666 dopr_outch(buffer, currlen, maxlen, signvalue); 00667 --padlen; 00668 signvalue = 0; 00669 } 00670 while (padlen > 0) { 00671 dopr_outch(buffer, currlen, maxlen, '0'); 00672 --padlen; 00673 } 00674 } 00675 while (padlen > 0) { 00676 dopr_outch(buffer, currlen, maxlen, ' '); 00677 --padlen; 00678 } 00679 if (signvalue) 00680 dopr_outch(buffer, currlen, maxlen, signvalue); 00681 00682 while (iplace > 0) 00683 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); 00684 00685 /* 00686 * Decimal point. This should probably use locale to find the correct 00687 * char to print out. 00688 */ 00689 if (max > 0) { 00690 dopr_outch(buffer, currlen, maxlen, '.'); 00691 00692 while (fplace > 0) 00693 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); 00694 } 00695 00696 while (zpadlen > 0) { 00697 dopr_outch(buffer, currlen, maxlen, '0'); 00698 --zpadlen; 00699 } 00700 00701 while (padlen < 0) { 00702 dopr_outch(buffer, currlen, maxlen, ' '); 00703 ++padlen; 00704 } 00705 } 00706 00707 static void 00708 dopr_outch(char *buffer, size_t * currlen, size_t maxlen, char c) 00709 { 00710 if (*currlen < maxlen) 00711 buffer[(*currlen)++] = c; 00712 } 00713 00714 #ifndef HAVE_VSNPRINTF 00715 int 00716 vsnprintf(char *str, size_t count, const char *fmt, va_list args) 00717 { 00718 str[0] = 0; 00719 dopr(str, count, fmt, args); 00720 return (strlen(str)); 00721 } 00722 #endif /* !HAVE_VSNPRINTF */ 00723 00724 #ifndef HAVE_SNPRINTF 00725 /* 00726 * VARARGS3 00727 */ 00728 #ifdef HAVE_STDARGS 00729 int 00730 snprintf(char *str, size_t count, const char *fmt, ...) 00731 #else 00732 int 00733 snprintf(va_alist) 00734 va_dcl 00735 #endif 00736 { 00737 #ifndef HAVE_STDARGS 00738 char *str; 00739 size_t count; 00740 char *fmt; 00741 #endif 00742 VA_LOCAL_DECL; 00743 00744 VA_START(fmt); 00745 VA_SHIFT(str, char *); 00746 VA_SHIFT(count, size_t); 00747 VA_SHIFT(fmt, char *); 00748 (void) vsnprintf(str, count, fmt, ap); 00749 VA_END; 00750 return (strlen(str)); 00751 } 00752 #endif /* !HAVE_SNPRINTF */ 00753 00754 #ifdef TEST_SNPRINTF 00755 #ifndef LONG_STRING 00756 #define LONG_STRING 1024 00757 #endif 00758 int 00759 main(void) 00760 { 00761 char buf1[LONG_STRING]; 00762 char buf2[LONG_STRING]; 00763 char *fp_fmt[] = { 00764 "%-1.5f", 00765 "%1.5f", 00766 "%123.9f", 00767 "%10.5f", 00768 "% 10.5f", 00769 "%+22.9f", 00770 "%+4.9f", 00771 "%01.3f", 00772 "%4f", 00773 "%3.1f", 00774 "%3.2f", 00775 "%.0f", 00776 "%.1f", 00777 NULL 00778 }; 00779 double fp_nums[] = 00780 { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, 00781 0.9996, 1.996, 4.136, 0 00782 }; 00783 char *int_fmt[] = { 00784 "%-1.5d", 00785 "%1.5d", 00786 "%123.9d", 00787 "%5.5d", 00788 "%10.5d", 00789 "% 10.5d", 00790 "%+22.33d", 00791 "%01.3d", 00792 "%4d", 00793 NULL 00794 }; 00795 long int_nums[] = { -1, 134, 91340, 341, 0203, 0 }; 00796 int x, y; 00797 int fail = 0; 00798 int num = 0; 00799 00800 printf("Testing snprintf format codes against system sprintf...\n"); 00801 00802 for (x = 0; fp_fmt[x] != NULL; x++) 00803 for (y = 0; fp_nums[y] != 0; y++) { 00804 snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); 00805 sprintf(buf2, fp_fmt[x], fp_nums[y]); 00806 if (strcmp(buf1, buf2)) { 00807 printf 00808 ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", 00809 fp_fmt[x], buf1, buf2); 00810 fail++; 00811 } 00812 num++; 00813 } 00814 00815 for (x = 0; int_fmt[x] != NULL; x++) 00816 for (y = 0; int_nums[y] != 0; y++) { 00817 snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); 00818 sprintf(buf2, int_fmt[x], int_nums[y]); 00819 if (strcmp(buf1, buf2)) { 00820 printf 00821 ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", 00822 int_fmt[x], buf1, buf2); 00823 fail++; 00824 } 00825 num++; 00826 } 00827 printf("%d tests failed out of %d.\n", fail, num); 00828 } 00829 #endif /* SNPRINTF_TEST */ 00830 00831 #endif /* !HAVE_SNPRINTF */