[PATCH v4 next 16/23] tools/nolibc/printf: Handle "%s" with the numeric formats

david.laight.linux@gmail.com posted 23 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH v4 next 16/23] tools/nolibc/printf: Handle "%s" with the numeric formats
Posted by david.laight.linux@gmail.com 1 month, 1 week 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.

Signed-off-by: David Laight <david.laight.linux@gmail.com>
---

Unchanched for v4.

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 4c7626dbd63f..484432ca87d5 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
Re: [PATCH v4 next 16/23] tools/nolibc/printf: Handle "%s" with the numeric formats
Posted by Willy Tarreau 1 month ago
On Mon, Mar 02, 2026 at 10:18:08AM +0000, david.laight.linux@gmail.com wrote:
> From: David Laight <david.laight.linux@gmail.com>
> 
> Avoids the extra va_arg() call with is non-trivial on a lot of
                                 ^^^^
s/with/which/ I guess :-)

> modern ABI.
> 
> Signed-off-by: David Laight <david.laight.linux@gmail.com>

Acked-by: Willy Tarreau <w@1wt.eu>

thanks!
Willy

> ---
> 
> Unchanched for v4.
> 
> 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 4c7626dbd63f..484432ca87d5 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