]> granicus.if.org Git - neomutt/commitdiff
Check whether v?snprintf is C99-compliant, and fix replacement functions to be.
authorHolger Weiss <holger@zedat.fu-berlin.de>
Tue, 8 Aug 2006 22:49:12 +0000 (22:49 +0000)
committerHolger Weiss <holger@zedat.fu-berlin.de>
Tue, 8 Aug 2006 22:49:12 +0000 (22:49 +0000)
configure.in
snprintf.c

index 5493895de442189041e4079631a7089a1a0e43f7..62523644fe9e140d754993f4876ed070cadb388a 100644 (file)
@@ -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 <stdio.h>
+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 <stdarg.h>
+#include <stdio.h>
+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
 
index 8a5586abaa358bb4be431261b8464590ddd2c592..549a7a7e8cea39c3d34379556cd1aa572258f3ea 100644 (file)
  *    missing.  Some systems only have snprintf() but not vsnprintf(), so
  *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
  *
+ *  Holger Weiss <holger@zedat.fu-berlin.de> 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