From c9170233809c149808389837be754c52b3bbdd74 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 1/4] 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..3f6700c8385d 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 + (void) 0; /* no flag set = 32 */ + fmt += 1; + } else if (fmt[0] == '1' && fmt[1] == '6') { + if (!(flags & FASTINT)) + flags |= SHORTINT; + else + (void) 0; /* no flag set = 32 */ + fmt += 2; + } else if (fmt[0] == '3' && fmt[1] == '2') { + /* no flag set = 32 */ + 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; From 91fdb7366cbe1200ef38b3ce379bffb1ac7aacee Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 10 Mar 2024 13:30:46 +0100 Subject: [PATCH 2/4] tests: exercise `%w`/`%wf` printfrr modifiers Added by ISO C23 / N2680, implementation imported from FreeBSD. Signed-off-by: David Lamparter --- tests/lib/test_printfrr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c index 66699ec7c056..cefa07ec7323 100644 --- a/tests/lib/test_printfrr.c +++ b/tests/lib/test_printfrr.c @@ -143,6 +143,8 @@ int main(int argc, char **argv) NAN, }; uint64_t ui64 = 0xfeed1278cafef00d; + uint16_t i16 = -23456; + int_fast8_t if8 = 123; struct in_addr ip; char *p; char buf[256]; @@ -169,6 +171,16 @@ int main(int argc, char **argv) FMT_NSTD(printchk("11110000000011111010010111000011", "%b", 0xf00fa5c3)); FMT_NSTD(printchk("0b01011010", "%#010b", 0x5a)); +/* FMT_NSTD is conditional on the frr-format plugin being NOT enabled. + * However, the frr-format plugin does not support %wd/%wfd yet, so this needs + * to be unconditional. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat" + printchk("123 -23456 feed1278cafef00d 9876", "%wf8d %w16d %w64x %d", + if8, i16, ui64, 9876); +#pragma GCC diagnostic pop + inet_aton("192.168.1.2", &ip); printchk("192.168.1.2", "%pI4", &ip); printchk(" 192.168.1.2", "%20pI4", &ip); From a7ab0c943d36f0305798774c79bb665a8e8779d6 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 10 Mar 2024 13:21:37 +0100 Subject: [PATCH 3/4] lib/printf: update README Make a note that `%w[f](8|16|32|64)d` was picked up. Signed-off-by: David Lamparter --- lib/printf/README | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/printf/README b/lib/printf/README index 46d51cec6a93..3c3ef74ca8bb 100644 --- a/lib/printf/README +++ b/lib/printf/README @@ -1,6 +1,7 @@ This is the printf implementation from FreeBSD. The history of this code is: - imported on 2019-05-12, from SVN revision 347514 - resynced on 2023-09-03, to pick up `%b` implementation +- resynced on 2024-03-10, to pick up `%w[f](8|16|32|64)d` implementation Please don't reindent or otherwise mangle the files to make importing fixes easy (not that there are significant changes likely to happen...) From 02af04f73d547dd295c6e7d6ce34f2763b3b98ba Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 10 Mar 2024 13:40:19 +0100 Subject: [PATCH 4/4] doc: update re. ISO C23 printf changes The new `%w99d` fixed-width modifier still needs work in `frr-format`, which unfortunately is not as trivial as `%b` was. Signed-off-by: David Lamparter --- doc/developer/logging.rst | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst index 52653d37686c..6058b8c0fca4 100644 --- a/doc/developer/logging.rst +++ b/doc/developer/logging.rst @@ -77,7 +77,14 @@ are available: .. note:: - ``printfrr()`` does not support the ``%n`` format. + ``printfrr()`` does not support the ``%n`` format. It does support ISO C23 + ``%b``, ``%w99d`` and ``%wf99d`` additions, but the latter two are not + supported by the ``frr-format`` plugin yet, and all 3 aren't supported by + the older compilers still in use on some supported platforms. + + ``%b`` can be used with ``FMT_NSTD``, but ``%w99d`` and ``%wf99d`` require + work in the ``frr-format`` plugin before they are really usable. + AS-Safety ^^^^^^^^^ @@ -557,8 +564,9 @@ Integer formats cause compiler warnings when used without the plugin. Use with :c:macro:`FMT_NSTD` if necessary. - It is possible ISO C23 may introduce another format for these, possibly - ``%w64d`` discussed in `JTC 1/SC 22/WG 14/N2680 `_. + As anticipated, ISO C23 has introduced new modifiers for this, specifically + ``%w64d`` (= ``%Ld``) and ``%w64u`` (= ``%Lu``). Unfortunately, these new + modifiers are not supported by ``frr-format`` yet. .. frrfmt:: %Lu (uint64_t)