pr_info("probing failed (%dE)\n", ret);

expands to

        probing failed (EIO)

if ret holds -EIO (or EIO). This introduces an array of error codes. If
the error code is missing, %dE falls back to %d and so prints the plain
number.

Signed-off-by: Uwe Kleine-König <u...@kleine-koenig.org>
---
Hello

there are many code sites that benefit from this. Just grep for
"(%d)" ...

As an example the follow up patch converts a printk to use this new
format escape.

Best regards
Uwe

 Documentation/core-api/printk-formats.rst |   3 +
 lib/vsprintf.c                            | 193 +++++++++++++++++++++-
 2 files changed, 195 insertions(+), 1 deletion(-)

diff --git a/Documentation/core-api/printk-formats.rst 
b/Documentation/core-api/printk-formats.rst
index c6224d039bcb..81002414f956 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -35,6 +35,9 @@ Integer types
                u64                     %llu or %llx
 
 
+To print the name that corresponds to an integer error constant, use %dE and
+pass the int.
+
 If <type> is dependent on a config option for its size (e.g., sector_t,
 blkcnt_t) or is architecture-dependent for its size (e.g., tcflag_t), use a
 format specifier of its largest possible type and explicitly cast to it.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b0967cf17137..672eab8dab84 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -533,6 +533,192 @@ char *number(char *buf, char *end, unsigned long long num,
        return buf;
 }
 
+#define ERRORCODE(x) { .str = #x, .err = x }
+
+static const struct {
+       const char *str;
+       int err;
+} errorcodes[] = {
+       ERRORCODE(EPERM),
+       ERRORCODE(ENOENT),
+       ERRORCODE(ESRCH),
+       ERRORCODE(EINTR),
+       ERRORCODE(EIO),
+       ERRORCODE(ENXIO),
+       ERRORCODE(E2BIG),
+       ERRORCODE(ENOEXEC),
+       ERRORCODE(EBADF),
+       ERRORCODE(ECHILD),
+       ERRORCODE(EAGAIN),
+       ERRORCODE(ENOMEM),
+       ERRORCODE(EACCES),
+       ERRORCODE(EFAULT),
+       ERRORCODE(ENOTBLK),
+       ERRORCODE(EBUSY),
+       ERRORCODE(EEXIST),
+       ERRORCODE(EXDEV),
+       ERRORCODE(ENODEV),
+       ERRORCODE(ENOTDIR),
+       ERRORCODE(EISDIR),
+       ERRORCODE(EINVAL),
+       ERRORCODE(ENFILE),
+       ERRORCODE(EMFILE),
+       ERRORCODE(ENOTTY),
+       ERRORCODE(ETXTBSY),
+       ERRORCODE(EFBIG),
+       ERRORCODE(ENOSPC),
+       ERRORCODE(ESPIPE),
+       ERRORCODE(EROFS),
+       ERRORCODE(EMLINK),
+       ERRORCODE(EPIPE),
+       ERRORCODE(EDOM),
+       ERRORCODE(ERANGE),
+       ERRORCODE(EDEADLK),
+       ERRORCODE(ENAMETOOLONG),
+       ERRORCODE(ENOLCK),
+       ERRORCODE(ENOSYS),
+       ERRORCODE(ENOTEMPTY),
+       ERRORCODE(ELOOP),
+       ERRORCODE(EWOULDBLOCK),
+       ERRORCODE(ENOMSG),
+       ERRORCODE(EIDRM),
+       ERRORCODE(ECHRNG),
+       ERRORCODE(EL2NSYNC),
+       ERRORCODE(EL3HLT),
+       ERRORCODE(EL3RST),
+       ERRORCODE(ELNRNG),
+       ERRORCODE(EUNATCH),
+       ERRORCODE(ENOCSI),
+       ERRORCODE(EL2HLT),
+       ERRORCODE(EBADE),
+       ERRORCODE(EBADR),
+       ERRORCODE(EXFULL),
+       ERRORCODE(ENOANO),
+       ERRORCODE(EBADRQC),
+       ERRORCODE(EBADSLT),
+       ERRORCODE(EBFONT),
+       ERRORCODE(ENOSTR),
+       ERRORCODE(ENODATA),
+       ERRORCODE(ETIME),
+       ERRORCODE(ENOSR),
+       ERRORCODE(ENONET),
+       ERRORCODE(ENOPKG),
+       ERRORCODE(EREMOTE),
+       ERRORCODE(ENOLINK),
+       ERRORCODE(EADV),
+       ERRORCODE(ESRMNT),
+       ERRORCODE(ECOMM),
+       ERRORCODE(EPROTO),
+       ERRORCODE(EMULTIHOP),
+       ERRORCODE(EDOTDOT),
+       ERRORCODE(EBADMSG),
+       ERRORCODE(EOVERFLOW),
+       ERRORCODE(ENOTUNIQ),
+       ERRORCODE(EBADFD),
+       ERRORCODE(EREMCHG),
+       ERRORCODE(ELIBACC),
+       ERRORCODE(ELIBBAD),
+       ERRORCODE(ELIBSCN),
+       ERRORCODE(ELIBMAX),
+       ERRORCODE(ELIBEXEC),
+       ERRORCODE(EILSEQ),
+       ERRORCODE(ERESTART),
+       ERRORCODE(ESTRPIPE),
+       ERRORCODE(EUSERS),
+       ERRORCODE(ENOTSOCK),
+       ERRORCODE(EDESTADDRREQ),
+       ERRORCODE(EMSGSIZE),
+       ERRORCODE(EPROTOTYPE),
+       ERRORCODE(ENOPROTOOPT),
+       ERRORCODE(EPROTONOSUPPORT),
+       ERRORCODE(ESOCKTNOSUPPORT),
+       ERRORCODE(EOPNOTSUPP),
+       ERRORCODE(EPFNOSUPPORT),
+       ERRORCODE(EAFNOSUPPORT),
+       ERRORCODE(EADDRINUSE),
+       ERRORCODE(EADDRNOTAVAIL),
+       ERRORCODE(ENETDOWN),
+       ERRORCODE(ENETUNREACH),
+       ERRORCODE(ENETRESET),
+       ERRORCODE(ECONNABORTED),
+       ERRORCODE(ECONNRESET),
+       ERRORCODE(ENOBUFS),
+       ERRORCODE(EISCONN),
+       ERRORCODE(ENOTCONN),
+       ERRORCODE(ESHUTDOWN),
+       ERRORCODE(ETOOMANYREFS),
+       ERRORCODE(ETIMEDOUT),
+       ERRORCODE(ECONNREFUSED),
+       ERRORCODE(EHOSTDOWN),
+       ERRORCODE(EHOSTUNREACH),
+       ERRORCODE(EALREADY),
+       ERRORCODE(EINPROGRESS),
+       ERRORCODE(ESTALE),
+       ERRORCODE(EUCLEAN),
+       ERRORCODE(ENOTNAM),
+       ERRORCODE(ENAVAIL),
+       ERRORCODE(EISNAM),
+       ERRORCODE(EREMOTEIO),
+       ERRORCODE(EDQUOT),
+       ERRORCODE(ENOMEDIUM),
+       ERRORCODE(EMEDIUMTYPE),
+       ERRORCODE(ECANCELED),
+       ERRORCODE(ENOKEY),
+       ERRORCODE(EKEYEXPIRED),
+       ERRORCODE(EKEYREVOKED),
+       ERRORCODE(EKEYREJECTED),
+       ERRORCODE(EOWNERDEAD),
+       ERRORCODE(ENOTRECOVERABLE),
+       ERRORCODE(ERFKILL),
+       ERRORCODE(EHWPOISON),
+       ERRORCODE(ERESTARTSYS),
+       ERRORCODE(ERESTARTNOINTR),
+       ERRORCODE(ERESTARTNOHAND),
+       ERRORCODE(ENOIOCTLCMD),
+       ERRORCODE(ERESTART_RESTARTBLOCK),
+       ERRORCODE(EPROBE_DEFER),
+       ERRORCODE(EOPENSTALE),
+       ERRORCODE(ENOPARAM),
+       ERRORCODE(EBADHANDLE),
+       ERRORCODE(ENOTSYNC),
+       ERRORCODE(EBADCOOKIE),
+       ERRORCODE(ENOTSUPP),
+       ERRORCODE(ETOOSMALL),
+       ERRORCODE(ESERVERFAULT),
+       ERRORCODE(EBADTYPE),
+       ERRORCODE(EJUKEBOX),
+       ERRORCODE(EIOCBQUEUED),
+       ERRORCODE(ERECALLCONFLICT),
+};
+
+static noinline_for_stack
+char *errstr(char *buf, char *end, unsigned long long num,
+            struct printf_spec spec)
+{
+       char *errname = NULL;
+       size_t errnamelen, copy;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(errorcodes); ++i) {
+               if (num == errorcodes[i].err || num == -errorcodes[i].err) {
+                       errname = errorcodes[i].str;
+                       break;
+               }
+       }
+
+       if (!errname) {
+               /* fall back to ordinary number */
+               return number(buf, end, num, spec);
+       }
+
+       copy = errnamelen = strlen(errname);
+       if (copy > end - buf)
+               copy = end - buf;
+       buf = memcpy(buf, errname, copy);
+
+       return buf + errnamelen;
+}
+
 static noinline_for_stack
 char *special_hex_number(char *buf, char *end, unsigned long long num, int 
size)
 {
@@ -2566,7 +2752,12 @@ 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 (spec.type == FORMAT_TYPE_INT && *fmt == 'E') {
+                               fmt++;
+                               str = errstr(str, end, num, spec);
+                       } else {
+                               str = number(str, end, num, spec);
+                       }
                }
        }
 
-- 
2.20.1

Reply via email to