From d1886b57774c9d0af819724e03e8ac9a75b9e273 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Aug 2006 22:49:12 +0000 Subject: [PATCH] Check whether v?snprintf is C99-compliant, and fix replacement functions to be. --- configure.in | 57 ++++++++++++++++++++++++++++++++++++++++++++++++---- snprintf.c | 34 +++++++++++++++++++------------ 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/configure.in b/configure.in index 5493895de..62523644f 100644 --- a/configure.in +++ b/configure.in @@ -337,11 +337,60 @@ if test $ac_cv_func_getopt = yes; then AC_CHECK_HEADERS(getopt.h) fi -mutt_cv_snprintf=no SNPRINTFOBJS="" -AC_CHECK_FUNCS(snprintf, , [mutt_cv_snprintf=yes]) -AC_CHECK_FUNCS(vsnprintf, , [mutt_cv_snprintf=yes]) -if test $mutt_cv_snprintf = yes; then +AC_CHECK_FUNC(snprintf, [mutt_cv_func_snprintf=yes], [mutt_cv_func_snprintf=no]) +AC_CHECK_FUNC(vsnprintf, [mutt_cv_func_vsnprintf=yes], [mutt_cv_func_vsnprintf=no]) +if test $mutt_cv_func_snprintf = yes; then +AC_CACHE_CHECK([whether your system's snprintf is C99 compliant], + [mutt_cv_c99_snprintf], + AC_TRY_RUN([ +#include +int main() +{ +changequote(, )dnl + char buf[8]; + int len = snprintf(buf, 4, "1234567"); + return (len != 7 || buf[3] != '\0'); +changequote([, ])dnl +} + ], mutt_cv_c99_snprintf=yes, mutt_cv_c99_snprintf=no, mutt_cv_c99_snprintf=no)) +else + mutt_cv_c99_snprintf=no +fi +if test $mutt_cv_func_vsnprintf = yes; then +AC_CACHE_CHECK([whether your system's vsnprintf is C99 compliant], + [mutt_cv_c99_vsnprintf], + AC_TRY_RUN([ +#include +#include +int foo(const char *fmt, ...) +{ +changequote(, )dnl + char buf[8]; + int len; + va_list ap; + va_start(ap, fmt); + len = vsnprintf(buf, 4, fmt, ap); + va_end(ap); + return (len != 7 || buf[3] != '\0'); +changequote([, ])dnl +} + +int main() +{ + return foo("%s", "1234567"); +} + ], mutt_cv_c99_vsnprintf=yes, mutt_cv_c99_vsnprintf=no, mutt_cv_c99_vsnprintf=no)) +else + mutt_cv_c99_vsnprintf=no +fi +if test $mutt_cv_c99_snprintf = yes; then + AC_DEFINE(HAVE_SNPRINTF, 1, [ Define to 1 if you have a C99 compliant snprintf function. ]) +fi +if test $mutt_cv_c99_vsnprintf = yes; then + AC_DEFINE(HAVE_VSNPRINTF, 1, [ Define to 1 if you have a C99 compliant vsnprintf function. ]) +fi +if test $mutt_cv_c99_snprintf = no -o $mutt_cv_c99_vsnprintf = no; then AC_LIBOBJ(snprintf) fi diff --git a/snprintf.c b/snprintf.c index 8a5586aba..549a7a7e8 100644 --- a/snprintf.c +++ b/snprintf.c @@ -38,6 +38,13 @@ * missing. Some systems only have snprintf() but not vsnprintf(), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * + * Holger Weiss 07/23/06 for mutt 1.5.13 + * A C99 compliant [v]snprintf() returns the number of characters that + * would have been written to a sufficiently sized buffer (excluding + * the '\0'). Mutt now relies on this behaviour, but the original + * code simply returned the length of the resulting output string, so + * that's been fixed. + * **************************************************************/ #if HAVE_CONFIG_H @@ -79,7 +86,7 @@ /*int snprintf (char *str, size_t count, const char *fmt, ...);*/ /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/ -static void dopr (char *buffer, size_t maxlen, const char *format, +static int dopr (char *buffer, size_t maxlen, const char *format, va_list args); static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max); @@ -121,7 +128,7 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c ); #undef MAX #define MAX(p,q) ((p >= q) ? p : q) -static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) +static int dopr (char *buffer, size_t maxlen, const char *format, va_list args) { char ch; long value; @@ -141,7 +148,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) while (state != DP_S_DONE) { - if ((ch == '\0') || (currlen >= maxlen)) + if (ch == '\0') state = DP_S_DONE; switch(state) @@ -317,8 +324,6 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) break; case 's': strvalue = va_arg (args, char *); - if (max < 0) - max = maxlen; /* ie, no max */ fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); break; case 'p': @@ -372,6 +377,8 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) buffer[currlen] = '\0'; else buffer[maxlen - 1] = '\0'; + + return (int)currlen; } static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, @@ -392,18 +399,18 @@ static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ - while ((padlen > 0) && (cnt < max)) + while ((padlen > 0) && (max == -1 || cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } - while (*value && (cnt < max)) + while (*value && (max == -1 || cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } - while ((padlen < 0) && (cnt < max)) + while ((padlen < 0) && (max == -1 || cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; @@ -677,7 +684,8 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) { if (*currlen < maxlen) - buffer[(*currlen)++] = c; + buffer[*currlen] = c; + (*currlen)++; } #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ @@ -685,8 +693,7 @@ static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c) int vsnprintf (char *str, size_t count, const char *fmt, va_list args) { str[0] = 0; - dopr(str, count, fmt, args); - return(strlen(str)); + return(dopr(str, count, fmt, args)); } #endif /* !HAVE_VSNPRINTF */ @@ -703,15 +710,16 @@ int snprintf (va_alist) va_dcl size_t count; char *fmt; #endif + int len; VA_LOCAL_DECL; VA_START (fmt); VA_SHIFT (str, char *); VA_SHIFT (count, size_t ); VA_SHIFT (fmt, char *); - (void) vsnprintf(str, count, fmt, ap); + len = vsnprintf(str, count, fmt, ap); VA_END; - return(strlen(str)); + return(len); } #ifdef TEST_SNPRINTF -- 2.40.0