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