Messages in this thread Patch in this message | | | From | Uwe Kleine-König <> | Subject | [PATCH 1/2] printf: add support for printing symbolic error names from numbers | Date | Mon, 20 Jan 2020 09:55:07 +0100 |
| |
This is an extension of the ability introduced in commit 57f5677e535b ("printf: add support for printing symbolic error names") that made %pe consume an error valued pointer and emit a symbolic error name.
Here the same is done for numbers:
printk("%de\n", -EIO);
now emits "-EIO\n".
To keep printk flexible enough to emit an 'e' after a number the character ` can be used which is just swallowed by *printf and ends interpreting the format code. So
printk("%d`e\n", -5);
emits "-5e\n". (Note that the implementation of ` isn't complete, it only works for numbers for now. It might make sense to implement the same for %s and %p.)
For non-error valued numbers %de falls back to emit the plain number (as %d would do).
Some runtime tests are added to cover %de.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- lib/test_printf.c | 8 ++++++++ lib/vsprintf.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/lib/test_printf.c b/lib/test_printf.c index 2d9f520d2f27..a18a7742d5fe 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -13,6 +13,7 @@ #include <linux/rtc.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/stringify.h> #include <linux/bitmap.h> #include <linux/dcache.h> @@ -628,6 +629,8 @@ static void __init errptr(void) { test("-1234", "%pe", ERR_PTR(-1234)); + test("-4321", "%de", -4321); + test("-5e", "%d`e", -5); /* Check that %pe with a non-ERR_PTR gets treated as ordinary %p. */ BUILD_BUG_ON(IS_ERR(PTR)); @@ -641,6 +644,11 @@ errptr(void) test("[-EIO ]", "[%-8pe]", ERR_PTR(-EIO)); test("[ -EIO]", "[%8pe]", ERR_PTR(-EIO)); test("-EPROBE_DEFER", "%pe", ERR_PTR(-EPROBE_DEFER)); + + test("-ERESTARTSYS", "%de", -ERESTARTSYS); +#else + + test("-" __stringify(ERESTARTSYS), "%de", -ERESTARTSYS); #endif } diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 7c488a1ce318..1bcd1ce2c319 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2637,7 +2637,39 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) num = va_arg(args, unsigned int); } - str = number(str, end, num, spec); + if (*fmt != 'e') { + str = number(str, end, num, spec); + } else { + unsigned long num_err = 0; + + fmt++; + + /* + * error values are negative numbers near zero. + * If num represents such a number, it must be + * big (as it is unsigned), otherwise print it + * as an ordinary number. + */ + if (num > (unsigned long long)-UINT_MAX) + num_err = num; + + if (IS_ENABLED(CONFIG_SYMBOLIC_ERRNAME) && + IS_ERR_VALUE(num_err)) + str = err_ptr(str, end, ERR_PTR(num), spec); + else + str = number(str, end, num, spec); + } + + if (*fmt == '`') + /* + * When a format specifier is followed by `, + * this ends parsing. This way a string can be + * printed that has an int followed by a literal + * 'e' (using "%d`e") which otherwise (i.e. by + * using "%de") would be interpreted as request + * to format the int as error code. + */ + ++fmt; } } -- 2.24.0
| |