summary refs log tree commit diff
path: root/pkgs/tools/X11/xkbvalidate/xkbvalidate.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/tools/X11/xkbvalidate/xkbvalidate.c')
-rw-r--r--pkgs/tools/X11/xkbvalidate/xkbvalidate.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/pkgs/tools/X11/xkbvalidate/xkbvalidate.c b/pkgs/tools/X11/xkbvalidate/xkbvalidate.c
index d9c9042467c..d25eef154b3 100644
--- a/pkgs/tools/X11/xkbvalidate/xkbvalidate.c
+++ b/pkgs/tools/X11/xkbvalidate/xkbvalidate.c
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -14,6 +13,9 @@ static bool log_alloc_success = true;
 static void add_log(struct xkb_context *ctx, enum xkb_log_level level,
                     const char *fmt, va_list args)
 {
+    size_t buflen;
+    va_list tmpargs;
+
     log_buffer_size++;
 
     if (log_buffer == NULL)
@@ -28,11 +30,24 @@ static void add_log(struct xkb_context *ctx, enum xkb_log_level level,
         return;
     }
 
-    if (vasprintf(&log_buffer[log_buffer_size - 1], fmt, args) == -1) {
+    /* Unfortunately, vasprintf() is a GNU extension and thus not very
+     * portable, so let's first get the required buffer size using a dummy
+     * vsnprintf and afterwards allocate the returned amount of bytes.
+     *
+     * We also need to make a copy of the args, because the value of the args
+     * will be indeterminate after the return.
+     */
+    va_copy(tmpargs, args);
+    buflen = vsnprintf(NULL, 0, fmt, tmpargs);
+    va_end(tmpargs);
+
+    log_buffer[log_buffer_size - 1] = malloc(++buflen);
+
+    if (vsnprintf(log_buffer[log_buffer_size - 1], buflen, fmt, args) == -1) {
         perror("log line alloc");
         log_alloc_success = false;
-        return;
     }
+    va_end(args);
 }
 
 static void print_logs(void)