X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fsnprintf.c;h=2f2698bea47d2c958f394ece7d7970a420b0c4f2;hp=bc83def4ff6686445434f24c3e6b05750abdb67d;hb=d763f8bf6d6e13ce006ffab616cc8a77e747a633;hpb=1a6058b1ec98baf1dce0574bec5079ae0db0f0c0 diff --git a/src/snprintf.c b/src/snprintf.c index bc83def4..2f2698be 100644 --- a/src/snprintf.c +++ b/src/snprintf.c @@ -62,43 +62,51 @@ * fixed return value to comply with C99 * fixed handling of snprintf(NULL, ...) * - * Hrvoje Niksic 2000-11-04 + * Hrvoje Niksic 2000-11-04 * include instead of "config.h". * moved TEST_SNPRINTF stuff out of HAVE_SNPRINTF ifdef. * include for NULL. * added support and test cases for long long. * don't declare argument types to (v)snprintf if stdarg is not used. + * use int instead of short int as 2nd arg to va_arg. + * + * alexk (INN) 2002-08-21 + * use LLONG in fmtfp to handle more characters during floating + * point conversion. + * + * herb (Samba) 2002-12-19 + * actually print args for %g and %e + * + * Hrvoje Niksic 2005-04-15 + * write function definitions in the ansi2knr-friendly way. + * if string precision is specified, don't read VALUE past it. + * fix bug in fmtfp that caused 0.01 to be printed as 0.1. + * don't include because none of it is used. + * interpret precision as number of significant digits with %g + * omit trailing decimal zeros with %g * **************************************************************/ -#ifdef HAVE_CONFIG_H -# include +#include "wget.h" + +/* For testing purposes, always compile in the code. */ +#ifdef TEST_SNPRINTF +# undef HAVE_SNPRINTF +# undef HAVE_VSNPRINTF +# ifndef SIZEOF_LONG_LONG +# ifdef __GNUC__ +# define SIZEOF_LONG_LONG 8 +# endif +# endif #endif #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) #include #include -#include /* for NULL */ -#include - -/* varargs declarations: */ - -#if defined(HAVE_STDARG_H) -# include -# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ -# define VA_LOCAL_DECL va_list ap -# define VA_START(f) va_start(ap, f) -# define VA_SHIFT(v,t) ; /* no-op for ANSI */ -# define VA_END va_end(ap) -#else -# include -# undef HAVE_STDARGS -# define VA_LOCAL_DECL va_list ap -# define VA_START(f) va_start(ap) /* f is ignored! */ -# define VA_SHIFT(v,t) v = va_arg(ap,t) -# define VA_END va_end(ap) -#endif +#include /* for NULL */ + +#include #ifdef HAVE_LONG_DOUBLE #define LDOUBLE long double @@ -106,29 +114,31 @@ #define LDOUBLE double #endif -#ifdef HAVE_LONG_LONG +#if SIZEOF_LONG_LONG != 0 # define LLONG long long #else # define LLONG long #endif -#ifdef HAVE_STDARGS +/* If we're running the test suite, rename snprintf and vsnprintf to + avoid conflicts with the system version. */ +#ifdef TEST_SNPRINTF +# define snprintf test_snprintf +# define vsnprintf test_vsnprintf +#endif + int snprintf (char *str, size_t count, const char *fmt, ...); int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); -#else -int snprintf (); -int vsnprintf (); -#endif -static int dopr (char *buffer, size_t maxlen, const char *format, +static int dopr (char *buffer, size_t maxlen, const char *format, va_list args); static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max); + const char *value, int flags, int min, int max); static int fmtint (char *buffer, size_t *currlen, size_t maxlen, - LLONG value, int base, int min, int max, int flags); + LLONG value, int base, int min, int max, int flags); static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags); -static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); + LDOUBLE fvalue, int min, int max, int flags); +static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c); /* * dopr(): poor man's version of doprintf @@ -146,13 +156,14 @@ static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); #define DP_S_DONE 8 /* format flags - Bits */ -#define DP_F_MINUS (1 << 0) -#define DP_F_PLUS (1 << 1) -#define DP_F_SPACE (1 << 2) -#define DP_F_NUM (1 << 3) -#define DP_F_ZERO (1 << 4) -#define DP_F_UP (1 << 5) -#define DP_F_UNSIGNED (1 << 6) +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) +#define DP_F_FP_G (1 << 7) /* Conversion Flags */ #define DP_C_SHORT 1 @@ -193,113 +204,113 @@ static int dopr (char *buffer, size_t maxlen, const char *format, va_list args) { case DP_S_DEFAULT: if (ch == '%') - state = DP_S_FLAGS; + state = DP_S_FLAGS; else - total += dopr_outch (buffer, &currlen, maxlen, ch); + total += dopr_outch (buffer, &currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': - flags |= DP_F_MINUS; + flags |= DP_F_MINUS; ch = *format++; - break; + break; case '+': - flags |= DP_F_PLUS; + flags |= DP_F_PLUS; ch = *format++; - break; + break; case ' ': - flags |= DP_F_SPACE; + flags |= DP_F_SPACE; ch = *format++; - break; + break; case '#': - flags |= DP_F_NUM; + flags |= DP_F_NUM; ch = *format++; - break; + break; case '0': - flags |= DP_F_ZERO; + flags |= DP_F_ZERO; ch = *format++; - break; + break; default: - state = DP_S_MIN; - break; + state = DP_S_MIN; + break; } break; case DP_S_MIN: - if (ISDIGIT(ch)) + if ('0' <= ch && ch <= '9') { - min = 10*min + char_to_int (ch); - ch = *format++; + min = 10*min + char_to_int (ch); + ch = *format++; } else if (ch == '*') { - min = va_arg (args, int); - ch = *format++; - state = DP_S_DOT; + min = va_arg (args, int); + ch = *format++; + state = DP_S_DOT; } else - state = DP_S_DOT; + state = DP_S_DOT; break; case DP_S_DOT: if (ch == '.') { - state = DP_S_MAX; - ch = *format++; + state = DP_S_MAX; + ch = *format++; } else - state = DP_S_MOD; + state = DP_S_MOD; break; case DP_S_MAX: - if (ISDIGIT(ch)) + if ('0' <= ch && ch <= '9') { - if (max < 0) - max = 0; - max = 10*max + char_to_int (ch); - ch = *format++; + if (max < 0) + max = 0; + max = 10*max + char_to_int (ch); + ch = *format++; } else if (ch == '*') { - max = va_arg (args, int); - ch = *format++; - state = DP_S_MOD; + max = va_arg (args, int); + ch = *format++; + state = DP_S_MOD; } else - state = DP_S_MOD; + state = DP_S_MOD; break; case DP_S_MOD: switch (ch) { case 'h': - cflags = DP_C_SHORT; - ch = *format++; - break; + cflags = DP_C_SHORT; + ch = *format++; + break; case 'l': - cflags = DP_C_LONG; - ch = *format++; - break; + cflags = DP_C_LONG; + ch = *format++; + break; case 'L': - cflags = DP_C_LDOUBLE; - ch = *format++; - break; + cflags = DP_C_LDOUBLE; + ch = *format++; + break; default: - break; + break; } if (cflags != DP_C_LONG) - state = DP_S_CONV; + state = DP_S_CONV; else - state = DP_S_MOD_L; + state = DP_S_MOD_L; break; case DP_S_MOD_L: switch (ch) - { - case 'l': - cflags = DP_C_LLONG; - ch = *format++; - break; - default: - break; - } + { + case 'l': + cflags = DP_C_LLONG; + ch = *format++; + break; + default: + break; + } state = DP_S_CONV; break; case DP_S_CONV: @@ -307,126 +318,131 @@ static int dopr (char *buffer, size_t maxlen, const char *format, va_list args) { case 'd': case 'i': - if (cflags == DP_C_SHORT) - value = va_arg (args, short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, long int); - else if (cflags == DP_C_LLONG) - value = va_arg (args, LLONG); - else - value = va_arg (args, int); - total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; + if (cflags == DP_C_SHORT) + value = (short int) va_arg (args, int); + else if (cflags == DP_C_LONG) + value = va_arg (args, long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, LLONG); + else + value = va_arg (args, int); + total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; case 'o': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else if (cflags == DP_C_LLONG) - value = va_arg (args, unsigned LLONG); - else - value = va_arg (args, unsigned int); - total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); - break; + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = (unsigned short int) va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, unsigned LLONG); + else + value = va_arg (args, unsigned int); + total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); + break; case 'u': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else if (cflags == DP_C_LLONG) - value = va_arg (args, unsigned LLONG); - else - value = va_arg (args, unsigned int); - total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); - break; + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = (unsigned short int) va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, unsigned LLONG); + else + value = va_arg (args, unsigned int); + total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); + break; case 'X': - flags |= DP_F_UP; + flags |= DP_F_UP; case 'x': - flags |= DP_F_UNSIGNED; - if (cflags == DP_C_SHORT) - value = va_arg (args, unsigned short int); - else if (cflags == DP_C_LONG) - value = va_arg (args, unsigned long int); - else if (cflags == DP_C_LLONG) - value = va_arg (args, unsigned LLONG); - else - value = va_arg (args, unsigned int); - total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); - break; + flags |= DP_F_UNSIGNED; + if (cflags == DP_C_SHORT) + value = (unsigned short int) va_arg (args, unsigned int); + else if (cflags == DP_C_LONG) + value = va_arg (args, unsigned long int); + else if (cflags == DP_C_LLONG) + value = va_arg (args, unsigned LLONG); + else + value = va_arg (args, unsigned int); + total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); + break; case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - /* um, floating point? */ - total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); - break; + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; case 'E': - flags |= DP_F_UP; + flags |= DP_F_UP; case 'e': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - break; + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; case 'G': - flags |= DP_F_UP; + flags |= DP_F_UP; case 'g': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg (args, LDOUBLE); - else - fvalue = va_arg (args, double); - break; + flags |= DP_F_FP_G; + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg (args, LDOUBLE); + else + fvalue = va_arg (args, double); + if (max == 0) + /* C99 says: if precision [for %g] is zero, it is taken as one */ + max = 1; + total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); + break; case 'c': - total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); - break; + total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); + break; case 's': - strvalue = va_arg (args, char *); - total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); - break; + strvalue = va_arg (args, char *); + total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); + break; case 'p': - strvalue = va_arg (args, void *); - total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, + strvalue = va_arg (args, void *); + total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); - break; + break; case 'n': - if (cflags == DP_C_SHORT) - { - short int *num; - num = va_arg (args, short int *); - *num = currlen; + if (cflags == DP_C_SHORT) + { + short int *num; + num = va_arg (args, short int *); + *num = currlen; } - else if (cflags == DP_C_LONG) - { - long int *num; - num = va_arg (args, long int *); - *num = currlen; + else if (cflags == DP_C_LONG) + { + long int *num; + num = va_arg (args, long int *); + *num = currlen; } - else if (cflags == DP_C_LLONG) - { - LLONG *num; - num = va_arg (args, LLONG *); - *num = currlen; + else if (cflags == DP_C_LLONG) + { + LLONG *num; + num = va_arg (args, LLONG *); + *num = currlen; } - else - { - int *num; - num = va_arg (args, int *); - *num = currlen; + else + { + int *num; + num = va_arg (args, int *); + *num = currlen; } - break; + break; case '%': - total += dopr_outch (buffer, &currlen, maxlen, ch); - break; + total += dopr_outch (buffer, &currlen, maxlen, ch); + break; case 'w': - /* not supported yet, treat as next char */ - ch = *format++; - break; + /* not supported yet, treat as next char */ + ch = *format++; + break; default: - /* Unknown, skip */ - break; + /* Unknown, skip */ + break; } ch = *format++; state = DP_S_DEFAULT; @@ -451,7 +467,7 @@ static int dopr (char *buffer, size_t maxlen, const char *format, va_list args) } static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, - char *value, int flags, int min, int max) + const char *value, int flags, int min, int max) { int padlen, strln; /* amount to pad */ int cnt = 0; @@ -459,12 +475,16 @@ static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, if (value == 0) { - value = ""; + value = "(null)"; } - for (strln = 0; value[strln]; ++strln); /* strlen */ - if (max >= 0 && max < strln) - strln = max; + if (max < 0) + strln = strlen (value); + else + /* When precision is specified, don't read VALUE past precision. */ + /*strln = strnlen (value, max);*/ + for (strln = 0; strln < max && value[strln]; ++strln) + ; padlen = min - strln; if (padlen < 0) padlen = 0; @@ -492,7 +512,7 @@ static int fmtstr (char *buffer, size_t *currlen, size_t maxlen, /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static int fmtint (char *buffer, size_t *currlen, size_t maxlen, - LLONG value, int base, int min, int max, int flags) + LLONG value, int base, int min, int max, int flags) { int signvalue = 0; unsigned LLONG uvalue; @@ -516,10 +536,10 @@ static int fmtint (char *buffer, size_t *currlen, size_t maxlen, } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ - signvalue = '+'; + signvalue = '+'; else if (flags & DP_F_SPACE) - signvalue = ' '; + signvalue = ' '; } if (flags & DP_F_UP) @@ -596,7 +616,7 @@ static LDOUBLE abs_val (LDOUBLE value) return result; } -static LDOUBLE pow10 (int exp) +static LDOUBLE pow10_int (int exp) { LDOUBLE result = 1; @@ -609,9 +629,9 @@ static LDOUBLE pow10 (int exp) return result; } -static long round (LDOUBLE value) +static LLONG round_int (LDOUBLE value) { - long intpart; + LLONG intpart; intpart = value; value = value - intpart; @@ -622,20 +642,23 @@ static long round (LDOUBLE value) } static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, - LDOUBLE fvalue, int min, int max, int flags) + LDOUBLE fvalue, int min, int max, int flags) { int signvalue = 0; LDOUBLE ufvalue; - char iconvert[20]; - char fconvert[20]; + char iconvert[24]; + char fconvert[24]; int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; - int caps = 0; int total = 0; - long intpart; - long fracpart; + LLONG intpart; + LLONG fracpart; + LLONG mask10; + int leadingfrac0s = 0; /* zeros at the start of fractional part */ + int omitzeros = 0; + int omitcount = 0; /* * AIX manpage says the default is 0, but Solaris says the default @@ -653,7 +676,7 @@ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, signvalue = '+'; else if (flags & DP_F_SPACE) - signvalue = ' '; + signvalue = ' '; #if 0 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ @@ -661,23 +684,70 @@ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, intpart = ufvalue; + /* With %g precision is the number of significant digits, which + includes the digits in intpart. */ + if (flags & DP_F_FP_G) + { + if (intpart != 0) + { + /* For each digit of INTPART, print one less fractional digit. */ + LLONG temp = intpart; + for (temp = intpart; temp != 0; temp /= 10) + --max; + if (max < 0) + max = 0; + } + else + { + /* For each leading 0 in fractional part, print one more + fractional digit. */ + LDOUBLE temp; + if (ufvalue != 0) + for (temp = ufvalue; temp < 0.1; temp *= 10) + ++max; + } + } + + /* C99: trailing zeros are removed from the fractional portion of the + result unless the # flag is specified */ + if ((flags & DP_F_FP_G) && !(flags & DP_F_NUM)) + omitzeros = 1; + +#if SIZEOF_LONG_LONG > 0 +# define MAX_DIGITS 18 /* grok more digits with long long */ +#else +# define MAX_DIGITS 9 /* just long */ +#endif + /* - * Sorry, we only support 9 digits past the decimal because of our - * conversion method + * Sorry, we only support several digits past the decimal because of + * our conversion method */ - if (max > 9) - max = 9; + if (max > MAX_DIGITS) + max = MAX_DIGITS; + + /* Factor of 10 with the needed number of digits, e.g. 1000 for max==3 */ + mask10 = pow10_int (max); /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ - fracpart = round ((pow10 (max)) * (ufvalue - intpart)); + fracpart = round_int (mask10 * (ufvalue - intpart)); - if (fracpart >= pow10 (max)) + if (fracpart >= mask10) { intpart++; - fracpart -= pow10 (max); + fracpart -= mask10; } + else if (fracpart != 0) + /* If fracpart has less digits than the 10* mask, we need to + manually insert leading 0s. For example 2.01's fractional part + requires one leading zero to distinguish it from 2.1. */ + while (fracpart < mask10 / 10) + { + ++leadingfrac0s; + mask10 /= 10; + } #ifdef DEBUG_SNPRINTF dprint (1, (debugfile, "fmtfp: %f =? %d.%d\n", fvalue, intpart, fracpart)); @@ -685,25 +755,29 @@ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, /* Convert integer part */ do { - iconvert[iplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10]; + iconvert[iplace++] = '0' + intpart % 10; intpart = (intpart / 10); - } while(intpart && (iplace < 20)); - if (iplace == 20) iplace--; + } while(intpart && (iplace < sizeof(iconvert))); + if (iplace == sizeof(iconvert)) iplace--; iconvert[iplace] = 0; /* Convert fractional part */ do { - fconvert[fplace++] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10]; + fconvert[fplace++] = '0' + fracpart % 10; fracpart = (fracpart / 10); - } while(fracpart && (fplace < 20)); - if (fplace == 20) fplace--; + } while(fracpart && (fplace < sizeof(fconvert))); + while (leadingfrac0s-- > 0 && fplace < sizeof(fconvert)) + fconvert[fplace++] = '0'; + if (fplace == sizeof(fconvert)) fplace--; fconvert[fplace] = 0; + if (omitzeros) + while (omitcount < fplace && fconvert[omitcount] == '0') + ++omitcount; /* -1 for decimal point, another -1 if we are printing a sign */ - padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); - zpadlen = max - fplace; + padlen = min - iplace - (max - omitcount) - 1 - ((signvalue) ? 1 : 0); + if (!omitzeros) + zpadlen = max - fplace; if (zpadlen < 0) zpadlen = 0; if (padlen < 0) @@ -740,11 +814,11 @@ static int fmtfp (char *buffer, size_t *currlen, size_t maxlen, * Decimal point. This should probably use locale to find the correct * char to print out. */ - if (max > 0) + if (max > 0 && (fplace > omitcount || zpadlen > 0)) { total += dopr_outch (buffer, currlen, maxlen, '.'); - while (fplace > 0) + while (fplace > omitcount) total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); } @@ -780,27 +854,14 @@ int vsnprintf (char *str, size_t count, const char *fmt, va_list args) #endif /* !HAVE_VSNPRINTF */ #ifndef HAVE_SNPRINTF -/* VARARGS3 */ -#ifdef HAVE_STDARGS -int snprintf (char *str,size_t count,const char *fmt,...) -#else -int snprintf (va_alist) va_dcl -#endif +int snprintf (char *str, size_t count, const char *fmt,...) { -#ifndef HAVE_STDARGS - char *str; - size_t count; - char *fmt; -#endif - VA_LOCAL_DECL; + va_list ap; int total; - - VA_START (fmt); - VA_SHIFT (str, char *); - VA_SHIFT (count, size_t ); - VA_SHIFT (fmt, char *); - total = vsnprintf(str, count, fmt, ap); - VA_END; + + va_start (ap, fmt); + total = vsnprintf (str, count, fmt, ap); + va_end (ap); return total; } #endif /* !HAVE_SNPRINTF */ @@ -808,16 +869,17 @@ int snprintf (va_alist) va_dcl #ifdef TEST_SNPRINTF -#include +# ifndef LONG_STRING +# define LONG_STRING 1024 +# endif -#ifndef LONG_STRING -#define LONG_STRING 1024 -#endif int main (void) { char buf1[LONG_STRING]; char buf2[LONG_STRING]; char *fp_fmt[] = { + /* %f formats */ + "%f", "%-1.5f", "%1.5f", "%123.9f", @@ -831,10 +893,28 @@ int main (void) "%3.2f", "%.0f", "%.1f", + "%#10.1f", +#if SIZEOF_LONG_LONG != 0 + "%.16f", + "%18.16f", + "%-16.16f", +#endif + /* %g formats */ + "%g", + "%1.5g", + "%-1.5g", + "%.9g", + "%123.9g", + "%#123.9g", +#if SIZEOF_LONG_LONG != 0 + "%.16g", + "%20.16g", +#endif NULL }; double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, - 0.9996, 1.996, 4.136, 0}; + 0.9996, 1.996, 4.136, 0.00205, 0.0001, 321.000009, + 0}; char *int_fmt[] = { "%-1.5d", "%1.5d", @@ -848,22 +928,22 @@ int main (void) NULL }; long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; -#ifdef HAVE_LONG_LONG +#if SIZEOF_LONG_LONG != 0 char *llong_fmt[] = { - "%lld", "%llu", - "%-1.5lld", "%-1.5llu", - "%1.5lld", "%1.5llu", - "%123.9lld", "%123.9llu", - "%5.5lld", "%5.5llu", - "%10.5lld", "%10.5llu", - "% 10.5lld", "% 10.5llu", - "%+22.33lld", "%+22.33llu", - "%01.3lld", "%01.3llu", - "%4lld", "%4llu", + "%lld", "%llu", + "%-1.5lld", "%-1.5llu", + "%1.5lld", "%1.5llu", + "%123.9lld", "%123.9llu", + "%5.5lld", "%5.5llu", + "%10.5lld", "%10.5llu", + "% 10.5lld", "% 10.5llu", + "%+22.33lld", "%+22.33llu", + "%01.3lld", "%01.3llu", + "%4lld", "%4llu", NULL }; long long llong_nums[] = { - ~(long long)0, /* all-1 bit pattern */ + ~(long long)0, /* all-1 bit pattern */ (~(unsigned long long)0) >> 1, /* largest signed long long */ /* random... */ -150, 134, 91340, 341, @@ -883,9 +963,9 @@ int main (void) sprintf (buf2, fp_fmt[x], fp_nums[y]); if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - fp_fmt[x], buf1, buf2); - fail++; + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + fp_fmt[x], buf1, buf2); + fail++; } num++; } @@ -897,14 +977,14 @@ int main (void) sprintf (buf2, int_fmt[x], int_nums[y]); if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - int_fmt[x], buf1, buf2); - fail++; + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + int_fmt[x], buf1, buf2); + fail++; } num++; } -#ifdef HAVE_LONG_LONG +#if SIZEOF_LONG_LONG != 0 for (x = 0; llong_fmt[x] != NULL ; x++) for (y = 0; llong_nums[y] != 0 ; y++) { @@ -912,14 +992,15 @@ int main (void) sprintf (buf2, llong_fmt[x], llong_nums[y]); if (strcmp (buf1, buf2)) { - printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", - llong_fmt[x], buf1, buf2); - fail++; + printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n", + llong_fmt[x], buf1, buf2); + fail++; } num++; } #endif printf ("%d tests failed out of %d.\n", fail, num); + return 0; } -#endif /* SNPRINTF_TEST */ +#endif /* TEST_SNPRINTF */