diff options
author | Adrian Perez de Castro <aperez@igalia.com> | 2019-08-05 16:18:05 +0300 |
---|---|---|
committer | Ran Benita <ran@unusedvar.com> | 2019-12-27 12:45:34 +0200 |
commit | bdff8ebe3c0be4f55281a3ec7d70be753e2456c0 (patch) | |
tree | 5ae3022284b3d075b5049541e3dcf9cc63e50474 | |
parent | 93a13050d64cbd98168df6a4257cf84a7139542f (diff) | |
download | libxkbcommon-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.build | 5 | ||||
-rw-r--r-- | src/utils.c | 45 | ||||
-rw-r--r-- | src/utils.h | 8 |
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 */ |