summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Perez de Castro <aperez@igalia.com>2019-08-05 16:18:05 +0300
committerRan Benita <ran@unusedvar.com>2019-12-27 12:45:34 +0200
commitbdff8ebe3c0be4f55281a3ec7d70be753e2456c0 (patch)
tree5ae3022284b3d075b5049541e3dcf9cc63e50474
parent93a13050d64cbd98168df6a4257cf84a7139542f (diff)
downloadlibxkbcommon-bdff8ebe3c0be4f55281a3ec7d70be753e2456c0.tar.gz
libxkbcommon-bdff8ebe3c0be4f55281a3ec7d70be753e2456c0.tar.bz2
libxkbcommon-bdff8ebe3c0be4f55281a3ec7d70be753e2456c0.zip
Provide a fallback implementation of [v]asprintf()
Some environments (e.g. Windows + MSVC) do not provide asprintf() or vasprintf(). This tries to detect their presence, and provides suitable fallback implementations when not available.
-rw-r--r--meson.build5
-rw-r--r--src/utils.c45
-rw-r--r--src/utils.h8
3 files changed, 58 insertions, 0 deletions
diff --git a/meson.build b/meson.build
index b7aaeee..2c6d8e3 100644
--- a/meson.build
+++ b/meson.build
@@ -102,6 +102,11 @@ endif
if cc.has_header_symbol('string.h', 'strndup', prefix: system_ext_define)
configh_data.set('HAVE_STRNDUP', 1)
endif
+if cc.has_header_symbol('stdio.h', 'asprintf', prefix: system_ext_define)
+ configh_data.set('HAVE_ASPRINTF', 1)
+elif cc.has_header_symbol('stdio.h', 'vasprintf', prefix: system_ext_define)
+ configh_data.set('HAVE_VASPRINTF', 1)
+endif
if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: system_ext_define)
configh_data.set('HAVE_SECURE_GETENV', 1)
elif cc.has_header_symbol('stdlib.h', '__secure_getenv', prefix: system_ext_define)
diff --git a/src/utils.c b/src/utils.c
index a71b570..a981a41 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -161,3 +161,48 @@ istrncmp(const char *a, const char *b, size_t n)
}
return 0;
}
+
+#if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF)
+int
+asprintf(char **strp, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vasprintf(strp, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+# if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF)
+int
+vasprintf(char **strp, const char *fmt, va_list ap)
+{
+ int ret;
+ char *buf;
+ va_list ap_copy;
+
+ /*
+ * The value of the va_list parameter is undefined after the call to
+ * vsnprintf() returns: pass a copy to make sure "ap" remains valid.
+ */
+ va_copy(ap_copy, ap);
+ ret = vsnprintf(NULL, 0, fmt, ap_copy);
+ va_end(ap_copy);
+
+ if (ret < 0)
+ return ret;
+
+ if (!(buf = malloc(ret + 1)))
+ return -1;
+
+ if ((ret = vsnprintf(buf, ret + 1, fmt, ap)) < 0) {
+ free(buf);
+ return ret;
+ }
+
+ *strp = buf;
+ return ret;
+}
+# endif /* !HAVE_VASPRINTF */
+#endif /* !HAVE_ASPRINTF */
diff --git a/src/utils.h b/src/utils.h
index d796e10..acd191e 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -259,4 +259,12 @@ unmap_file(char *string, size_t size);
#define ATTR_PACKED
#endif
+#if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF)
+int asprintf(char **strp, const char *fmt, ...) ATTR_PRINTF(2, 3);
+# if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF)
+# include <stdarg.h>
+int vasprintf(char **strp, const char *fmt, va_list ap);
+# endif /* !HAVE_VASPRINTF */
+#endif /* !HAVE_ASPRINTF */
+
#endif /* UTILS_H */