[PATCH v3 next 00/17] Enhance printf()
From: david . laight . linux
Date: Mon Feb 23 2026 - 05:37:08 EST
From: David Laight <david.laight.linux@xxxxxxxxx>
Update printf() so that it handles almost all the non-fp formats.
In particular:
- Left alignment.
- Zero padding.
- Alternate form "%#x" and "%#o".
- Field precision.
- Variable field width and precision.
- Width modifiers q, L, t and z.
- Conversion specifiers i, o and X (X generates lower case).
About the only things that are missing are wide chanacters and floating point.
The tests are updated to match.
Bloat/savings (in nolibc-test, but excluding the program) to patch 12:
Function old new delta
_nolibc_u64toa_base.isra - 143 +143
strerror - 78 +78
__nolibc_sprintf_cb 58 91 +33
itoa_r.isra 60 75 +15
utoa_r.isra 144 - -144
__nolibc_printf 1081 729 -352
(All these functions include ~40 bytes for the stack protector code.)
utoa_r.isra and _nolibc_u64toa_base.isra pretty much cancel each other out.
itoa_r.isra grows slightly since it calls _nolibc_u64toa_base().
strerror() used to be inlined, but over half of it is the stack check.
While some of the code added to __nolibc_sprintf_cb() has come out of
__nolibc_printf() 16-20 bytes is removed from the caller.
So there is a net saving of about 280 bytes (including losing a copy of
the number to ascii code).
The later patches add code back in:
patch 13 - conversion flags " +#" +80 bytes
patch 14 - left aligning fields +38 bytes
patch 15 - zero padding and field precision +260 bytes
patch 16 - octal output +34 bytes
So probably about +130 bytes, but it will depend on what the application
actually calls and inlining decisions made by the compiler.
(All x86-64, other architectures will vary.)
The biggest size change is probably removing the .data from strerror().
This reduced the program binary file by 4k if it is the only initialised
data in a small program.
Significant changes for v3:
The patches have been re-ordered, split and joined but the final code
is pretty much the same as v2.
- Include the patch to stdlib.h that optimises the 'number to ascii'
functions. This is needed for the final patch that adds octal support.
This includes a fix to the previous version that could generate negative
digits.
- Add octal support in the final patch.
- Update the selftests as new features are added.
- The patch to buffer fprintf() output has been removed.
Changes for v2:
Mostly changes to improve the readability of the code.
- New patch #1 inserted to rename the variable 'c' to 'ch'.
- Use #define 'magic' for the bit-masks that check multiple characters.
The check for the conversion flag characters is then based on:
ch_flag = _NOLIBC_PF_CHAR_IS_ONE_OF(ch, ' ', '#', '+', '-', '0');
- Re-order the changes so that the old patch 10 (Use bit-pattern for
integral formats) is done at the same time as bit-masks are used for
the flags characters and length modifiers.
This means the restructuring changes are done before new features are
added.
- Put all the changes to the selftest together at the end.
There is one extra test for ("%#01x", 0x1234) (should be "0x1234")
which is problematic because once you've removed the length of the "0x"
from the field width there are -1 character postions for the digits.
David Laight (17):
tools/nolibc: Add _NOLIBC_OPTIMIZER_HIDE_VAR() to compiler.h
tools/nolibc: Optimise and common up the number to ascii functions
selftests/nolibc: Fix build with host headers and libc
selftests/nolibc: Improve reporting of vfprintf() errors
tools/nolibc: Implement strerror() in terms of strerror_r()
tools/nolibc/printf: Change variables 'c' to 'ch' and 'tmpbuf[]' to
'outbuf[]'
tools/nolibc/printf: Move snprintf length check to callback
tools/nolibc/printf: Output pad characters in 16 byte chunks
tools/nolibc/printf: Simplify __nolibc_printf()
tools/nolibc/printf: Use goto and reduce indentation
tools/nolibc/printf: Use bit-masks to hold requested flag, length and
conversion chars
tools/nolibc/printf: Handle "%s" with the numeric formats
tools/nolibc/printf: Add support for conversion flags " +#"
tools/nolibc/printf: Add support for left aligning fields
tools/nolibc/printf: Add support for zero padding and field precision
tools/nolibc/printf: Add support for octal output
selftests/nolibc: Use printf variable field widths and precisions
tools/include/nolibc/compiler.h | 5 +
tools/include/nolibc/stdio.h | 502 ++++++++++++++-----
tools/include/nolibc/stdlib.h | 169 +++----
tools/testing/selftests/nolibc/nolibc-test.c | 179 ++++---
4 files changed, 575 insertions(+), 280 deletions(-)
--
2.39.5