In some cases we want to show a signed value to the user without needing
to use the full printf() implementation. Add a new version of the
simple_itoa() function to handle this.

Update the existing function to use ulong instead of long, to avoid
confusion about which it actually uses.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 include/vsprintf.h | 14 ++++++++++++++
 lib/vsprintf.c     | 29 +++++++++++++++++++++++++----
 test/lib/str.c     | 17 ++++++++++++++++-
 3 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index 9da6ce7cc4d..cd079684572 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -219,6 +219,20 @@ int vsprintf(char *buf, const char *fmt, va_list args);
  */
 char *simple_itoa(ulong val);
 
+/**
+ * simple_itoa_signed() - convert a signed integer to a string
+ *
+ * This returns a static string containing the decimal representation of the
+ * given value. The returned value may be overwritten by other calls to other
+ * simple... functions, so should be used immediately
+ *
+ * If the value is negative, a minus sign ('-') is prepended
+ *
+ * @val: Value to convert
+ * Return: string containing the signed decimal representation of @val
+ */
+char *simple_itoa_signed(long i);
+
 /**
  * simple_xtoa() - convert an unsigned integer to a hex string
  *
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index c7340a047b2..478d445a569 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -845,21 +845,42 @@ int vprintf(const char *fmt, va_list args)
 }
 #endif
 
-static char local_toa[22];
+static char local_toa[23];
 
-char *simple_itoa(ulong i)
+char *simple_itoa_(ulong i, bool use_signed)
 {
-       /* 21 digits plus null terminator, good for 64-bit or smaller ints */
-       char *p = &local_toa[21];
+       /*
+        * 21 digits plus sign and null terminator, good for 64-bit or smaller
+        * ints
+        */
+       char *p = &local_toa[22];
+       bool neg = false;
 
+       if (use_signed && (long)i < 0) {
+               i = -i;
+               neg = true;
+       }
        *p-- = '\0';
        do {
                *p-- = '0' + i % 10;
                i /= 10;
        } while (i > 0);
+
+       if (neg)
+               *p-- = '-';
        return p + 1;
 }
 
+char *simple_itoa(ulong i)
+{
+       return simple_itoa_(i, false);
+}
+
+char *simple_itoa_signed(long i)
+{
+       return simple_itoa_(i, true);
+}
+
 char *simple_xtoa(ulong num)
 {
        /* 16 digits plus nul terminator, good for 64-bit or smaller ints */
diff --git a/test/lib/str.c b/test/lib/str.c
index e62045318c0..d6d29bbf3eb 100644
--- a/test/lib/str.c
+++ b/test/lib/str.c
@@ -221,14 +221,29 @@ static int str_itoa(struct unit_test_state *uts)
        ut_asserteq_str("123", simple_itoa(123));
        ut_asserteq_str("0", simple_itoa(0));
        ut_asserteq_str("2147483647", simple_itoa(0x7fffffff));
-       ut_asserteq_str("4294967295", simple_itoa(0xffffffff));
+       ut_asserteq_str("2147483647", simple_itoa_signed(0x7fffffff));
+       ut_asserteq_str("2147483648", simple_itoa(0x80000000));
+       if (IS_ENABLED(CONFIG_PHYS_64BIT)) {
+               ut_asserteq_str("2147483648", simple_itoa_signed(0x80000000));
+               ut_asserteq_str("4294967295", simple_itoa_signed(0xffffffff));
+       } else {
+               ut_asserteq_str("-2147483648", simple_itoa_signed(0x80000000));
+               ut_asserteq_str("-1", simple_itoa_signed(0xffffffff));
+       }
 
        /* Use #ifdef here to avoid a compiler warning on 32-bit machines */
 #ifdef CONFIG_PHYS_64BIT
        if (sizeof(ulong) == 8) {
                ut_asserteq_str("9223372036854775807",
                                simple_itoa((1UL << 63) - 1));
+               ut_asserteq_str("9223372036854775807",
+                               simple_itoa_signed((1UL << 63) - 1));
+               ut_asserteq_str("9223372036854775808",
+                               simple_itoa((1UL << 63)));
+               ut_asserteq_str("-9223372036854775808",
+                               simple_itoa_signed((1UL << 63)));
                ut_asserteq_str("18446744073709551615", simple_itoa(-1));
+               ut_asserteq_str("-1", simple_itoa_signed(-1));
        }
 #endif /* CONFIG_PHYS_64BIT */
 
-- 
2.43.0

Reply via email to