[PATCH v3 next 10/17] tools/nolibc/printf: Use goto and reduce indentation
From: david . laight . linux
Date: Mon Feb 23 2026 - 06:15:58 EST
From: David Laight <david.laight.linux@xxxxxxxxx>
Upcoming changes will need to use goto to jump to the code that
outputs characters.
Use 'goto do_output' to output a known number of characters.
Use 'goto do_strlen_output' to output a '\0' terminated string.
Removes a level of indentation from the format processing code.
Signed-off-by: David Laight <david.laight.linux@xxxxxxxxx>
---
New patch for v3.
Makes the final code look better and there is less to change if done early.
tools/include/nolibc/stdio.h | 168 +++++++++++++++++++----------------
1 file changed, 91 insertions(+), 77 deletions(-)
diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 52c4c4476102..ae96b7bebbfe 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -329,99 +329,113 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list
fmt++;
/* Output characters from the format string. */
len = fmt - outstr;
- } else {
- /* we're in a format sequence */
+ goto do_output;
+ }
- ch = *fmt++;
+ /* we're in a format sequence */
- /* width */
- while (ch >= '0' && ch <= '9') {
- width *= 10;
- width += ch - '0';
+ ch = *fmt++;
- ch = *fmt++;
- }
+ /* width */
+ while (ch >= '0' && ch <= '9') {
+ width *= 10;
+ width += ch - '0';
+
+ ch = *fmt++;
+ }
- /* Length modifiers */
+ /* Length modifiers */
+ if (ch == 'l') {
+ lpref = 1;
+ ch = *fmt++;
if (ch == 'l') {
- lpref = 1;
- ch = *fmt++;
- if (ch == 'l') {
- lpref = 2;
- ch = *fmt++;
- }
- } else if (ch == 'j') {
- /* intmax_t is long long */
lpref = 2;
ch = *fmt++;
- } else {
- lpref = 0;
}
+ } else if (ch == 'j') {
+ /* intmax_t is long long */
+ lpref = 2;
+ ch = *fmt++;
+ } else {
+ lpref = 0;
+ }
- if (ch == 'c' || ch == 'd' || ch == 'u' || ch == 'x' || ch == 'p') {
- char *out = outbuf;
+ if (ch == 'c' || ch == 'd' || ch == 'u' || ch == 'x' || ch == 'p') {
+ char *out = outbuf;
- if (ch == 'p')
+ if (ch == 'p')
+ v = va_arg(args, unsigned long);
+ else if (lpref) {
+ if (lpref > 1)
+ v = va_arg(args, unsigned long long);
+ else
v = va_arg(args, unsigned long);
- else if (lpref) {
- if (lpref > 1)
- v = va_arg(args, unsigned long long);
- else
- v = va_arg(args, unsigned long);
- } else
- v = va_arg(args, unsigned int);
-
- if (ch == 'd') {
- /* sign-extend the value */
- if (lpref == 0)
- v = (long long)(int)v;
- else if (lpref == 1)
- v = (long long)(long)v;
- }
+ } else
+ v = va_arg(args, unsigned int);
- switch (ch) {
- case 'c':
- out[0] = v;
- out[1] = 0;
- break;
- case 'd':
- i64toa_r(v, out);
- break;
- case 'u':
- u64toa_r(v, out);
- break;
- case 'p':
- *(out++) = '0';
- *(out++) = 'x';
- __nolibc_fallthrough;
- default: /* 'x' and 'p' above */
- u64toh_r(v, out);
- break;
- }
- outstr = outbuf;
- }
- else if (ch == 's') {
- outstr = va_arg(args, char *);
- if (!outstr)
- outstr="(null)";
+ if (ch == 'd') {
+ /* sign-extend the value */
+ if (lpref == 0)
+ v = (long long)(int)v;
+ else if (lpref == 1)
+ v = (long long)(long)v;
}
- else if (ch == 'm') {
- outstr = strerror(errno);
- } else {
- if (ch != '%') {
- /* Invalid format: back up to output the format characters */
- fmt = outstr + 1;
- /* and output a '%' now. */
- }
- /* %% is documented as a 'conversion specifier'.
- * Any flags, precision or length modifier are ignored.
- */
- width = 0;
- outstr = "%";
+
+ switch (ch) {
+ case 'c':
+ out[0] = v;
+ out[1] = 0;
+ break;
+ case 'd':
+ i64toa_r(v, out);
+ break;
+ case 'u':
+ u64toa_r(v, out);
+ break;
+ case 'p':
+ *(out++) = '0';
+ *(out++) = 'x';
+ __nolibc_fallthrough;
+ default: /* 'x' and 'p' above */
+ u64toh_r(v, out);
+ break;
}
- len = strlen(outstr);
+ outstr = outbuf;
+ goto do_strlen_output;
}
+ if (ch == 's') {
+ outstr = va_arg(args, char *);
+ if (!outstr)
+ outstr="(null)";
+ goto do_strlen_output;
+ }
+
+ if (ch == 'm') {
+ outstr = strerror(errno);
+ goto do_strlen_output;
+ }
+
+ if (ch != '%') {
+ /* Invalid format: back up to output the format characters */
+ fmt = outstr + 1;
+ /* and output a '%' now. */
+ }
+ /* %% is documented as a 'conversion specifier'.
+ * Any flags, precision or length modifier are ignored.
+ */
+ len = 1;
+ width = 0;
+ outstr = fmt - 1;
+ goto do_output;
+
+do_strlen_output:
+ /* Open coded strlen() (slightly smaller). */
+ for (len = 0;; len++)
+ if (!outstr[len])
+ break;
+
+do_output:
written += len;
width -= len;
--
2.39.5