On Sun, Mar 09, 2008 at 10:51:42AM -0400, Jeff Johnson wrote:
> Meanwhile, below is a rewrite of POPT_fprintf, essentially identical
> to the "man vsnprintf" example. See what you think ...

Looks good.  I did some tweaking based on this code.  The attached patch
changes what you checked-in to CVS.  See if you agree with these points:

1. If the system has vasprintf(), just use that (avoiding issues 2 & 3).

2. Always allocate one more byte than we need, just in case the system's
   vsprintf() has an off-by-one bug with the limit.

3. Moved the va_start() and va_end() calls back in the loop because I
   believe that the systems that needed a va_copy() in the old code
   won't like the reuse of "ap" without it.

Bonus question:  I didn't think older systems supported the idiom of
realloc(NULL, len) doing a malloc().  I didn't check to see if that
idiom is already used elsewhere in the popt code, though, so I just
left that alone.

I tested both sides of the HAVE_VASPRINTF code and this seems good to
me.

..wayne..
--- configure.ac        9 Mar 2008 20:24:45 -0000       1.39
+++ configure.ac        9 Mar 2008 21:26:17 -0000
@@ -69,7 +69,7 @@ AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, t
 AC_CHECK_FUNC(setreuid, [], [
     AC_CHECK_LIB(ucb, setreuid, [if echo $LIBS | grep -- -lucb >/dev/null 
;then :; else LIBS="$LIBS -lc -lucb" USEUCB=y;fi])
 ])
-AC_CHECK_FUNCS(getuid geteuid iconv mtrace __secure_getenv setregid stpcpy 
strerror)
+AC_CHECK_FUNCS(getuid geteuid iconv mtrace __secure_getenv setregid stpcpy 
strerror vasprintf)
 
 AM_GNU_GETTEXT([external])
 
--- poptint.c   9 Mar 2008 20:24:45 -0000       1.17
+++ poptint.c   9 Mar 2008 21:26:18 -0000
@@ -152,13 +152,17 @@ int
 POPT_fprintf (FILE * stream, const char * format, ...)
 {
     char * b = NULL, * ob = NULL;
-    size_t nb = (size_t)1;
     int rc;
     va_list ap;
+#ifndef HAVE_VASPRINTF
+    size_t nb = (size_t)1;
 
-    va_start(ap, format);
-    while ((b = realloc(b, nb)) != NULL) {
+    /* Note that we always allocate 1 byte more than we need, just in
+     * case the vsnprintf() has an off-by-one bug with the limit. */
+    while ((b = realloc(b, nb+1)) != NULL) {
+       va_start(ap, format);
        rc = vsnprintf(b, nb, format, ap);
+       va_end(ap);
        if (rc > -1) {  /* glibc 2.1 */
            if ((size_t)rc < nb)
                break;
@@ -167,8 +171,16 @@ POPT_fprintf (FILE * stream, const char 
            nb += (nb < (size_t)100 ? (size_t)100 : nb);
        ob = b;
     }
+
+#else /* HAVE_VASPRINTF */
+
+    va_start(ap, format);
+    if (vasprintf(&b, format, ap) < 0)
+       b = NULL;
     va_end(ap);
 
+#endif
+
     rc = 0;
     if (b != NULL) {
 #ifdef HAVE_ICONV

Reply via email to