I don't have the cross compilation environment set up yet, but it does build with and without HAVE_ASPRINTF defined. I also tested the asprintf() code in a test application to make sure it did what I thought it did.
------------
Andrew pointed out that adding the use of asprintf() broke the build for Windows. Instead of reverting the uses back to how they were, this patch adds a custom implementation of asprintf() that will only be included when the build system doesn't find asprintf() on the system.
Signed-off-by: Russell Bryant russell@russellbryant.net --- src/CMakeLists.txt | 2 ++ src/include/config.h.in | 1 + src/include/matahari/utilities.h | 13 +++++++++++++ src/lib/utilities.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3b49a7..16d3403 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,6 +33,8 @@ file(GLOB SCHEMAS "${CMAKE_CURRENT_SOURCE_DIR}/*.xml") include (CheckIncludeFiles) check_include_files (string.h HAVE_STRING_H) check_include_files (sys/ioctl.h HAVE_SYS_IOCTL_H) +include (CheckFunctionExists) +check_function_exists (asprintf HAVE_ASPRINTF) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/include/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/include/matahari.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/matahari.h)
diff --git a/src/include/config.h.in b/src/include/config.h.in index e67866b..9f2989c 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -1,2 +1,3 @@ #cmakedefine HAVE_STRING_H 1 #cmakedefine HAVE_SYS_IOCTL_H 1 +#cmakedefine HAVE_ASPRINTF 1 diff --git a/src/include/matahari/utilities.h b/src/include/matahari/utilities.h index 0c9fb94..e48be25 100644 --- a/src/include/matahari/utilities.h +++ b/src/include/matahari/utilities.h @@ -25,6 +25,8 @@ #ifndef __MH_UTILITIES__ #define __MH_UTILITIES__
+#include "config.h" + #include <stdlib.h> #include <sys/types.h> #include <string.h> @@ -34,6 +36,17 @@ extern const char *mh_hostname(void); extern void mh_abort(const char *file, const char *function, int line, const char *assert_condition, int do_core, int do_fork);
+#ifndef HAVE_ASPRINTF +/** + * Custom implementation of asprintf() + * + * This version of asprintf() is only used when the build system doesn't find + * asprintf() on the system. For more information on how to use asprintf(), + * see its man page. + */ +extern int asprintf(char **ret, const char *fmt, ...); +#endif + #define DIMOF(a) ((int) (sizeof(a) / sizeof(0[a])))
#ifndef __GNUC__ diff --git a/src/lib/utilities.c b/src/lib/utilities.c index 645a81c..cad41eb 100644 --- a/src/lib/utilities.c +++ b/src/lib/utilities.c @@ -16,9 +16,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "config.h" + #define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> +#include <stdarg.h>
#include <stdio.h> #include <errno.h> @@ -391,3 +394,35 @@ mh_uuid(void) mh_trace("Got uuid: %s", uuid); return uuid; } + +#ifndef HAVE_ASPRINTF +int +asprintf(char **ret, const char *fmt, ...) +{ + va_list ap; + int len; + char buf[1]; + + /* + * Ask vsnprintf() how many characters it would write if the buffer + * were big enough. + */ + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + /* + * Now go allocate a buffer that is big enough. + */ + *ret = malloc(len + 1); + + /* + * Now vsnprintf() the string into the final result buffer. + */ + va_start(ap, fmt); + vsnprintf(*ret, len + 1, fmt, ap); + va_end(ap); + + return len; +} +#endif /* HAVE_ASPRINTF */