From ad2fbd03f08e49f9da0ebe6133c33073244f01d2 Mon Sep 17 00:00:00 2001
From: nattthebear <goyuken@gmail.com>
Date: Tue, 5 Apr 2016 21:19:23 -0400
Subject: [PATCH] Waterbox: a few small libc changes

---
 waterbox/libc/functions/stdio/vasprintf.c | 58 +++++++++++++++++++++++
 waterbox/libc/includes/stdio.h            |  3 ++
 waterbox/libc/internals/_PDCLIB_config.h  |  2 +-
 3 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 waterbox/libc/functions/stdio/vasprintf.c

diff --git a/waterbox/libc/functions/stdio/vasprintf.c b/waterbox/libc/functions/stdio/vasprintf.c
new file mode 100644
index 0000000000..96bbe17f51
--- /dev/null
+++ b/waterbox/libc/functions/stdio/vasprintf.c
@@ -0,0 +1,58 @@
+#define _PDCLIB_EXTENSIONS
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+static size_t mcb(void *p, const char *buf, size_t size)
+{
+	*(size_t *)p += size;
+	return size;
+} 
+
+static size_t vprintflen(const char *restrict fmt, va_list arg)
+{
+	size_t ret = 0;
+	_vcbprintf(&ret, mcb, fmt, arg);
+	return ret + 1;
+}
+
+int asprintf(char **strp, const char *restrict fmt, ...)
+{
+    va_list arg, arg2;
+    va_start(arg, fmt);
+	va_copy(arg2, arg);
+	
+	size_t sz = vprintflen(fmt, arg);
+
+	*strp = malloc(sz);
+	if (!strp)
+	{
+		va_end(arg);
+		va_end(arg2);
+		return -1;
+	}
+
+	int ret = vsnprintf(*strp, sz, fmt, arg2);
+	va_end(arg);
+	va_end(arg2);
+	return ret;
+}
+
+int vasprintf(char **strp, const char *restrict fmt, va_list arg)
+{
+    va_list arg2;
+	va_copy(arg2, arg);
+	
+	size_t sz = vprintflen(fmt, arg);
+
+	*strp = malloc(sz);
+	if (!strp)
+	{
+		va_end(arg2);
+		return -1;
+	}
+
+	int ret = vsnprintf(*strp, sz, fmt, arg2);
+	va_end(arg2);
+	return ret;
+}
diff --git a/waterbox/libc/includes/stdio.h b/waterbox/libc/includes/stdio.h
index 0d28ce7468..c70ad2f502 100644
--- a/waterbox/libc/includes/stdio.h
+++ b/waterbox/libc/includes/stdio.h
@@ -646,6 +646,9 @@ int vsprintf( char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _
 */
 int vsscanf( const char * _PDCLIB_restrict s, const char * _PDCLIB_restrict format, _PDCLIB_va_list arg ) _PDCLIB_nothrow;
 
+int asprintf(char **strp, const char * _PDCLIB_restrict fmt, ...) _PDCLIB_nothrow;
+int vasprintf(char **strp, const char * _PDCLIB_restrict fmt, _PDCLIB_va_list arg) _PDCLIB_nothrow;
+
 /* Character input/output functions */
 
 /* Retrieve the next character from given stream.
diff --git a/waterbox/libc/internals/_PDCLIB_config.h b/waterbox/libc/internals/_PDCLIB_config.h
index 3be7ca2aee..5aad2c6c07 100644
--- a/waterbox/libc/internals/_PDCLIB_config.h
+++ b/waterbox/libc/internals/_PDCLIB_config.h
@@ -278,7 +278,7 @@ struct _PDCLIB_imaxdiv_t
 typedef char * _PDCLIB_va_list;
 #define _PDCLIB_va_arg( ap, type ) ( (ap) += (_PDCLIB_va_round(type)), ( *(type*) ( (ap) - (_PDCLIB_va_round(type)) ) ) )
 #define _PDCLIB_va_copy( dest, src ) ( (dest) = (src), (void)0 )
-#define _PDCLIB_va_end( ap ) ( (ap) = (void *)0, (void)0 )
+#define _PDCLIB_va_end( ap ) ( (ap) = (char *)0, (void)0 )
 #define _PDCLIB_va_start( ap, parmN ) ( (ap) = (char *) &parmN + ( _PDCLIB_va_round(parmN) ), (void)0 )
 
 /* -------------------------------------------------------------------------- */