* [musl] [C23 printf 1/3] C23: implement the b and B printf specifiers
2023-05-31 14:04 [musl] [C23 printf 0/3] to be replaced Jens Gustedt
@ 2023-05-31 14:04 ` Jens Gustedt
2023-05-31 14:04 ` [musl] [C23 printf 2/3] C23: implement the wN length specifiers for printf Jens Gustedt
2023-05-31 14:04 ` [musl] [C23 printf 3/3] C23: implement the wfN length modifiers " Jens Gustedt
2 siblings, 0 replies; 4+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:04 UTC (permalink / raw)
To: musl
The b specifier is mandatory for C23. It has been reserved previously,
so we may safely add it, even for older compilation modes.
The B specifier is optional, but recommended for those implementations
that didn't have it reserved previously for other purposes.
The PRIbXXX and PRIBXXX macros are mandatory if the specifiers are
supported and may serve as feature test macros for users.
---
include/inttypes.h | 34 ++++++++++++++++++++++++++++++++++
src/stdio/vfprintf.c | 19 ++++++++++++++++++-
src/stdio/vfwprintf.c | 11 +++++++++--
3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/include/inttypes.h b/include/inttypes.h
index 61dcb727..73a42e32 100644
--- a/include/inttypes.h
+++ b/include/inttypes.h
@@ -120,12 +120,44 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
#define PRIXFAST32 "X"
#define PRIXFAST64 __PRI64 "X"
+#define PRIb8 "b"
+#define PRIb16 "b"
+#define PRIb32 "b"
+#define PRIb64 __PRI64 "b"
+
+#define PRIbLEAST8 "b"
+#define PRIbLEAST16 "b"
+#define PRIbLEAST32 "b"
+#define PRIbLEAST64 __PRI64 "b"
+
+#define PRIbFAST8 "b"
+#define PRIbFAST16 "b"
+#define PRIbFAST32 "b"
+#define PRIbFAST64 __PRI64 "b"
+
+#define PRIB8 "B"
+#define PRIB16 "B"
+#define PRIB32 "B"
+#define PRIB64 __PRI64 "B"
+
+#define PRIBLEAST8 "B"
+#define PRIBLEAST16 "B"
+#define PRIBLEAST32 "B"
+#define PRIBLEAST64 __PRI64 "B"
+
+#define PRIBFAST8 "B"
+#define PRIBFAST16 "B"
+#define PRIBFAST32 "B"
+#define PRIBFAST64 __PRI64 "B"
+
#define PRIdMAX __PRI64 "d"
#define PRIiMAX __PRI64 "i"
#define PRIoMAX __PRI64 "o"
#define PRIuMAX __PRI64 "u"
#define PRIxMAX __PRI64 "x"
#define PRIXMAX __PRI64 "X"
+#define PRIbMAX __PRI64 "b"
+#define PRIBMAX __PRI64 "B"
#define PRIdPTR __PRIPTR "d"
#define PRIiPTR __PRIPTR "i"
@@ -133,6 +165,8 @@ uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int);
#define PRIuPTR __PRIPTR "u"
#define PRIxPTR __PRIPTR "x"
#define PRIXPTR __PRIPTR "X"
+#define PRIbPTR __PRIPTR "b"
+#define PRIBPTR __PRIPTR "B"
#define SCNd8 "hhd"
#define SCNd16 "hd"
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index a712d80f..cbc79783 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -48,6 +48,7 @@ enum {
static const unsigned char states[]['z'-'A'+1] = {
{ /* 0: bare types */
+ S('b') = UINT, S('B') = UINT,
S('d') = INT, S('i') = INT,
S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
@@ -58,6 +59,7 @@ static const unsigned char states[]['z'-'A'+1] = {
S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
}, { /* 1: l-prefixed */
+ S('b') = ULONG, S('B') = ULONG,
S('d') = LONG, S('i') = LONG,
S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
@@ -65,17 +67,20 @@ static const unsigned char states[]['z'-'A'+1] = {
S('c') = INT, S('s') = PTR, S('n') = PTR,
S('l') = LLPRE,
}, { /* 2: ll-prefixed */
+ S('b') = ULLONG, S('B') = ULLONG,
S('d') = LLONG, S('i') = LLONG,
S('o') = ULLONG, S('u') = ULLONG,
S('x') = ULLONG, S('X') = ULLONG,
S('n') = PTR,
}, { /* 3: h-prefixed */
+ S('b') = USHORT, S('B') = USHORT,
S('d') = SHORT, S('i') = SHORT,
S('o') = USHORT, S('u') = USHORT,
S('x') = USHORT, S('X') = USHORT,
S('n') = PTR,
S('h') = HHPRE,
}, { /* 4: hh-prefixed */
+ S('b') = UCHAR, S('B') = UCHAR,
S('d') = CHAR, S('i') = CHAR,
S('o') = UCHAR, S('u') = UCHAR,
S('x') = UCHAR, S('X') = UCHAR,
@@ -85,11 +90,13 @@ static const unsigned char states[]['z'-'A'+1] = {
S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
S('n') = PTR,
}, { /* 6: z- or t-prefixed (assumed to be same size) */
+ S('b') = SIZET, S('B') = SIZET,
S('d') = PDIFF, S('i') = PDIFF,
S('o') = SIZET, S('u') = SIZET,
S('x') = SIZET, S('X') = SIZET,
S('n') = PTR,
}, { /* 7: j-prefixed */
+ S('b') = UMAX, S('B') = UMAX,
S('d') = IMAX, S('i') = IMAX,
S('o') = UMAX, S('u') = UMAX,
S('x') = UMAX, S('X') = UMAX,
@@ -156,6 +163,12 @@ static char *fmt_x(uintmax_t x, char *s, int lower)
return s;
}
+static char *fmt_b(uintmax_t x, char *s)
+{
+ for (; x; x>>=1) *--s = '0' + (x&1);
+ return s;
+}
+
static char *fmt_o(uintmax_t x, char *s)
{
for (; x; x>>=3) *--s = '0' + (x&7);
@@ -437,7 +450,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
unsigned st, ps;
int cnt=0, l=0;
size_t i;
- char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
+ char buf[sizeof(uintmax_t)*CHAR_BIT+3+LDBL_MANT_DIG/4];
const char *prefix;
int t, pl;
wchar_t wc[2], *ws;
@@ -564,6 +577,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
a = fmt_x(arg.i, z, t&32);
if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
if (0) {
+ case 'b': case 'B':
+ a = fmt_b(arg.i, z);
+ if (arg.i && (fl & ALT_FORM)) prefix = (t == 'b' ? "0b" : "0B"), pl=2;
+ } if (0) {
case 'o':
a = fmt_o(arg.i, z);
if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c
index 53697701..dbc93f74 100644
--- a/src/stdio/vfwprintf.c
+++ b/src/stdio/vfwprintf.c
@@ -41,6 +41,7 @@ enum {
static const unsigned char states[]['z'-'A'+1] = {
{ /* 0: bare types */
+ S('b') = UINT, S('B') = UINT,
S('d') = INT, S('i') = INT,
S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
@@ -51,6 +52,7 @@ static const unsigned char states[]['z'-'A'+1] = {
S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
}, { /* 1: l-prefixed */
+ S('b') = ULONG, S('B') = ULONG,
S('d') = LONG, S('i') = LONG,
S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
@@ -58,17 +60,20 @@ static const unsigned char states[]['z'-'A'+1] = {
S('c') = INT, S('s') = PTR, S('n') = PTR,
S('l') = LLPRE,
}, { /* 2: ll-prefixed */
+ S('b') = ULLONG, S('B') = ULLONG,
S('d') = LLONG, S('i') = LLONG,
S('o') = ULLONG, S('u') = ULLONG,
S('x') = ULLONG, S('X') = ULLONG,
S('n') = PTR,
}, { /* 3: h-prefixed */
+ S('b') = USHORT, S('B') = USHORT,
S('d') = SHORT, S('i') = SHORT,
S('o') = USHORT, S('u') = USHORT,
S('x') = USHORT, S('X') = USHORT,
S('n') = PTR,
S('h') = HHPRE,
}, { /* 4: hh-prefixed */
+ S('b') = UCHAR, S('B') = UCHAR,
S('d') = CHAR, S('i') = CHAR,
S('o') = UCHAR, S('u') = UCHAR,
S('x') = UCHAR, S('X') = UCHAR,
@@ -78,11 +83,13 @@ static const unsigned char states[]['z'-'A'+1] = {
S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
S('n') = PTR,
}, { /* 6: z- or t-prefixed (assumed to be same size) */
+ S('b') = SIZET, S('B') = SIZET,
S('d') = PDIFF, S('i') = PDIFF,
S('o') = SIZET, S('u') = SIZET,
S('x') = SIZET, S('X') = SIZET,
S('n') = PTR,
}, { /* 7: j-prefixed */
+ S('b') = UMAX, S('B') = UMAX,
S('d') = IMAX, S('i') = IMAX,
S('o') = UMAX, S('u') = UMAX,
S('x') = UMAX, S('X') = UMAX,
@@ -145,7 +152,7 @@ static int getint(wchar_t **s) {
static const char sizeprefix['y'-'a'] = {
['a'-'a']='L', ['e'-'a']='L', ['f'-'a']='L', ['g'-'a']='L',
-['d'-'a']='j', ['i'-'a']='j', ['o'-'a']='j', ['u'-'a']='j', ['x'-'a']='j',
+['b'-'a']='j', ['d'-'a']='j', ['i'-'a']='j', ['o'-'a']='j', ['u'-'a']='j', ['x'-'a']='j',
['p'-'a']='j'
};
@@ -321,7 +328,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
case 'a': case 'e': case 'f': case 'g':
l = fprintf(f, charfmt, w, p, arg.f);
break;
- case 'd': case 'i': case 'o': case 'u': case 'x': case 'p':
+ case 'b': case 'd': case 'i': case 'o': case 'u': case 'x': case 'p':
l = fprintf(f, charfmt, w, p, arg.i);
break;
}
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [musl] [C23 printf 2/3] C23: implement the wN length specifiers for printf
2023-05-31 14:04 [musl] [C23 printf 0/3] to be replaced Jens Gustedt
2023-05-31 14:04 ` [musl] [C23 printf 1/3] C23: implement the b and B printf specifiers Jens Gustedt
@ 2023-05-31 14:04 ` Jens Gustedt
2023-05-31 14:04 ` [musl] [C23 printf 3/3] C23: implement the wfN length modifiers " Jens Gustedt
2 siblings, 0 replies; 4+ messages in thread
From: Jens Gustedt @ 2023-05-31 14:04 UTC (permalink / raw)
To: musl
These are mandatory for C23 and concern all types for which the
platform has `int_leastN_t` and `uint_leastN_t`. For musl these types
always coincide with `intN_t` and `uintN_t` and are always present for
N equal 8, 16, 32 and 64.
They can be added for general use since all lowercase letters were
previously reserved.
Nevertheless, users that use these modifiers will see a lot of
warnings from compilers in the beginning. This is because the
compilers have not yet integrated this form of a specifier into their
correponding extensions (gcc attributes). So unfortunately also
testing this feature may be a bit noisy for the moment.
The only architecture dependend choice is the type for N == 64, which
may be `long` or `long long`. We just mimick the test that is done in
other places to compare `UINTPTR_MAX` and `UINT64_MAX` to determine
that.
---
src/stdio/vfprintf.c | 28 +++++++++++++++++++++++++---
src/stdio/vfwprintf.c | 28 +++++++++++++++++++++++++---
2 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index cbc79783..265fb7ad 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -33,7 +33,7 @@
enum {
BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
- ZTPRE, JPRE,
+ ZTPRE, JPRE, WPRE,
STOP,
PTR, INT, UINT, ULLONG,
LONG, ULONG,
@@ -57,7 +57,7 @@ static const unsigned char states[]['z'-'A'+1] = {
S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
S('m') = NOARG,
S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
- S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE, S('w') = WPRE,
}, { /* 1: l-prefixed */
S('b') = ULONG, S('B') = ULONG,
S('d') = LONG, S('i') = LONG,
@@ -101,6 +101,12 @@ static const unsigned char states[]['z'-'A'+1] = {
S('o') = UMAX, S('u') = UMAX,
S('x') = UMAX, S('X') = UMAX,
S('n') = PTR,
+ }, { /* 8: w-prefixed */
+ S('b') = UINT, S('B') = UINT,
+ S('d') = INT, S('i') = INT,
+ S('o') = UINT, S('u') = UINT,
+ S('x') = UINT, S('X') = UINT,
+ S('n') = PTR,
}
};
@@ -447,7 +453,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
int w, p, xp;
union arg arg;
int argpos;
- unsigned st, ps;
+ unsigned st, ps, width=0;
int cnt=0, l=0;
size_t i;
char buf[sizeof(uintmax_t)*CHAR_BIT+3+LDBL_MANT_DIG/4];
@@ -527,9 +533,25 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
if (OOB(*s)) goto inval;
ps=st;
st=states[st]S(*s++);
+ if (st == WPRE) {
+ if (*s == '0') goto inval;
+ width = getint(&s);
+ }
} while (st-1<STOP);
if (!st) goto inval;
+ if (ps == WPRE) switch (width) {
+ case 8: ps = HHPRE; st = (st == UINT) ? UCHAR : ((st == INT) ? CHAR : PTR); break;
+ case 16: ps = HPRE; st = (st == UINT) ? USHORT : ((st == INT) ? SHORT : PTR); break;
+ case 32: ps = BARE; break;
+#if UINTPTR_MAX >= UINT64_MAX
+ case 64: ps = LPRE; st = (st == UINT) ? ULONG : ((st == INT) ? LONG : PTR); break;
+#else
+ case 64: ps = LLPRE; st = (st == UINT) ? ULLONG : ((st == INT) ? LLONG : PTR); break;
+#endif
+ default: goto inval;
+ }
+
/* Check validity of argument type (nl/normal) */
if (st==NOARG) {
if (argpos>=0) goto inval;
diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c
index dbc93f74..c3e81d2a 100644
--- a/src/stdio/vfwprintf.c
+++ b/src/stdio/vfwprintf.c
@@ -26,7 +26,7 @@
enum {
BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
- ZTPRE, JPRE,
+ ZTPRE, JPRE, WPRE,
STOP,
PTR, INT, UINT, ULLONG,
LONG, ULONG,
@@ -50,7 +50,7 @@ static const unsigned char states[]['z'-'A'+1] = {
S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
S('m') = NOARG,
S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
- S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE, S('w') = WPRE,
}, { /* 1: l-prefixed */
S('b') = ULONG, S('B') = ULONG,
S('d') = LONG, S('i') = LONG,
@@ -94,6 +94,12 @@ static const unsigned char states[]['z'-'A'+1] = {
S('o') = UMAX, S('u') = UMAX,
S('x') = UMAX, S('X') = UMAX,
S('n') = PTR,
+ }, { /* 8: w-prefixed */
+ S('b') = UINT, S('B') = UINT,
+ S('d') = INT, S('i') = INT,
+ S('o') = UINT, S('u') = UINT,
+ S('x') = UINT, S('X') = UINT,
+ S('n') = PTR,
}
};
@@ -163,7 +169,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
int w, p, xp;
union arg arg;
int argpos;
- unsigned st, ps;
+ unsigned st, ps, width=0;
int cnt=0, l=0;
int i;
int t;
@@ -242,9 +248,25 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
if (OOB(*s)) goto inval;
ps=st;
st=states[st]S(*s++);
+ if (st == WPRE) {
+ if (*s == L'0') goto inval;
+ width = getint(&s);
+ }
} while (st-1<STOP);
if (!st) goto inval;
+ if (ps == WPRE) switch (width) {
+ case 8: ps = HHPRE; st = (st == UINT) ? UCHAR : ((st == INT) ? CHAR : PTR); break;
+ case 16: ps = HPRE; st = (st == UINT) ? USHORT : ((st == INT) ? SHORT : PTR); break;
+ case 32: ps = BARE; break;
+#if UINTPTR_MAX >= UINT64_MAX
+ case 64: ps = LPRE; st = (st == UINT) ? ULONG : ((st == INT) ? LONG : PTR); break;
+#else
+ case 64: ps = LLPRE; st = (st == UINT) ? ULLONG : ((st == INT) ? LLONG : PTR); break;
+#endif
+ default: goto inval;
+ }
+
/* Check validity of argument type (nl/normal) */
if (st==NOARG) {
if (argpos>=0) goto inval;
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread