diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3 --- a/lib/libc/stdio/printf.3 +++ b/lib/libc/stdio/printf.3 @@ -31,7 +31,7 @@ .\" .\" @(#)printf.3 8.1 (Berkeley) 6/4/93 .\" -.Dd August 21, 2023 +.Dd September 5, 2023 .Dt PRINTF 3 .Os .Sh NAME @@ -342,6 +342,8 @@ .It Cm ll No (ell ell) Ta Vt "long long" Ta Vt "unsigned long long" Ta Vt "long long *" .It Cm j Ta Vt intmax_t Ta Vt uintmax_t Ta Vt "intmax_t *" .It Cm t Ta Vt ptrdiff_t Ta (see note) Ta Vt "ptrdiff_t *" +.It Cm w Ns Ar N Ta Vt intN_t Ta Vt uintN_t Ta Vt "intN_t *" +.It Cm wf Ns Ar N Ta Vt int_fastN_t Ta Vt uint_fastN_t Ta Vt "int_fastN_t *" .It Cm z Ta (see note) Ta Vt size_t Ta (see note) .It Cm q Em (deprecated) Ta Vt quad_t Ta Vt u_quad_t Ta Vt "quad_t *" .El diff --git a/lib/libc/stdio/printflocal.h b/lib/libc/stdio/printflocal.h --- a/lib/libc/stdio/printflocal.h +++ b/lib/libc/stdio/printflocal.h @@ -49,6 +49,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/libc/stdio/scanf.3 b/lib/libc/stdio/scanf.3 --- a/lib/libc/stdio/scanf.3 +++ b/lib/libc/stdio/scanf.3 @@ -31,7 +31,7 @@ .\" .\" @(#)scanf.3 8.2 (Berkeley) 12/11/93 .\" -.Dd August 21, 2023 +.Dd September 5, 2023 .Dt SCANF 3 .Os .Sh NAME @@ -217,6 +217,34 @@ .Vt ptrdiff_t (rather than .Vt int ) . +.It Cm w Ns Ar N +.Po +where +.Ar N +is 8, 16, 32, or 64 +.Pc +Indicates that the conversion will be one of +.Cm bdioux +or +.Cm n +and the next pointer is a pointer to a +.Vt intN_t +(rather than +.Vt int ) . +.It Cm wf Ns Ar N +.Po +where +.Ar N +is 8, 16, 32, or 64 +.Pc +Indicates that the conversion will be one of +.Cm bdioux +or +.Cm n +and the next pointer is a pointer to a +.Vt int_fastN_t +(rather than +.Vt int ) . .It Cm z Indicates that the conversion will be one of .Cm bdioux diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -610,6 +610,49 @@ 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 */ ; + fmt += 1; + } else if (fmt[0] == '1' && fmt[1] == '6') { + if (!(flags & FASTINT)) + flags |= SHORTINT; + else + /* 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; @@ -932,6 +975,7 @@ default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; +invalid: /* pretend it was %c with argument ch */ cp = buf; *cp = ch; diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c --- a/lib/libc/stdio/vfscanf.c +++ b/lib/libc/stdio/vfscanf.c @@ -75,6 +75,7 @@ #define SUPPRESS 0x08 /* *: suppress assignment */ #define POINTER 0x10 /* p: void * (as hex) */ #define NOSKIP 0x20 /* [ or c: do not skip blanks */ +#define FASTINT 0x200 /* wfN: int_fastN_t */ #define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */ #define INTMAXT 0x800 /* j: intmax_t */ #define PTRDIFFT 0x1000 /* t: ptrdiff_t */ @@ -555,6 +556,45 @@ case 't': flags |= PTRDIFFT; goto again; + 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 &= ~(SHORTSHORT|SHORT|LONG|LONGLONG|SIZET|INTMAXT|PTRDIFFT); + if (fmt[0] == 'f') { + flags |= FASTINT; + fmt++; + } else { + flags &= ~FASTINT; + } + if (fmt[0] == '8') { + if (!(flags & FASTINT)) + flags |= SHORTSHORT; + else + /* no flag set = 32 */ ; + fmt += 1; + } else if (fmt[0] == '1' && fmt[1] == '6') { + if (!(flags & FASTINT)) + flags |= SHORT; + else + /* 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 |= LONGLONG; + fmt += 2; + } else { + goto match_failure; + } + goto again; case 'z': flags |= SIZET; goto again; diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -681,6 +681,49 @@ 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 */ ; + fmt += 1; + } else if (fmt[0] == '1' && fmt[1] == '6') { + if (!(flags & FASTINT)) + flags |= SHORTINT; + else + /* 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; @@ -993,6 +1036,7 @@ default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; +invalid: /* pretend it was %c with argument ch */ cp = buf; *cp = ch; diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c --- a/lib/libc/stdio/vfwscanf.c +++ b/lib/libc/stdio/vfwscanf.c @@ -73,6 +73,7 @@ #define SUPPRESS 0x08 /* *: suppress assignment */ #define POINTER 0x10 /* p: void * (as hex) */ #define NOSKIP 0x20 /* [ or c: do not skip blanks */ +#define FASTINT 0x200 /* wfN: int_fastN_t */ #define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */ #define INTMAXT 0x800 /* j: intmax_t */ #define PTRDIFFT 0x1000 /* t: ptrdiff_t */ @@ -539,6 +540,45 @@ case 't': flags |= PTRDIFFT; goto again; + 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 &= ~(SHORTSHORT|SHORT|LONG|LONGLONG|SIZET|INTMAXT|PTRDIFFT); + if (fmt[0] == 'f') { + flags |= FASTINT; + fmt++; + } else { + flags &= ~FASTINT; + } + if (fmt[0] == '8') { + if (!(flags & FASTINT)) + flags |= SHORTSHORT; + else + /* no flag set = 32 */ ; + fmt += 1; + } else if (fmt[0] == '1' && fmt[1] == '6') { + if (!(flags & FASTINT)) + flags |= SHORT; + else + /* 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 |= LONGLONG; + fmt += 2; + } else { + goto match_failure; + } + goto again; case 'z': flags |= SIZET; goto again;