aft.c: Silence scan-build warning.
[paraslash.git] / string.c
index 3bddd5e80896e843470687671a05cb0ef09051e2..aa3bcbddabe425cc823e3ad5e567f707f70dbccb 100644 (file)
--- a/string.c
+++ b/string.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2011 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2004-2012 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -114,6 +114,65 @@ __must_check __malloc char *para_strdup(const char *s)
        exit(EXIT_FAILURE);
 }
 
+/**
+ * Print a formated message to a dynamically allocated string.
+ *
+ * \param result The formated string is returned here.
+ * \param fmt The format string.
+ * \param ap Initialized list of arguments.
+ *
+ * This function is similar to vasprintf(), a GNU extension which is not in C
+ * or POSIX. It allocates a string large enough to hold the output including
+ * the terminating null byte. The allocated string is returned via the first
+ * argument and must be freed by the caller. However, unlike vasprintf(), this
+ * function calls exit() if insufficient memory is available, while vasprintf()
+ * returns -1 in this case.
+ *
+ * \return Number of bytes written, not including the terminating \p NULL
+ * character.
+ *
+ * \sa printf(3), vsnprintf(3), va_start(3), vasprintf(3), \ref xasprintf().
+ */
+__printf_2_0 unsigned xvasprintf(char **result, const char *fmt, va_list ap)
+{
+       int ret;
+       size_t size;
+       va_list aq;
+
+       va_copy(aq, ap);
+       ret = vsnprintf(NULL, 0, fmt, aq);
+       va_end(aq);
+       assert(ret >= 0);
+       size = ret + 1;
+       *result = para_malloc(size);
+       va_copy(aq, ap);
+       ret = vsnprintf(*result, size, fmt, aq);
+       va_end(aq);
+       assert(ret >= 0 && ret < size);
+       return ret;
+}
+
+/**
+ * Print to a dynamically allocated string, variable number of arguments.
+ *
+ * \param result See \ref xvasprintf().
+ * \param fmt Usual format string.
+ *
+ * \return The return value of the underlying call to \ref xvasprintf().
+ *
+ * \sa \ref xvasprintf() and the references mentioned there.
+ */
+__printf_2_3 unsigned xasprintf(char **result, const char *fmt, ...)
+{
+       va_list ap;
+       unsigned ret;
+
+       va_start(ap, fmt);
+       ret = xvasprintf(result, fmt, ap);
+       va_end(ap);
+       return ret;
+}
+
 /**
  * Allocate a sufficiently large string and print into it.
  *
@@ -125,13 +184,16 @@ __must_check __malloc char *para_strdup(const char *s)
  * \return This function either returns a pointer to a string that must be
  * freed by the caller or aborts without returning.
  *
- * \sa printf(3).
+ * \sa printf(3), xasprintf().
  */
 __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...)
 {
        char *msg;
+       va_list ap;
 
-       PARA_VSPRINTF(fmt, msg);
+       va_start(ap, fmt);
+       xvasprintf(&msg, fmt, ap);
+       va_end(ap);
        return msg;
 }