about summary refs log tree commit diff
path: root/lib/util/vasprintf.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-09-03 18:27:51 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-09-03 18:27:51 +0000
commit93331c9bb51fcfe06fc275f411fa31b6406370e5 (patch)
tree51160cc92e0c5dfd9cf637d238d2ad7c1a90fe27 /lib/util/vasprintf.c
parent89973760e357aaf87b834f93e133ffb76b157d4b (diff)
downloadnetpbm-mirror-93331c9bb51fcfe06fc275f411fa31b6406370e5.tar.gz
netpbm-mirror-93331c9bb51fcfe06fc275f411fa31b6406370e5.tar.xz
netpbm-mirror-93331c9bb51fcfe06fc275f411fa31b6406370e5.zip
Add missing vasprintf.c
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@31 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/util/vasprintf.c')
-rw-r--r--lib/util/vasprintf.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/util/vasprintf.c b/lib/util/vasprintf.c
new file mode 100644
index 00000000..a4229c70
--- /dev/null
+++ b/lib/util/vasprintf.c
@@ -0,0 +1,59 @@
+#define _GNU_SOURCE
+   /* Due to conditional compilation, this is GNU source only if the C library
+      is GNU.
+   */
+#include <stdlib.h>
+#include <string.h>
+
+#include "nstring.h"
+
+#ifdef __GNUC__
+  #define HAVE_VASPRINTF 1
+#else
+  #define HAVE_VASPRINTF 0
+#endif
+
+void
+vasprintfN(const char ** const resultP,
+           const char *  const format,
+           va_list             varargs) {
+
+    char * result;
+
+#if HAVE_VASPRINTF
+    vasprintf(&result, format, varargs);
+
+    if (result == NULL)
+        *resultP = strsol;
+    else
+        *resultP = result;
+#else
+    /* We have a big compromise here.  To do this right, without a
+       huge amount of work, we need to go through the variable
+       arguments twice: once to determine how much memory to allocate,
+       and once to format the string.  On some machines, you can
+       simply make two copies of the va_list variable in normal C
+       fashion, but on others you need va_copy, which is a relatively
+       recent invention.  In particular, the simple va_list copy
+       failed on an AMD64 Gcc Linux system in March 2006.  
+
+       So instead, we just allocate 4K and truncate or waste as
+       necessary.
+    */
+    size_t const allocSize = 4096;
+    result = malloc(allocSize);
+    
+    if (result == NULL)
+        *resultP = strsol;
+    else {
+        size_t realLen;
+
+        vsnprintfN(result, allocSize, format, varargs, &realLen);
+        
+        if (realLen >= allocSize)
+            strcpy(result + allocSize - 15, "<<<TRUNCATED");
+
+        *resultP = result;
+    }
+#endif
+}