00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #ifndef NO_CONFIG_H
00095 #include "config.h"
00096 #else
00097 #define NULL 0
00098 #endif
00099
00100 #ifdef TEST_SNPRINTF
00101
00102
00103
00104 # undef HAVE_SNPRINTF
00105 # undef HAVE_VSNPRINTF
00106 # undef HAVE_C99_VSNPRINTF
00107 # undef HAVE_ASPRINTF
00108 # undef HAVE_VASPRINTF
00109 # include <math.h>
00110 #endif
00111
00112 #ifdef HAVE_STRING_H
00113 #include <string.h>
00114 #endif
00115
00116 #ifdef HAVE_STRINGS_H
00117 #include <strings.h>
00118 #endif
00119 #ifdef HAVE_CTYPE_H
00120 #include <ctype.h>
00121 #endif
00122 #include <sys/types.h>
00123 #include <stdarg.h>
00124 #ifdef HAVE_STDLIB_H
00125 #include <stdlib.h>
00126 #endif
00127
00128 #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
00129
00130 #include <stdio.h>
00131
00132 void dummy_snprintf(void);
00133 void dummy_snprintf(void) {}
00134 #endif
00135
00136 #ifdef HAVE_LONG_DOUBLE
00137 #define LDOUBLE long double
00138 #else
00139 #define LDOUBLE double
00140 #endif
00141
00142 #if SIZEOF_LONG_LONG
00143 #define LLONG long long
00144 #else
00145 #define LLONG long
00146 #endif
00147
00148 #ifndef VA_COPY
00149 #if defined HAVE_VA_COPY || defined va_copy
00150 #define VA_COPY(dest, src) va_copy(dest, src)
00151 #else
00152 #ifdef HAVE___VA_COPY
00153 #define VA_COPY(dest, src) __va_copy(dest, src)
00154 #else
00155 #define VA_COPY(dest, src) (dest) = (src)
00156 #endif
00157 #endif
00158
00159
00160
00161
00162
00163
00164 #define DP_S_DEFAULT 0
00165 #define DP_S_FLAGS 1
00166 #define DP_S_MIN 2
00167 #define DP_S_DOT 3
00168 #define DP_S_MAX 4
00169 #define DP_S_MOD 5
00170 #define DP_S_CONV 6
00171 #define DP_S_DONE 7
00172
00173
00174 #define DP_F_MINUS (1 << 0)
00175 #define DP_F_PLUS (1 << 1)
00176 #define DP_F_SPACE (1 << 2)
00177 #define DP_F_NUM (1 << 3)
00178 #define DP_F_ZERO (1 << 4)
00179 #define DP_F_UP (1 << 5)
00180 #define DP_F_UNSIGNED (1 << 6)
00181
00182
00183 #define DP_C_SHORT 1
00184 #define DP_C_LONG 2
00185 #define DP_C_LDOUBLE 3
00186 #define DP_C_LLONG 4
00187
00188 #define char_to_int(p) ((p)- '0')
00189 #ifndef MAX
00190 #define MAX(p,q) (((p) >= (q)) ? (p) : (q))
00191 #endif
00192
00193
00194 #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
00195
00196 static size_t dopr(char *buffer, size_t maxlen, const char *format,
00197 va_list args_in);
00198 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
00199 char *value, int flags, int min, int max);
00200 static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
00201 long value, int base, int min, int max, int flags);
00202 static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
00203 LDOUBLE fvalue, int min, int max, int flags);
00204 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
00205
00206 static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
00207 {
00208 char ch;
00209 LLONG value;
00210 LDOUBLE fvalue;
00211 char *strvalue;
00212 int min;
00213 int max;
00214 int state;
00215 int flags;
00216 int cflags;
00217 size_t currlen;
00218 va_list args;
00219
00220 VA_COPY(args, args_in);
00221
00222 state = DP_S_DEFAULT;
00223 currlen = flags = cflags = min = 0;
00224 max = -1;
00225 ch = *format++;
00226
00227 while (state != DP_S_DONE) {
00228 if (ch == '\0')
00229 state = DP_S_DONE;
00230
00231 switch(state) {
00232 case DP_S_DEFAULT:
00233 if (ch == '%')
00234 state = DP_S_FLAGS;
00235 else
00236 dopr_outch (buffer, &currlen, maxlen, ch);
00237 ch = *format++;
00238 break;
00239 case DP_S_FLAGS:
00240 switch (ch) {
00241 case '-':
00242 flags |= DP_F_MINUS;
00243 ch = *format++;
00244 break;
00245 case '+':
00246 flags |= DP_F_PLUS;
00247 ch = *format++;
00248 break;
00249 case ' ':
00250 flags |= DP_F_SPACE;
00251 ch = *format++;
00252 break;
00253 case '#':
00254 flags |= DP_F_NUM;
00255 ch = *format++;
00256 break;
00257 case '0':
00258 flags |= DP_F_ZERO;
00259 ch = *format++;
00260 break;
00261 default:
00262 state = DP_S_MIN;
00263 break;
00264 }
00265 break;
00266 case DP_S_MIN:
00267 if (isdigit((unsigned char)ch)) {
00268 min = 10*min + char_to_int (ch);
00269 ch = *format++;
00270 } else if (ch == '*') {
00271 min = va_arg (args, int);
00272 ch = *format++;
00273 state = DP_S_DOT;
00274 } else {
00275 state = DP_S_DOT;
00276 }
00277 break;
00278 case DP_S_DOT:
00279 if (ch == '.') {
00280 state = DP_S_MAX;
00281 ch = *format++;
00282 } else {
00283 state = DP_S_MOD;
00284 }
00285 break;
00286 case DP_S_MAX:
00287 if (isdigit((unsigned char)ch)) {
00288 if (max < 0)
00289 max = 0;
00290 max = 10*max + char_to_int (ch);
00291 ch = *format++;
00292 } else if (ch == '*') {
00293 max = va_arg (args, int);
00294 ch = *format++;
00295 state = DP_S_MOD;
00296 } else {
00297 state = DP_S_MOD;
00298 }
00299 break;
00300 case DP_S_MOD:
00301 switch (ch) {
00302 case 'h':
00303 cflags = DP_C_SHORT;
00304 ch = *format++;
00305 break;
00306 case 'l':
00307 cflags = DP_C_LONG;
00308 ch = *format++;
00309 if (ch == 'l') {
00310 cflags = DP_C_LLONG;
00311 ch = *format++;
00312 }
00313 break;
00314 case 'L':
00315 cflags = DP_C_LDOUBLE;
00316 ch = *format++;
00317 break;
00318 default:
00319 break;
00320 }
00321 state = DP_S_CONV;
00322 break;
00323 case DP_S_CONV:
00324 switch (ch) {
00325 case 'd':
00326 case 'i':
00327 if (cflags == DP_C_SHORT)
00328 value = va_arg (args, int);
00329 else if (cflags == DP_C_LONG)
00330 value = va_arg (args, long int);
00331 else if (cflags == DP_C_LLONG)
00332 value = va_arg (args, LLONG);
00333 else
00334 value = va_arg (args, int);
00335 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
00336 break;
00337 case 'o':
00338 flags |= DP_F_UNSIGNED;
00339 if (cflags == DP_C_SHORT)
00340 value = va_arg (args, unsigned int);
00341 else if (cflags == DP_C_LONG)
00342 value = (long)va_arg (args, unsigned long int);
00343 else if (cflags == DP_C_LLONG)
00344 value = (long)va_arg (args, unsigned LLONG);
00345 else
00346 value = (long)va_arg (args, unsigned int);
00347 fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
00348 break;
00349 case 'u':
00350 flags |= DP_F_UNSIGNED;
00351 if (cflags == DP_C_SHORT)
00352 value = va_arg (args, unsigned int);
00353 else if (cflags == DP_C_LONG)
00354 value = (long)va_arg (args, unsigned long int);
00355 else if (cflags == DP_C_LLONG)
00356 value = (LLONG)va_arg (args, unsigned LLONG);
00357 else
00358 value = (long)va_arg (args, unsigned int);
00359 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
00360 break;
00361 case 'X':
00362 flags |= DP_F_UP;
00363 case 'x':
00364 flags |= DP_F_UNSIGNED;
00365 if (cflags == DP_C_SHORT)
00366 value = va_arg (args, unsigned int);
00367 else if (cflags == DP_C_LONG)
00368 value = (long)va_arg (args, unsigned long int);
00369 else if (cflags == DP_C_LLONG)
00370 value = (LLONG)va_arg (args, unsigned LLONG);
00371 else
00372 value = (long)va_arg (args, unsigned int);
00373 fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
00374 break;
00375 case 'f':
00376 if (cflags == DP_C_LDOUBLE)
00377 fvalue = va_arg (args, LDOUBLE);
00378 else
00379 fvalue = va_arg (args, double);
00380
00381 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
00382 break;
00383 case 'E':
00384 flags |= DP_F_UP;
00385 case 'e':
00386 if (cflags == DP_C_LDOUBLE)
00387 fvalue = va_arg (args, LDOUBLE);
00388 else
00389 fvalue = va_arg (args, double);
00390 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
00391 break;
00392 case 'G':
00393 flags |= DP_F_UP;
00394 case 'g':
00395 if (cflags == DP_C_LDOUBLE)
00396 fvalue = va_arg (args, LDOUBLE);
00397 else
00398 fvalue = va_arg (args, double);
00399 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
00400 break;
00401 case 'c':
00402 dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
00403 break;
00404 case 's':
00405 strvalue = va_arg (args, char *);
00406 if (!strvalue) strvalue = "(NULL)";
00407 if (max == -1) {
00408 max = strlen(strvalue);
00409 }
00410 if (min > 0 && max >= 0 && min > max) max = min;
00411 fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
00412 break;
00413 case 'p':
00414 strvalue = va_arg (args, void *);
00415 fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
00416 break;
00417 case 'n':
00418 if (cflags == DP_C_SHORT) {
00419 short int *num;
00420 num = va_arg (args, short int *);
00421 *num = currlen;
00422 } else if (cflags == DP_C_LONG) {
00423 long int *num;
00424 num = va_arg (args, long int *);
00425 *num = (long int)currlen;
00426 } else if (cflags == DP_C_LLONG) {
00427 LLONG *num;
00428 num = va_arg (args, LLONG *);
00429 *num = (LLONG)currlen;
00430 } else {
00431 int *num;
00432 num = va_arg (args, int *);
00433 *num = currlen;
00434 }
00435 break;
00436 case '%':
00437 dopr_outch (buffer, &currlen, maxlen, ch);
00438 break;
00439 case 'w':
00440
00441 ch = *format++;
00442 break;
00443 default:
00444
00445 break;
00446 }
00447 ch = *format++;
00448 state = DP_S_DEFAULT;
00449 flags = cflags = min = 0;
00450 max = -1;
00451 break;
00452 case DP_S_DONE:
00453 break;
00454 default:
00455
00456 break;
00457 }
00458 }
00459 if (maxlen != 0) {
00460 if (currlen < maxlen - 1)
00461 buffer[currlen] = '\0';
00462 else if (maxlen > 0)
00463 buffer[maxlen - 1] = '\0';
00464 }
00465
00466 return currlen;
00467 }
00468
00469 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
00470 char *value, int flags, int min, int max)
00471 {
00472 int padlen, strln;
00473 int cnt = 0;
00474
00475 #ifdef DEBUG_SNPRINTF
00476 printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
00477 #endif
00478 if (value == 0) {
00479 value = "<NULL>";
00480 }
00481
00482 for (strln = 0; value[strln]; ++strln);
00483 padlen = min - strln;
00484 if (padlen < 0)
00485 padlen = 0;
00486 if (flags & DP_F_MINUS)
00487 padlen = -padlen;
00488
00489 while ((padlen > 0) && (cnt < max)) {
00490 dopr_outch (buffer, currlen, maxlen, ' ');
00491 --padlen;
00492 ++cnt;
00493 }
00494 while (*value && (cnt < max)) {
00495 dopr_outch (buffer, currlen, maxlen, *value++);
00496 ++cnt;
00497 }
00498 while ((padlen < 0) && (cnt < max)) {
00499 dopr_outch (buffer, currlen, maxlen, ' ');
00500 ++padlen;
00501 ++cnt;
00502 }
00503 }
00504
00505
00506
00507 static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
00508 long value, int base, int min, int max, int flags)
00509 {
00510 int signvalue = 0;
00511 unsigned long uvalue;
00512 char convert[20];
00513 int place = 0;
00514 int spadlen = 0;
00515 int zpadlen = 0;
00516 int caps = 0;
00517
00518 if (max < 0)
00519 max = 0;
00520
00521 uvalue = value;
00522
00523 if(!(flags & DP_F_UNSIGNED)) {
00524 if( value < 0 ) {
00525 signvalue = '-';
00526 uvalue = -value;
00527 } else {
00528 if (flags & DP_F_PLUS)
00529 signvalue = '+';
00530 else if (flags & DP_F_SPACE)
00531 signvalue = ' ';
00532 }
00533 }
00534
00535 if (flags & DP_F_UP) caps = 1;
00536
00537 do {
00538 convert[place++] =
00539 (caps? "0123456789ABCDEF":"0123456789abcdef")
00540 [uvalue % (unsigned)base ];
00541 uvalue = (uvalue / (unsigned)base );
00542 } while(uvalue && (place < 20));
00543 if (place == 20) place--;
00544 convert[place] = 0;
00545
00546 zpadlen = max - place;
00547 spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
00548 if (zpadlen < 0) zpadlen = 0;
00549 if (spadlen < 0) spadlen = 0;
00550 if (flags & DP_F_ZERO) {
00551 zpadlen = MAX(zpadlen, spadlen);
00552 spadlen = 0;
00553 }
00554 if (flags & DP_F_MINUS)
00555 spadlen = -spadlen;
00556
00557 #ifdef DEBUG_SNPRINTF
00558 printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
00559 zpadlen, spadlen, min, max, place);
00560 #endif
00561
00562
00563 while (spadlen > 0) {
00564 dopr_outch (buffer, currlen, maxlen, ' ');
00565 --spadlen;
00566 }
00567
00568
00569 if (signvalue)
00570 dopr_outch (buffer, currlen, maxlen, signvalue);
00571
00572
00573 if (zpadlen > 0) {
00574 while (zpadlen > 0) {
00575 dopr_outch (buffer, currlen, maxlen, '0');
00576 --zpadlen;
00577 }
00578 }
00579
00580
00581 while (place > 0)
00582 dopr_outch (buffer, currlen, maxlen, convert[--place]);
00583
00584
00585 while (spadlen < 0) {
00586 dopr_outch (buffer, currlen, maxlen, ' ');
00587 ++spadlen;
00588 }
00589 }
00590
00591 static LDOUBLE abs_val(LDOUBLE value)
00592 {
00593 LDOUBLE result = value;
00594
00595 if (value < 0)
00596 result = -value;
00597
00598 return result;
00599 }
00600
00601 static LDOUBLE POW10(int exp)
00602 {
00603 LDOUBLE result = 1;
00604
00605 while (exp) {
00606 result *= 10;
00607 exp--;
00608 }
00609
00610 return result;
00611 }
00612
00613 static LLONG ROUND(LDOUBLE value)
00614 {
00615 LLONG intpart;
00616
00617 intpart = (LLONG)value;
00618 value = value - intpart;
00619 if (value >= 0.5) intpart++;
00620
00621 return intpart;
00622 }
00623
00624
00625
00626 static double my_modf(double x0, double *iptr)
00627 {
00628 int i;
00629 long l;
00630 double x = x0;
00631 double f = 1.0;
00632
00633 for (i=0;i<100;i++) {
00634 l = (long)x;
00635 if (l <= (x+1) && l >= (x-1)) {
00636 if (i != 0) {
00637 double i2;
00638 double ret;
00639
00640 ret = my_modf(x0-l*f, &i2);
00641 (*iptr) = l*f + i2;
00642 return ret;
00643 }
00644
00645 (*iptr) = l;
00646 return x - (*iptr);
00647 }
00648 x *= 0.1;
00649 f *= 10.0;
00650 }
00651
00652
00653 (*iptr) = 0;
00654 return 0;
00655 }
00656
00657
00658 static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
00659 LDOUBLE fvalue, int min, int max, int flags)
00660 {
00661 int signvalue = 0;
00662 double ufvalue;
00663 char iconvert[311];
00664 char fconvert[311];
00665 int iplace = 0;
00666 int fplace = 0;
00667 int padlen = 0;
00668 int zpadlen = 0;
00669 int caps = 0;
00670 int idx;
00671 double intpart;
00672 double fracpart;
00673 double temp;
00674
00675
00676
00677
00678
00679 if (max < 0)
00680 max = 6;
00681
00682 ufvalue = abs_val (fvalue);
00683
00684 if (fvalue < 0) {
00685 signvalue = '-';
00686 } else {
00687 if (flags & DP_F_PLUS) {
00688 signvalue = '+';
00689 } else {
00690 if (flags & DP_F_SPACE)
00691 signvalue = ' ';
00692 }
00693 }
00694
00695 #if 0
00696 if (flags & DP_F_UP) caps = 1;
00697 #endif
00698
00699 #if 0
00700 if (max == 0) ufvalue += 0.5;
00701 #endif
00702
00703
00704
00705
00706
00707 if (max > 16)
00708 max = 16;
00709
00710
00711
00712
00713
00714 temp = ufvalue;
00715 my_modf(temp, &intpart);
00716
00717 fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
00718
00719 if (fracpart >= POW10(max)) {
00720 intpart++;
00721 fracpart -= POW10(max);
00722 }
00723
00724
00725
00726 do {
00727 temp = intpart*0.1;
00728 my_modf(temp, &intpart);
00729 idx = (int) ((temp -intpart +0.05)* 10.0);
00730
00731
00732 iconvert[iplace++] =
00733 (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
00734 } while (intpart && (iplace < 311));
00735 if (iplace == 311) iplace--;
00736 iconvert[iplace] = 0;
00737
00738
00739 if (fracpart)
00740 {
00741 do {
00742 temp = fracpart*0.1;
00743 my_modf(temp, &fracpart);
00744 idx = (int) ((temp -fracpart +0.05)* 10.0);
00745
00746
00747 fconvert[fplace++] =
00748 (caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
00749 } while(fracpart && (fplace < 311));
00750 if (fplace == 311) fplace--;
00751 }
00752 fconvert[fplace] = 0;
00753
00754
00755 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
00756 zpadlen = max - fplace;
00757 if (zpadlen < 0) zpadlen = 0;
00758 if (padlen < 0)
00759 padlen = 0;
00760 if (flags & DP_F_MINUS)
00761 padlen = -padlen;
00762
00763 if ((flags & DP_F_ZERO) && (padlen > 0)) {
00764 if (signvalue) {
00765 dopr_outch (buffer, currlen, maxlen, signvalue);
00766 --padlen;
00767 signvalue = 0;
00768 }
00769 while (padlen > 0) {
00770 dopr_outch (buffer, currlen, maxlen, '0');
00771 --padlen;
00772 }
00773 }
00774 while (padlen > 0) {
00775 dopr_outch (buffer, currlen, maxlen, ' ');
00776 --padlen;
00777 }
00778 if (signvalue)
00779 dopr_outch (buffer, currlen, maxlen, signvalue);
00780
00781 while (iplace > 0)
00782 dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
00783
00784 #ifdef DEBUG_SNPRINTF
00785 printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
00786 #endif
00787
00788
00789
00790
00791
00792 if (max > 0) {
00793 dopr_outch (buffer, currlen, maxlen, '.');
00794
00795 while (zpadlen > 0) {
00796 dopr_outch (buffer, currlen, maxlen, '0');
00797 --zpadlen;
00798 }
00799
00800 while (fplace > 0)
00801 dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
00802 }
00803
00804 while (padlen < 0) {
00805 dopr_outch (buffer, currlen, maxlen, ' ');
00806 ++padlen;
00807 }
00808 }
00809
00810 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
00811 {
00812 if (*currlen < maxlen) {
00813 buffer[(*currlen)] = c;
00814 }
00815 (*currlen)++;
00816 }
00817
00818 int rsync_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
00819 {
00820 return dopr(str, count, fmt, args);
00821 }
00822 #define vsnprintf rsync_vsnprintf
00823 #endif
00824
00825
00826
00827
00828
00829
00830
00831 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
00832 int rsync_snprintf(char *str,size_t count,const char *fmt,...)
00833 {
00834 size_t ret;
00835 va_list ap;
00836
00837 va_start(ap, fmt);
00838 ret = vsnprintf(str, count, fmt, ap);
00839 va_end(ap);
00840 return ret;
00841 }
00842 #define snprintf rsync_snprintf
00843 #endif
00844
00845 #endif
00846
00847 #ifndef HAVE_VASPRINTF
00848 int vasprintf(char **ptr, const char *format, va_list ap)
00849 {
00850 int ret;
00851 va_list ap2;
00852
00853 VA_COPY(ap2, ap);
00854
00855 ret = vsnprintf(NULL, 0, format, ap2);
00856 if (ret <= 0) return ret;
00857
00858 (*ptr) = (char *)malloc(ret+1);
00859 if (!*ptr) return -1;
00860
00861 VA_COPY(ap2, ap);
00862
00863 ret = vsnprintf(*ptr, ret+1, format, ap2);
00864
00865 return ret;
00866 }
00867 #endif
00868
00869
00870 #ifndef HAVE_ASPRINTF
00871 int asprintf(char **ptr, const char *format, ...)
00872 {
00873 va_list ap;
00874 int ret;
00875
00876 *ptr = NULL;
00877 va_start(ap, format);
00878 ret = vasprintf(ptr, format, ap);
00879 va_end(ap);
00880
00881 return ret;
00882 }
00883 #endif
00884
00885 #ifdef TEST_SNPRINTF
00886
00887 int sprintf(char *str,const char *fmt,...);
00888
00889 int main (void)
00890 {
00891 char buf1[1024];
00892 char buf2[1024];
00893 char *fp_fmt[] = {
00894 "%1.1f",
00895 "%-1.5f",
00896 "%1.5f",
00897 "%123.9f",
00898 "%10.5f",
00899 "% 10.5f",
00900 "%+22.9f",
00901 "%+4.9f",
00902 "%01.3f",
00903 "%4f",
00904 "%3.1f",
00905 "%3.2f",
00906 "%.0f",
00907 "%f",
00908 "-16.16f",
00909 NULL
00910 };
00911 double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,
00912 0.9996, 1.996, 4.136, 5.030201, 0.00205,
00913 0};
00914 char *int_fmt[] = {
00915 "%-1.5d",
00916 "%1.5d",
00917 "%123.9d",
00918 "%5.5d",
00919 "%10.5d",
00920 "% 10.5d",
00921 "%+22.33d",
00922 "%01.3d",
00923 "%4d",
00924 "%d",
00925 NULL
00926 };
00927 long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
00928 char *str_fmt[] = {
00929 "10.5s",
00930 "5.10s",
00931 "10.1s",
00932 "0.10s",
00933 "10.0s",
00934 "1.10s",
00935 "%s",
00936 "%.1s",
00937 "%.10s",
00938 "%10s",
00939 NULL
00940 };
00941 char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
00942 int x, y;
00943 int fail = 0;
00944 int num = 0;
00945
00946 printf ("Testing snprintf format codes against system sprintf...\n");
00947
00948 for (x = 0; fp_fmt[x] ; x++) {
00949 for (y = 0; fp_nums[y] != 0 ; y++) {
00950 int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
00951 int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
00952 sprintf (buf2, fp_fmt[x], fp_nums[y]);
00953 if (strcmp (buf1, buf2)) {
00954 printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
00955 fp_fmt[x], buf1, buf2);
00956 fail++;
00957 }
00958 if (l1 != l2) {
00959 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
00960 fail++;
00961 }
00962 num++;
00963 }
00964 }
00965
00966 for (x = 0; int_fmt[x] ; x++) {
00967 for (y = 0; int_nums[y] != 0 ; y++) {
00968 int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
00969 int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
00970 sprintf (buf2, int_fmt[x], int_nums[y]);
00971 if (strcmp (buf1, buf2)) {
00972 printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
00973 int_fmt[x], buf1, buf2);
00974 fail++;
00975 }
00976 if (l1 != l2) {
00977 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
00978 fail++;
00979 }
00980 num++;
00981 }
00982 }
00983
00984 for (x = 0; str_fmt[x] ; x++) {
00985 for (y = 0; str_vals[y] != 0 ; y++) {
00986 int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
00987 int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
00988 sprintf (buf2, str_fmt[x], str_vals[y]);
00989 if (strcmp (buf1, buf2)) {
00990 printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
00991 str_fmt[x], buf1, buf2);
00992 fail++;
00993 }
00994 if (l1 != l2) {
00995 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
00996 fail++;
00997 }
00998 num++;
00999 }
01000 }
01001
01002 printf ("%d tests failed out of %d.\n", fail, num);
01003
01004 printf("seeing how many digits we support\n");
01005 {
01006 double v0 = 0.12345678901234567890123456789012345678901;
01007 for (x=0; x<100; x++) {
01008 double p = pow(10, x);
01009 double r = v0*p;
01010 snprintf(buf1, sizeof(buf1), "%1.1f", r);
01011 sprintf(buf2, "%1.1f", r);
01012 if (strcmp(buf1, buf2)) {
01013 printf("we seem to support %d digits\n", x-1);
01014 break;
01015 }
01016 }
01017 }
01018
01019 return 0;
01020 }
01021 #endif