From 9557448ae65c8f767a3f42826ddff8b4334c3104 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20L=C3=A9veill=C3=A9?= <nicolas@uucidl.com>
Date: Sun, 16 Aug 2015 16:46:52 +0200
Subject: [PATCH] Introduce {v,}asprintf for windows

We have now again two functions called h_platform_vasprintf and
h_platform_asprintf. On windows they are implemented in terms of vsnprint
and the like. On BSD/GNU libraries we use the supplied vasprintf and
asprintf.
---
 src/backends/regex_debug.c |  5 ++---
 src/platform.h             |  9 +++++++++
 src/platform_bsdlike.c     | 19 +++++++++++++++++-
 src/platform_win32.c       | 41 +++++++++++++++++++++++++++++++++++++-
 src/pprint.c               | 30 +++++++++++++++++++---------
 5 files changed, 90 insertions(+), 14 deletions(-)

diff --git a/src/backends/regex_debug.c b/src/backends/regex_debug.c
index d28f9b2b..5207d9e1 100644
--- a/src/backends/regex_debug.c
+++ b/src/backends/regex_debug.c
@@ -1,6 +1,5 @@
 // Intended to be included from regex_debug.c
-#define _GNU_SOURCE
-#include <stdio.h>
+#include "../platform.h"
 #include <stdlib.h>
 
 #define USE_DLADDR (0)
@@ -22,7 +21,7 @@ char* getsym(HSVMActionFunc addr) {
       return retstr;
   } else
 #endif
-    if (asprintf(&retstr, "%p", addr) > 0)
+    if (h_platform_asprintf(&retstr, "%p", addr) > 0)
       return retstr;
     else
       return NULL;
diff --git a/src/platform.h b/src/platform.h
index 21760dd9..e6eb7ec4 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -8,8 +8,17 @@
 
 #include "compiler_specifics.h"
 
+#include <stdarg.h>
 #include <stdint.h>
 
+/* String Formatting */
+
+/** see GNU C asprintf */
+int h_platform_asprintf(char **strp, const char *fmt, ...);
+
+/** see GNU C vasprintf */
+int h_platform_vasprintf(char **strp, const char *fmt, va_list arg);
+
 /* Error Reporting */
 
 /* BSD errx function, seen in err.h */
diff --git a/src/platform_bsdlike.c b/src/platform_bsdlike.c
index 7d892cf9..2ccf8742 100644
--- a/src/platform_bsdlike.c
+++ b/src/platform_bsdlike.c
@@ -1,5 +1,8 @@
+#define _GNU_SOURCE // to obtain asprintf/vasprintf
 #include "platform.h"
 
+#include <stdio.h>
+
 #include <err.h>
 #include <stdarg.h>
 
@@ -12,6 +15,20 @@
 #include <sys/resource.h>
 #endif
 
+int h_platform_asprintf(char **strp, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  int res = h_platform_vasprintf(strp, fmt, ap);
+  va_end(ap);
+  return res;
+}
+
+int h_platform_vasprintf(char **strp, const char *fmt, va_list arg)
+{
+  return vasprintf(strp, fmt, arg);
+}
+
 void h_platform_errx(int err, const char* format, ...) {
   va_list ap;
   va_start(ap, format);
@@ -62,5 +79,5 @@ int64_t h_platform_stopwatch_ns(struct HStopWatch* stopwatch) {
 
   // time_diff is in ns
   return (ts_now.tv_sec - stopwatch->start.tv_sec) * 1000000000
-	  + (ts_now.tv_nsec - stopwatch->start.tv_nsec);
+          + (ts_now.tv_nsec - stopwatch->start.tv_nsec);
 }
diff --git a/src/platform_win32.c b/src/platform_win32.c
index 94f80bd8..9824b526 100644
--- a/src/platform_win32.c
+++ b/src/platform_win32.c
@@ -1,7 +1,46 @@
 #include "platform.h"
 
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
 #define WIN32_LEAN_AND_MEAN
-#include "windows.h"
+#include <windows.h>
+
+int h_platform_asprintf(char**strp, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  int res = h_platform_vasprintf(strp, fmt, ap);
+  va_end(ap);
+  return res;
+}
+
+int h_platform_vasprintf(char**strp, const char *fmt, va_list args)
+{
+  va_list ap;
+  va_copy(ap, args);
+  int non_null_char_count = _vscprintf(fmt, ap);
+  va_end(ap);
+
+  if (non_null_char_count < 0) {
+    return -1;
+  }
+
+  size_t buffer_size = 1 + non_null_char_count;
+  char* buffer = malloc(buffer_size);
+
+  va_copy(ap, args);
+  int res = vsnprintf_s(buffer, buffer_size, non_null_char_count, fmt, ap);
+  if (res < 0) {
+    free(buffer);
+  } else {
+    buffer[non_null_char_count] = 0;
+    *strp = buffer;
+  }
+  va_end(ap);
+
+  return res;
+}
 
 void h_platform_errx(int err, const char* format, ...) {
   // FIXME(windows) TODO(uucidl): to be implemented
diff --git a/src/pprint.c b/src/pprint.c
index b2290dda..11ec3d67 100644
--- a/src/pprint.c
+++ b/src/pprint.c
@@ -15,7 +15,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#define _GNU_SOURCE
+#include "platform.h"
+
 #include <stdio.h>
 #include <string.h>
 #include "hammer.h"
@@ -114,9 +115,24 @@ static inline bool append_buf_c(struct result_buf *buf, char v) {
   }
 }
 
-static void unamb_sub(const HParsedToken* tok, struct result_buf *buf) {
+/** append a formatted string to the result buffer */
+static inline bool append_buf_formatted(struct result_buf *buf, char* format, ...)
+{
   char* tmpbuf;
   int len;
+  bool result;
+  va_list ap;
+
+  va_start(ap, format);
+  len = h_platform_vasprintf(&tmpbuf, format, ap);
+  result = append_buf(buf, tmpbuf, len);
+  free(tmpbuf);
+  va_end(ap);
+
+  return result;
+}
+
+static void unamb_sub(const HParsedToken* tok, struct result_buf *buf) {
   if (!tok) {
     append_buf(buf, "NULL", 4);
     return;
@@ -141,16 +157,12 @@ static void unamb_sub(const HParsedToken* tok, struct result_buf *buf) {
     break;
   case TT_SINT:
     if (tok->sint < 0)
-      len = asprintf(&tmpbuf, "s-%#" PRIx64, -tok->sint);
+      append_buf_formatted(buf, "s-%#" PRIx64, -tok->sint);
     else
-      len = asprintf(&tmpbuf, "s%#" PRIx64, tok->sint);
-    append_buf(buf, tmpbuf, len);
-    free(tmpbuf);
+      append_buf_formatted(buf, "s%#" PRIx64, tok->sint);
     break;
   case TT_UINT:
-    len = asprintf(&tmpbuf, "u%#" PRIx64, tok->uint);
-    append_buf(buf, tmpbuf, len);
-    free(tmpbuf);
+    append_buf_formatted(buf, "u%#" PRIx64, tok->uint);
     break;
   case TT_ERR:
     append_buf(buf, "ERR", 3);
-- 
GitLab