[PATCH v5 next 10/17] tools/nolibc/printf: Handle "%s" with the numeric formats

david.laight.linux@gmail.com posted 17 patches 1 month ago
[PATCH v5 next 10/17] tools/nolibc/printf: Handle "%s" with the numeric formats
Posted by david.laight.linux@gmail.com 1 month ago
From: David Laight <david.laight.linux@gmail.com>

Avoids the extra va_arg() call with is non-trivial on a lot of
modern ABI.

Acked-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: David Laight <david.laight.linux@gmail.com>
---

Unchanched for v4 and v5.

Changes for v3:
- Moved to its own patch (part of patch 7 in v2)..
- Fix 32bit compile.

 tools/include/nolibc/stdio.h | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 09ea2e0c392f..40ceb7a0b25a 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -412,13 +412,13 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list
 		 */
 		ch_flag = _NOLIBC_PF_FLAG(ch);
 		if (((ch >= 'a' && ch <= 'z') || ch == 'X') &&
-		    _NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'c', 'd', 'i', 'u', 'x', 'p')) {
-			/* 'long' is needed for pointer conversions and ltz lengths.
+		    _NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'c', 'd', 'i', 'u', 'x', 'p', 's')) {
+			/* 'long' is needed for pointer/string conversions and ltz lengths.
 			 * A single test can be used provided 'p' (the same bit as '0')
 			 * is masked from flags.
 			 */
 			if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag | (flags & ~_NOLIBC_PF_FLAG('p')),
-						     'p', 'l', 't', 'z')) {
+						     'p', 's', 'l', 't', 'z')) {
 				v = va_arg(args, unsigned long);
 				signed_v = (long)v;
 			} else if (_NOLIBC_PF_FLAGS_CONTAIN(flags, 'j', 'q')) {
@@ -437,6 +437,15 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list
 				goto do_output;
 			}
 
+			if (ch == 's') {
+				/* "%s" - character string. */
+				outstr = (const char  *)(uintptr_t)v;
+				if (!outstr) {
+					outstr = "(null)";
+				}
+				goto do_strlen_output;
+			}
+
 			out = outbuf;
 
 			if (_NOLIBC_PF_FLAGS_CONTAIN(ch_flag, 'd', 'i')) {
@@ -465,13 +474,6 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list
 			goto do_strlen_output;
 		}
 
-		if (ch == 's') {
-			outstr = va_arg(args, char *);
-			if (!outstr)
-				outstr="(null)";
-			goto do_strlen_output;
-		}
-
 		if (ch == 'm') {
 #ifdef NOLIBC_IGNORE_ERRNO
 			outstr = "unknown error";
-- 
2.39.5