From 536cde75665836cc15686dce4a12f2ae986e041b Mon Sep 17 00:00:00 2001
From: Armin Luntzer <armin.luntzer@univie.ac.at>
Date: Tue, 31 Jul 2018 17:51:44 +0200
Subject: [PATCH] vsnprintf: 	* always clear precision field 	* support 64
 bit (long long) format flag

---
 lib/vsnprintf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/lib/vsnprintf.c b/lib/vsnprintf.c
index 48e6319..8f94742 100644
--- a/lib/vsnprintf.c
+++ b/lib/vsnprintf.c
@@ -44,6 +44,7 @@
 #define VSN_CHAR	(1 << 6)	/* arg is int, upcast from char */
 #define VSN_SHORT	(1 << 7)	/* arg is int, upcast from short */
 #define VSN_LONG	(1 << 8)	/* arg is long type */
+#define VSN_LONG_LONG	(1 << 10)	/* arg is long long type */
 
 /* type flags */
 #define VSN_UPPERCASE	(1 << 9)	/* %x or %X */
@@ -316,6 +317,9 @@ static size_t eval_prec(const char *fmt, struct fmt_spec *spec, va_list *args)
 	const char *begin = fmt;
 
 
+	/* default */
+	spec->prec = 0;
+
 	if ((*fmt) != '.')
 		return 0;
 
@@ -367,7 +371,12 @@ static size_t eval_length(const char *fmt, struct fmt_spec *spec)
 
 	case 'l':
 		/* we don't support long long specifiers */
-		spec->flags |= VSN_LONG;
+		if (fmt[1] == 'l') {
+			spec->flags |= VSN_LONG_LONG;
+			fmt++;
+		} else {
+			spec->flags |= VSN_LONG;
+		}
 		fmt++;
 		break;
 
@@ -577,6 +586,38 @@ static size_t render_xlong_to_ascii(bool usign, long value, char **str,
 	return render_final(str, end, sign, buf, n, spec);
 }
 
+/**
+ * @brief
+ *
+ * @param usign whether the value is treated as signed or unsigned
+ * @param str	the destination buffer, NULL to print to stdout
+ * @param spec	a struct fmt_spec
+ * @param args	the arguments to the format string
+ *
+ * @return the number of bytes written
+ */
+
+static size_t render_xlong_long_to_ascii(bool usign, long long value, char **str,
+				    const char *end, struct fmt_spec *spec)
+{
+	size_t n = 0;
+
+	long upper, lower;
+
+
+	upper = (long) (value >> 32) & 0xFFFFFFFFUL;
+	lower = (long) (value      ) & 0xFFFFFFFFUL;
+
+	/* only if set, otherwise we have a leading zero */
+	if (upper)
+		n = render_xlong_to_ascii(usign, upper, str, end, spec);
+
+	n += render_xlong_to_ascii(true, lower, str, end, spec);
+
+	return n;
+}
+
+
 
 /**
  * @brief render signed integer types
@@ -594,8 +635,15 @@ static size_t render_xsigned_integer(bool usign, char **str, const char *end,
 {
 	int  i;
 	long l;
+	long long ll;
 
 
+	/* argument is a long long, will turn into a long long */
+	if (spec->flags & VSN_LONG_LONG) {
+		ll = va_arg((*args), long long);
+		return render_xlong_long_to_ascii(usign, ll, str, end, spec);
+	}
+
 	/* argument is a long, will turn into a long */
 	if (spec->flags & VSN_LONG) {
 		l = va_arg((*args), long);
@@ -670,6 +718,8 @@ static size_t render_integer(char **str, const char *end, const char *fmt,
 	case 'X':
 	case 'o':
 	case 'b':
+		n = render_xsigned_integer(true, str, end, spec, args);
+		break;
 	case 'p':
 		n = render_pointer(str, end, spec, args);
 		break;
-- 
GitLab