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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
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 */