* [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