[poppler] qt4/src/poppler-qiodeviceoutstream.cc: open_memstream is non-portable

Jonathan Kew jonathan_kew at sil.org
Mon Jan 28 04:48:03 PST 2008


The document saving code in the Qt4 wrapper uses open_memstream(),  
which is not available on all platforms. I would recommend using  
vasprintf() instead, which I suspect is more widely supported, but  
this is also a GNU extension and may not be available everywhere. So  
a fallback approach using vsnprintf() is also needed.

Proposed changes below....

--
Jonathan
--

diff --git a/configure.ac b/configure.ac
index 99ffbda..602171a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,9 @@ AC_PROG_CXX
  AC_PROG_INSTALL
  AC_CHECK_FUNC(gettimeofday, AC_DEFINE(HAVE_GETTIMEOFDAY, 1,  
[Defines if gettimeofday is available on your system]))
  AC_CHECK_FUNC(localtime_r, AC_DEFINE(HAVE_LOCALTIME_R, 1, [Defines  
if localtime_r is available on your system]))
+AC_CHECK_FUNC(strndup, AC_DEFINE(HAVE_STRNDUP, 1, [Defines if  
strndup is available on your system]))
+AC_CHECK_FUNC(vasprintf, AC_DEFINE(HAVE_VASPRINTF, 1, [Defines if  
vasprintf is available on your system]))
+AC_CHECK_FUNC(open_memstream, AC_DEFINE(HAVE_OPEN_MEMSTREAM, 1,  
[Defines if open_memstream is available on your system]))

  dnl Enable these unconditionally.
  AC_DEFINE([OPI_SUPPORT], [1], [Generate OPI comments in PS output.])

diff --git a/qt4/src/poppler-qiodeviceoutstream.cc b/qt4/src/poppler- 
qiodeviceoutstream.cc
index 11fab97..6772c1d 100644
--- a/qt4/src/poppler-qiodeviceoutstream.cc
+++ b/qt4/src/poppler-qiodeviceoutstream.cc
@@ -57,13 +57,43 @@ void QIODeviceOutStream::put(char c)
  void QIODeviceOutStream::printf(const char *format, ...)
  {
    va_list ap;
-  va_start(ap, format);
    char* buf = 0;
+#ifdef HAVE_VASPRINTF
+  int bufsize;
+  va_start(ap, format);
+  bufsize = vasprintf(&buf, format, ap);
+  va_end(ap);
+  if (bufsize < 0)
+    return; /* failed to allocate memory */
+#else
+#ifdef HAVE_OPEN_MEMSTREAM
    size_t bufsize = 0;
    FILE* stream = open_memstream(&buf, &bufsize);
+  va_start(ap, format);
    vfprintf(stream, format, ap);
    va_end(ap);
    fclose(stream);
+#else /* do it the hard way - based on docs at linux.about.com */
+  size_t bufsize = 100;
+  if ((buf = (char*)malloc(bufsize)) == NULL)
+    return;
+  while (1) {
+    va_start(ap, format);
+    int n = vsnprintf(buf, bufsize, format, ap);
+    va_end(ap);
+    if (n > -1 && (size_t)n < bufsize) {
+      bufsize = n;
+      break;
+    }
+    if (n > -1)
+      bufsize = n + 1; /* allocate exactly what is needed */
+    else
+      bufsize *= 2;    /* else try twice the old size */
+    if ((buf = (char*)realloc(buf, bufsize)) == NULL)
+      return; /* failure! */
+  }
+#endif
+#endif
    m_device->write(buf, bufsize);
    free(buf);
  }



More information about the poppler mailing list