From dd2592aca0b80ec50fa39061ad70aace2c180d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Thu, 7 Sep 2023 06:14:44 +0000 Subject: [PATCH] lib/printf: Implement N2680. This adds specific width length modifiers in the form of wN and wfN (where N is 8, 16, 32, or 64) which allow printing intN_t and int_fastN_t without resorting to casts or PRI macros. Reviewed by: imp, emaste Differential Revision: https://reviews.freebsd.org/D41725 FRR changes only include printf(), scanf/strtol are not locally implemented in FRR. Also added "(void) 0" to empty "else ..." to avoid a compiler warning. Signed-off-by: David Lamparter (cherry picked from FreeBSD commit bce0bef3c6abab92c7ac8cc23b7cc632a382721e) --- lib/printf/printflocal.h | 1 + lib/printf/vfprintf.c | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/printf/printflocal.h b/lib/printf/printflocal.h index 4b030912fe7e..93318c8fdb16 100644 --- a/lib/printf/printflocal.h +++ b/lib/printf/printflocal.h @@ -52,6 +52,7 @@ #define PTRDIFFT 0x800 /* ptrdiff_t */ #define INTMAXT 0x1000 /* intmax_t */ #define CHARINT 0x2000 /* print char using int format */ +#define FASTINT 0x4000 /* int_fastN_t */ /* * Macros for converting digits to letters and vice versa diff --git a/lib/printf/vfprintf.c b/lib/printf/vfprintf.c index 2083642d5eb6..3d875fc13131 100644 --- a/lib/printf/vfprintf.c +++ b/lib/printf/vfprintf.c @@ -416,6 +416,49 @@ reswitch: switch (ch) { case 't': flags |= PTRDIFFT; goto rflag; + case 'w': + /* + * Fixed-width integer types. On all platforms we + * support, int8_t is equivalent to char, int16_t + * is equivalent to short, int32_t is equivalent + * to int, int64_t is equivalent to long long int. + * Furthermore, int_fast8_t, int_fast16_t and + * int_fast32_t are equivalent to int, and + * int_fast64_t is equivalent to long long int. + */ + flags &= ~(CHARINT|SHORTINT|LONGINT|LLONGINT|INTMAXT); + if (fmt[0] == 'f') { + flags |= FASTINT; + fmt++; + } else { + flags &= ~FASTINT; + } + if (fmt[0] == '8') { + if (!(flags & FASTINT)) + flags |= CHARINT; + else + /* no flag set = 32 */ (void) 0; + fmt += 1; + } else if (fmt[0] == '1' && fmt[1] == '6') { + if (!(flags & FASTINT)) + flags |= SHORTINT; + else + /* no flag set = 32 */ (void) 0; + fmt += 2; + } else if (fmt[0] == '3' && fmt[1] == '2') { + /* no flag set = 32 */ (void) 0; + fmt += 2; + } else if (fmt[0] == '6' && fmt[1] == '4') { + flags |= LLONGINT; + fmt += 2; + } else { + if (flags & FASTINT) { + flags &= ~FASTINT; + fmt--; + } + goto invalid; + } + goto rflag; case 'z': flags |= SIZET; goto rflag; @@ -684,6 +727,7 @@ number: if ((dprec = prec) >= 0) default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; +invalid: /* pretend it was %c with argument ch */ buf[0] = ch; cp = buf;