public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] tools/nolibc: support left-aligned printing in printf
@ 2026-01-26  3:10 licheng.li
  2026-01-26  3:10 ` [PATCH 2/2] selftests/nolibc: add tests for printf left alignment licheng.li
  2026-01-28  7:47 ` [PATCH 1/2] tools/nolibc: support left-aligned printing in printf Willy Tarreau
  0 siblings, 2 replies; 5+ messages in thread
From: licheng.li @ 2026-01-26  3:10 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Thomas Weißschuh, linux-kernel, im.lechain

From: Cheng Li <im.lechain@gmail.com>

Currently, __nolibc_printf() in nolibc does not support the '-' flag
for left alignment. This limits the ability to format tabular output
nicely.

This patch adds support for the '-' flag. The implementation is kept
minimal to minimize the binary size impact.

Measuring the nolibc-test binary on x86_64 shows a small increase in
the text section:

  text    data     bss     dec     hex filename
 43552     248     112   43912    ab88 nolibc-test (before)
 43677     248     112   44037    ac05 nolibc-test (after)

The net increase is 125 bytes.

Signed-off-by: Cheng Li <im.lechain@gmail.com>
---
 tools/include/nolibc/stdio.h | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 1f16dab2ac88..b90b59237bda 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -250,7 +250,7 @@ typedef int (*__nolibc_printf_cb)(intptr_t state, const char *buf, size_t size);
 static __attribute__((unused, format(printf, 4, 0)))
 int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char *fmt, va_list args)
 {
-	char escape, lpref, c;
+	char escape, lpref, padc, c;
 	unsigned long long v;
 	unsigned int written, width;
 	size_t len, ofs, w;
@@ -261,11 +261,17 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char
 	while (1) {
 		c = fmt[ofs++];
 		width = 0;
+		padc = ' ';
 
 		if (escape) {
 			/* we're in an escape sequence, ofs == 1 */
 			escape = 0;
 
+			if (c == '-' || c == '0') {
+				padc = c;
+				c = fmt[ofs++];
+			}
+
 			/* width */
 			while (c >= '0' && c <= '9') {
 				width *= 10;
@@ -358,13 +364,19 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char
 			if (n) {
 				w = len < n ? len : n;
 				n -= w;
-				while (width-- > w) {
-					if (cb(state, " ", 1) != 0)
+				while (padc != '-' && width > w) {
+					if (cb(state, &padc, 1) != 0)
 						return -1;
 					written += 1;
+					width--;
 				}
 				if (cb(state, outstr, w) != 0)
 					return -1;
+				while (width-- > w) {
+					if (cb(state, " ", 1) != 0)
+						return -1;
+					written += 1;
+				}
 			}
 
 			written += len;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] selftests/nolibc: add tests for printf left alignment
  2026-01-26  3:10 [PATCH 1/2] tools/nolibc: support left-aligned printing in printf licheng.li
@ 2026-01-26  3:10 ` licheng.li
  2026-01-28  7:51   ` Willy Tarreau
  2026-01-28  7:47 ` [PATCH 1/2] tools/nolibc: support left-aligned printing in printf Willy Tarreau
  1 sibling, 1 reply; 5+ messages in thread
From: licheng.li @ 2026-01-26  3:10 UTC (permalink / raw)
  To: Willy Tarreau; +Cc: Thomas Weißschuh, linux-kernel, im.lechain

From: Cheng Li <im.lechain@gmail.com>

This patch adds validation for the recently added '-' flag support in
printf(). It ensures that strings and numbers are correctly padded
with spaces on the right side when the left-alignment flag is used.

The test adds minimal overhead to the test binary size.
On x86_64:

  text    data     bss     dec     hex filename
 43677     248     112   44037    ac05 nolibc-test (before)
 43761     248     112   44121    ac59 nolibc-test (after)

The test logic adds 84 bytes.

Signed-off-by: Cheng Li <im.lechain@gmail.com>
---
 tools/testing/selftests/nolibc/nolibc-test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index 3c5a226dad3a..3d47711cad8f 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -1723,6 +1723,7 @@ static int run_printf(int min, int max)
 		CASE_TEST(truncation);   EXPECT_VFPRINTF(25, "01234567890123456789", "%s", "0123456789012345678901234"); break;
 		CASE_TEST(string_width); EXPECT_VFPRINTF(10, "         1", "%10s", "1"); break;
 		CASE_TEST(number_width); EXPECT_VFPRINTF(10, "         1", "%10d", 1); break;
+		CASE_TEST(left_align);   EXPECT_VFPRINTF(10, "foo      |", "%-9s|", "foo"); break;
 		CASE_TEST(width_trunc);  EXPECT_VFPRINTF(25, "                    ", "%25d", 1); break;
 		CASE_TEST(scanf);        EXPECT_ZR(1, test_scanf()); break;
 		CASE_TEST(strerror);     EXPECT_ZR(1, test_strerror()); break;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] tools/nolibc: support left-aligned printing in printf
  2026-01-26  3:10 [PATCH 1/2] tools/nolibc: support left-aligned printing in printf licheng.li
  2026-01-26  3:10 ` [PATCH 2/2] selftests/nolibc: add tests for printf left alignment licheng.li
@ 2026-01-28  7:47 ` Willy Tarreau
  2026-01-28  7:53   ` Willy Tarreau
  1 sibling, 1 reply; 5+ messages in thread
From: Willy Tarreau @ 2026-01-28  7:47 UTC (permalink / raw)
  To: licheng.li; +Cc: Thomas Weißschuh, linux-kernel

On Mon, Jan 26, 2026 at 11:10:37AM +0800, licheng.li wrote:
> From: Cheng Li <im.lechain@gmail.com>
> 
> Currently, __nolibc_printf() in nolibc does not support the '-' flag
> for left alignment. This limits the ability to format tabular output
> nicely.
> 
> This patch adds support for the '-' flag. The implementation is kept
> minimal to minimize the binary size impact.
> 
> Measuring the nolibc-test binary on x86_64 shows a small increase in
> the text section:
> 
>   text    data     bss     dec     hex filename
>  43552     248     112   43912    ab88 nolibc-test (before)
>  43677     248     112   44037    ac05 nolibc-test (after)
> 
> The net increase is 125 bytes.
> 
> Signed-off-by: Cheng Li <im.lechain@gmail.com>
> ---
>  tools/include/nolibc/stdio.h | 18 +++++++++++++++---
>  1 file changed, 15 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
> index 1f16dab2ac88..b90b59237bda 100644
> --- a/tools/include/nolibc/stdio.h
> +++ b/tools/include/nolibc/stdio.h
> @@ -250,7 +250,7 @@ typedef int (*__nolibc_printf_cb)(intptr_t state, const char *buf, size_t size);
>  static __attribute__((unused, format(printf, 4, 0)))
>  int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char *fmt, va_list args)
>  {
> -	char escape, lpref, c;
> +	char escape, lpref, padc, c;
>  	unsigned long long v;
>  	unsigned int written, width;
>  	size_t len, ofs, w;
> @@ -261,11 +261,17 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char
>  	while (1) {
>  		c = fmt[ofs++];
>  		width = 0;
> +		padc = ' ';
>  
>  		if (escape) {
>  			/* we're in an escape sequence, ofs == 1 */
>  			escape = 0;
>  
> +			if (c == '-' || c == '0') {
> +				padc = c;
> +				c = fmt[ofs++];
> +			}
> +
>  			/* width */
>  			while (c >= '0' && c <= '9') {
>  				width *= 10;
> @@ -358,13 +364,19 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char
>  			if (n) {
>  				w = len < n ? len : n;
>  				n -= w;
> -				while (width-- > w) {
> -					if (cb(state, " ", 1) != 0)
> +				while (padc != '-' && width > w) {
> +					if (cb(state, &padc, 1) != 0)
>  						return -1;
>  					written += 1;
> +					width--;
>  				}
>  				if (cb(state, outstr, w) != 0)
>  					return -1;
> +				while (width-- > w) {
> +					if (cb(state, " ", 1) != 0)
> +						return -1;
> +					written += 1;
> +				}
>  			}
>  
>  			written += len;

Thank you, this looks good to me. Since you have paid particular attention
to the size increase, I noticed a few tricks which help a little bit here:

- increment written at the beginning of the loop instead of the end
  helps the compiler make the code more compact.

- testing width > w before padc != '-' also helps by benefitting from
  the result of the last iteration's increment:

  	while (width > w && padc != '-') {
  		written += 1;
  		if (cb(state, &padc, 1) != 0)
  			return -1;
  		width--;
  	}

        ...

	while (width-- > w) {
		written += 1;
		if (cb(state, " ", 1) != 0)
			return -1;
	}

  $ printf '#include "stdio.h"\nvoid *p = printf;\n' |  gcc -Os -xc -c -o printf.o -
  $ nm -oa --size printf*o|grep 'printf$'
  printf-before.o:000000000000035f t printf
  printf-licheng.o:00000000000003b5 t printf
  printf.o:00000000000003a3 t printf

=> that's 19 less bytes, or almost 10% smaller ;-)

I also tried changing the 3 blocks for a single loop checking width and w
to call cb() once and adjust written/w once but it gave the exact same
size for less efficient code so that was not worth it.

Anyway, just to say that if you're interested in trying the minor
adjustments above, you're welcome, otherwise I'm fine with this patch.

Thanks!
Willy

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 2/2] selftests/nolibc: add tests for printf left alignment
  2026-01-26  3:10 ` [PATCH 2/2] selftests/nolibc: add tests for printf left alignment licheng.li
@ 2026-01-28  7:51   ` Willy Tarreau
  0 siblings, 0 replies; 5+ messages in thread
From: Willy Tarreau @ 2026-01-28  7:51 UTC (permalink / raw)
  To: licheng.li; +Cc: Thomas Weißschuh, linux-kernel

On Mon, Jan 26, 2026 at 11:10:38AM +0800, licheng.li wrote:
> From: Cheng Li <im.lechain@gmail.com>
> 
> This patch adds validation for the recently added '-' flag support in
> printf(). It ensures that strings and numbers are correctly padded
> with spaces on the right side when the left-alignment flag is used.
> 
> The test adds minimal overhead to the test binary size.
> On x86_64:
> 
>   text    data     bss     dec     hex filename
>  43677     248     112   44037    ac05 nolibc-test (before)
>  43761     248     112   44121    ac59 nolibc-test (after)
> 
> The test logic adds 84 bytes.
> 
> Signed-off-by: Cheng Li <im.lechain@gmail.com>
> ---
>  tools/testing/selftests/nolibc/nolibc-test.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
> index 3c5a226dad3a..3d47711cad8f 100644
> --- a/tools/testing/selftests/nolibc/nolibc-test.c
> +++ b/tools/testing/selftests/nolibc/nolibc-test.c
> @@ -1723,6 +1723,7 @@ static int run_printf(int min, int max)
>  		CASE_TEST(truncation);   EXPECT_VFPRINTF(25, "01234567890123456789", "%s", "0123456789012345678901234"); break;
>  		CASE_TEST(string_width); EXPECT_VFPRINTF(10, "         1", "%10s", "1"); break;
>  		CASE_TEST(number_width); EXPECT_VFPRINTF(10, "         1", "%10d", 1); break;
> +		CASE_TEST(left_align);   EXPECT_VFPRINTF(10, "foo      |", "%-9s|", "foo"); break;
>  		CASE_TEST(width_trunc);  EXPECT_VFPRINTF(25, "                    ", "%25d", 1); break;
>  		CASE_TEST(scanf);        EXPECT_ZR(1, test_scanf()); break;
>  		CASE_TEST(strerror);     EXPECT_ZR(1, test_strerror()); break;

Your first patch also made a special case of the '0', that will
pad with zeroes on the left, and which is not obvious when reading
the code (BTW I'm realizing now that it's not mentioned in the
commit message), so in my opinion your patch should also test for
this case, which could easily be overlooked and broken by accident.

Thanks,
Willy

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] tools/nolibc: support left-aligned printing in printf
  2026-01-28  7:47 ` [PATCH 1/2] tools/nolibc: support left-aligned printing in printf Willy Tarreau
@ 2026-01-28  7:53   ` Willy Tarreau
  0 siblings, 0 replies; 5+ messages in thread
From: Willy Tarreau @ 2026-01-28  7:53 UTC (permalink / raw)
  To: licheng.li; +Cc: Thomas Weißschuh, linux-kernel

On Wed, Jan 28, 2026 at 08:47:28AM +0100, Willy Tarreau wrote:
> On Mon, Jan 26, 2026 at 11:10:37AM +0800, licheng.li wrote:
> > From: Cheng Li <im.lechain@gmail.com>
> > 
> > Currently, __nolibc_printf() in nolibc does not support the '-' flag
> > for left alignment. This limits the ability to format tabular output
> > nicely.
> > 
> > This patch adds support for the '-' flag. The implementation is kept
> > minimal to minimize the binary size impact.

Since your patch also adds support for the '0' flag to left-pad
with zeroes, this should be mentioned in the commit message.

thanks,
Willy

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-01-28  7:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-26  3:10 [PATCH 1/2] tools/nolibc: support left-aligned printing in printf licheng.li
2026-01-26  3:10 ` [PATCH 2/2] selftests/nolibc: add tests for printf left alignment licheng.li
2026-01-28  7:51   ` Willy Tarreau
2026-01-28  7:47 ` [PATCH 1/2] tools/nolibc: support left-aligned printing in printf Willy Tarreau
2026-01-28  7:53   ` Willy Tarreau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox