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