MALI: midgard: support sharing regulator with other devices
[firefly-linux-kernel-4.4.55.git] / lib / vsprintf.c
index e149c6416384a2a335783f0db538e030e90e6e69..f9cee8e1233c0fe0f626fe2680ca4b9ff9d3153e 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <stdarg.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/module.h>      /* for KSYM_SYMBOL_LEN */
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/math64.h>
 #include <linux/uaccess.h>
 #include <linux/ioport.h>
+#include <linux/dcache.h>
+#include <linux/cred.h>
 #include <net/addrconf.h>
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/sections.h>      /* for dereference_function_descriptor() */
+#include <asm/byteorder.h>     /* cpu_to_le16 */
 
+#include <linux/string_helpers.h>
 #include "kstrtox.h"
 
 /**
@@ -111,148 +117,152 @@ int skip_atoi(const char **s)
 {
        int i = 0;
 
-       while (isdigit(**s))
+       do {
                i = i*10 + *((*s)++) - '0';
+       } while (isdigit(**s));
 
        return i;
 }
 
-/* Decimal conversion is by far the most typical, and is used
- * for /proc and /sys data. This directly impacts e.g. top performance
- * with many processes running. We optimize it for speed
- * using ideas described at <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
- * (with permission from the author, Douglas W. Jones).
+/*
+ * Decimal conversion is by far the most typical, and is used for
+ * /proc and /sys data. This directly impacts e.g. top performance
+ * with many processes running. We optimize it for speed by emitting
+ * two characters at a time, using a 200 byte lookup table. This
+ * roughly halves the number of multiplications compared to computing
+ * the digits one at a time. Implementation strongly inspired by the
+ * previous version, which in turn used ideas described at
+ * <http://www.cs.uiowa.edu/~jones/bcd/divide.html> (with permission
+ * from the author, Douglas W. Jones).
+ *
+ * It turns out there is precisely one 26 bit fixed-point
+ * approximation a of 64/100 for which x/100 == (x * (u64)a) >> 32
+ * holds for all x in [0, 10^8-1], namely a = 0x28f5c29. The actual
+ * range happens to be somewhat larger (x <= 1073741898), but that's
+ * irrelevant for our purpose.
+ *
+ * For dividing a number in the range [10^4, 10^6-1] by 100, we still
+ * need a 32x32->64 bit multiply, so we simply use the same constant.
+ *
+ * For dividing a number in the range [100, 10^4-1] by 100, there are
+ * several options. The simplest is (x * 0x147b) >> 19, which is valid
+ * for all x <= 43698.
  */
 
-#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
-/* Formats correctly any integer in [0, 999999999] */
+static const u16 decpair[100] = {
+#define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030)
+       _( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9),
+       _(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19),
+       _(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29),
+       _(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39),
+       _(40), _(41), _(42), _(43), _(44), _(45), _(46), _(47), _(48), _(49),
+       _(50), _(51), _(52), _(53), _(54), _(55), _(56), _(57), _(58), _(59),
+       _(60), _(61), _(62), _(63), _(64), _(65), _(66), _(67), _(68), _(69),
+       _(70), _(71), _(72), _(73), _(74), _(75), _(76), _(77), _(78), _(79),
+       _(80), _(81), _(82), _(83), _(84), _(85), _(86), _(87), _(88), _(89),
+       _(90), _(91), _(92), _(93), _(94), _(95), _(96), _(97), _(98), _(99),
+#undef _
+};
+
+/*
+ * This will print a single '0' even if r == 0, since we would
+ * immediately jump to out_r where two 0s would be written but only
+ * one of them accounted for in buf. This is needed by ip4_string
+ * below. All other callers pass a non-zero value of r.
+*/
 static noinline_for_stack
-char *put_dec_full9(char *buf, unsigned q)
+char *put_dec_trunc8(char *buf, unsigned r)
 {
-       unsigned r;
+       unsigned q;
 
-       /*
-        * Possible ways to approx. divide by 10
-        * (x * 0x1999999a) >> 32 x < 1073741829 (multiply must be 64-bit)
-        * (x * 0xcccd) >> 19     x <      81920 (x < 262149 when 64-bit mul)
-        * (x * 0x6667) >> 18     x <      43699
-        * (x * 0x3334) >> 17     x <      16389
-        * (x * 0x199a) >> 16     x <      16389
-        * (x * 0x0ccd) >> 15     x <      16389
-        * (x * 0x0667) >> 14     x <       2739
-        * (x * 0x0334) >> 13     x <       1029
-        * (x * 0x019a) >> 12     x <       1029
-        * (x * 0x00cd) >> 11     x <       1029 shorter code than * 0x67 (on i386)
-        * (x * 0x0067) >> 10     x <        179
-        * (x * 0x0034) >>  9     x <         69 same
-        * (x * 0x001a) >>  8     x <         69 same
-        * (x * 0x000d) >>  7     x <         69 same, shortest code (on i386)
-        * (x * 0x0007) >>  6     x <         19
-        * See <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
-        */
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 1 */
-       q      = (r * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (r - 10 * q) + '0'; /* 2 */
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 3 */
-       q      = (r * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (r - 10 * q) + '0'; /* 4 */
-       r      = (q * (uint64_t)0x1999999a) >> 32;
-       *buf++ = (q - 10 * r) + '0'; /* 5 */
-       /* Now value is under 10000, can avoid 64-bit multiply */
-       q      = (r * 0x199a) >> 16;
-       *buf++ = (r - 10 * q)  + '0'; /* 6 */
-       r      = (q * 0xcd) >> 11;
-       *buf++ = (q - 10 * r)  + '0'; /* 7 */
-       q      = (r * 0xcd) >> 11;
-       *buf++ = (r - 10 * q) + '0'; /* 8 */
-       *buf++ = q + '0'; /* 9 */
+       /* 1 <= r < 10^8 */
+       if (r < 100)
+               goto out_r;
+
+       /* 100 <= r < 10^8 */
+       q = (r * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
+
+       /* 1 <= q < 10^6 */
+       if (q < 100)
+               goto out_q;
+
+       /*  100 <= q < 10^6 */
+       r = (q * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[q - 100*r];
+       buf += 2;
+
+       /* 1 <= r < 10^4 */
+       if (r < 100)
+               goto out_r;
+
+       /* 100 <= r < 10^4 */
+       q = (r * 0x147b) >> 19;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
+out_q:
+       /* 1 <= q < 100 */
+       r = q;
+out_r:
+       /* 1 <= r < 100 */
+       *((u16 *)buf) = decpair[r];
+       buf += r < 10 ? 1 : 2;
        return buf;
 }
-#endif
 
-/* Similar to above but do not pad with zeros.
- * Code can be easily arranged to print 9 digits too, but our callers
- * always call put_dec_full9() instead when the number has 9 decimal digits.
- */
+#if BITS_PER_LONG == 64 && BITS_PER_LONG_LONG == 64
 static noinline_for_stack
-char *put_dec_trunc8(char *buf, unsigned r)
+char *put_dec_full8(char *buf, unsigned r)
 {
        unsigned q;
 
-       /* Copy of previous function's body with added early returns */
-       while (r >= 10000) {
-               q = r + '0';
-               r  = (r * (uint64_t)0x1999999a) >> 32;
-               *buf++ = q - 10*r;
-       }
-
-       q      = (r * 0x199a) >> 16;    /* r <= 9999 */
-       *buf++ = (r - 10 * q)  + '0';
-       if (q == 0)
-               return buf;
-       r      = (q * 0xcd) >> 11;      /* q <= 999 */
-       *buf++ = (q - 10 * r)  + '0';
-       if (r == 0)
-               return buf;
-       q      = (r * 0xcd) >> 11;      /* r <= 99 */
-       *buf++ = (r - 10 * q) + '0';
-       if (q == 0)
-               return buf;
-       *buf++ = q + '0';                /* q <= 9 */
-       return buf;
-}
+       /* 0 <= r < 10^8 */
+       q = (r * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
 
-/* There are two algorithms to print larger numbers.
- * One is generic: divide by 1000000000 and repeatedly print
- * groups of (up to) 9 digits. It's conceptually simple,
- * but requires a (unsigned long long) / 1000000000 division.
- *
- * Second algorithm splits 64-bit unsigned long long into 16-bit chunks,
- * manipulates them cleverly and generates groups of 4 decimal digits.
- * It so happens that it does NOT require long long division.
- *
- * If long is > 32 bits, division of 64-bit values is relatively easy,
- * and we will use the first algorithm.
- * If long long is > 64 bits (strange architecture with VERY large long long),
- * second algorithm can't be used, and we again use the first one.
- *
- * Else (if long is 32 bits and long long is 64 bits) we use second one.
- */
+       /* 0 <= q < 10^6 */
+       r = (q * (u64)0x28f5c29) >> 32;
+       *((u16 *)buf) = decpair[q - 100*r];
+       buf += 2;
 
-#if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
+       /* 0 <= r < 10^4 */
+       q = (r * 0x147b) >> 19;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
 
-/* First algorithm: generic */
+       /* 0 <= q < 100 */
+       *((u16 *)buf) = decpair[q];
+       buf += 2;
+       return buf;
+}
 
-static
+static noinline_for_stack
 char *put_dec(char *buf, unsigned long long n)
 {
-       if (n >= 100*1000*1000) {
-               while (n >= 1000*1000*1000)
-                       buf = put_dec_full9(buf, do_div(n, 1000*1000*1000));
-               if (n >= 100*1000*1000)
-                       return put_dec_full9(buf, n);
-       }
+       if (n >= 100*1000*1000)
+               buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
+       /* 1 <= n <= 1.6e11 */
+       if (n >= 100*1000*1000)
+               buf = put_dec_full8(buf, do_div(n, 100*1000*1000));
+       /* 1 <= n < 1e8 */
        return put_dec_trunc8(buf, n);
 }
 
-#else
-
-/* Second algorithm: valid only for 64-bit long longs */
+#elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64
 
-/* See comment in put_dec_full9 for choice of constants */
-static noinline_for_stack
-void put_dec_full4(char *buf, unsigned q)
+static void
+put_dec_full4(char *buf, unsigned r)
 {
-       unsigned r;
-       r      = (q * 0xccd) >> 15;
-       buf[0] = (q - 10 * r) + '0';
-       q      = (r * 0xcd) >> 11;
-       buf[1] = (r - 10 * q)  + '0';
-       r      = (q * 0xcd) >> 11;
-       buf[2] = (q - 10 * r)  + '0';
-       buf[3] = r + '0';
+       unsigned q;
+
+       /* 0 <= r < 10^4 */
+       q = (r * 0x147b) >> 19;
+       *((u16 *)buf) = decpair[r - 100*q];
+       buf += 2;
+       /* 0 <= q < 100 */
+       *((u16 *)buf) = decpair[q];
 }
 
 /*
@@ -260,9 +270,9 @@ void put_dec_full4(char *buf, unsigned q)
  * The approximation x/10000 == (x * 0x346DC5D7) >> 43
  * holds for all x < 1,128,869,999.  The largest value this
  * helper will ever be asked to convert is 1,125,520,955.
- * (d1 in the put_dec code, assuming n is all-ones).
+ * (second call in the put_dec code, assuming n is all-ones).
  */
-static
+static noinline_for_stack
 unsigned put_dec_helper4(char *buf, unsigned x)
 {
         uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
@@ -289,6 +299,8 @@ char *put_dec(char *buf, unsigned long long n)
        d2  = (h      ) & 0xffff;
        d3  = (h >> 16); /* implicit "& 0xffff" */
 
+       /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
+            = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
        q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
        q = put_dec_helper4(buf, q);
 
@@ -318,7 +330,8 @@ char *put_dec(char *buf, unsigned long long n)
  */
 int num_to_str(char *buf, int size, unsigned long long num)
 {
-       char tmp[sizeof(num) * 3];
+       /* put_dec requires 2-byte alignment of the buffer. */
+       char tmp[sizeof(num) * 3] __aligned(2);
        int idx, len;
 
        /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */
@@ -336,11 +349,11 @@ int num_to_str(char *buf, int size, unsigned long long num)
        return len;
 }
 
-#define ZEROPAD        1               /* pad with zero */
-#define SIGN   2               /* unsigned/signed long */
+#define SIGN   1               /* unsigned/signed, must be 1 */
+#define LEFT   2               /* left justified */
 #define PLUS   4               /* show plus */
 #define SPACE  8               /* space if plus */
-#define LEFT   16              /* left justified */
+#define ZEROPAD        16              /* pad with zero, must be 16 == '0' - ' ' */
 #define SMALL  32              /* use lowercase in hex (must be 32 == 0x20) */
 #define SPECIAL        64              /* prefix hex with "0x", octal with "0" */
 
@@ -362,7 +375,6 @@ enum format_type {
        FORMAT_TYPE_SHORT,
        FORMAT_TYPE_UINT,
        FORMAT_TYPE_INT,
-       FORMAT_TYPE_NRCHARS,
        FORMAT_TYPE_SIZE_T,
        FORMAT_TYPE_PTRDIFF
 };
@@ -380,10 +392,8 @@ static noinline_for_stack
 char *number(char *buf, char *end, unsigned long long num,
             struct printf_spec spec)
 {
-       /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
-       static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
-
-       char tmp[66];
+       /* put_dec requires 2-byte alignment of the buffer. */
+       char tmp[3 * sizeof(num)] __aligned(2);
        char sign;
        char locase;
        int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
@@ -419,12 +429,7 @@ char *number(char *buf, char *end, unsigned long long num,
        /* generate full string in tmp[], in reverse order */
        i = 0;
        if (num < spec.base)
-               tmp[i++] = digits[num] | locase;
-       /* Generic code, for any base:
-       else do {
-               tmp[i++] = (digits[do_div(num,base)] | locase);
-       } while (num != 0);
-       */
+               tmp[i++] = hex_asc_upper[num] | locase;
        else if (spec.base != 10) { /* 8 or 16 */
                int mask = spec.base - 1;
                int shift = 3;
@@ -432,7 +437,7 @@ char *number(char *buf, char *end, unsigned long long num,
                if (spec.base == 16)
                        shift = 4;
                do {
-                       tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
+                       tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);
                        num >>= shift;
                } while (num);
        } else { /* base 10 */
@@ -444,7 +449,7 @@ char *number(char *buf, char *end, unsigned long long num,
                spec.precision = i;
        /* leading space padding */
        spec.field_width -= spec.precision;
-       if (!(spec.flags & (ZEROPAD+LEFT))) {
+       if (!(spec.flags & (ZEROPAD | LEFT))) {
                while (--spec.field_width >= 0) {
                        if (buf < end)
                                *buf = ' ';
@@ -472,7 +477,8 @@ char *number(char *buf, char *end, unsigned long long num,
        }
        /* zero or space padding */
        if (!(spec.flags & LEFT)) {
-               char c = (spec.flags & ZEROPAD) ? '0' : ' ';
+               char c = ' ' + (spec.flags & ZEROPAD);
+               BUILD_BUG_ON(' ' + ZEROPAD != '0');
                while (--spec.field_width >= 0) {
                        if (buf < end)
                                *buf = c;
@@ -532,6 +538,81 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec)
        return buf;
 }
 
+static void widen(char *buf, char *end, unsigned len, unsigned spaces)
+{
+       size_t size;
+       if (buf >= end) /* nowhere to put anything */
+               return;
+       size = end - buf;
+       if (size <= spaces) {
+               memset(buf, ' ', size);
+               return;
+       }
+       if (len) {
+               if (len > size - spaces)
+                       len = size - spaces;
+               memmove(buf + spaces, buf, len);
+       }
+       memset(buf, ' ', spaces);
+}
+
+static noinline_for_stack
+char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec,
+                 const char *fmt)
+{
+       const char *array[4], *s;
+       const struct dentry *p;
+       int depth;
+       int i, n;
+
+       switch (fmt[1]) {
+               case '2': case '3': case '4':
+                       depth = fmt[1] - '0';
+                       break;
+               default:
+                       depth = 1;
+       }
+
+       rcu_read_lock();
+       for (i = 0; i < depth; i++, d = p) {
+               p = ACCESS_ONCE(d->d_parent);
+               array[i] = ACCESS_ONCE(d->d_name.name);
+               if (p == d) {
+                       if (i)
+                               array[i] = "";
+                       i++;
+                       break;
+               }
+       }
+       s = array[--i];
+       for (n = 0; n != spec.precision; n++, buf++) {
+               char c = *s++;
+               if (!c) {
+                       if (!i)
+                               break;
+                       c = '/';
+                       s = array[--i];
+               }
+               if (buf < end)
+                       *buf = c;
+       }
+       rcu_read_unlock();
+       if (n < spec.field_width) {
+               /* we want to pad the sucker */
+               unsigned spaces = spec.field_width - n;
+               if (!(spec.flags & LEFT)) {
+                       widen(buf - n, end, n, spaces);
+                       return buf + spaces;
+               }
+               while (spaces--) {
+                       if (buf < end)
+                               *buf = ' ';
+                       ++buf;
+               }
+       }
+       return buf;
+}
+
 static noinline_for_stack
 char *symbol_string(char *buf, char *end, void *ptr,
                    struct printf_spec spec, const char *fmt)
@@ -642,10 +723,15 @@ char *resource_string(char *buf, char *end, struct resource *res,
                specp = &mem_spec;
                decode = 0;
        }
-       p = number(p, pend, res->start, *specp);
-       if (res->start != res->end) {
-               *p++ = '-';
-               p = number(p, pend, res->end, *specp);
+       if (decode && res->flags & IORESOURCE_UNSET) {
+               p = string(p, pend, "size ", str_spec);
+               p = number(p, pend, resource_size(res), *specp);
+       } else {
+               p = number(p, pend, res->start, *specp);
+               if (res->start != res->end) {
+                       *p++ = '-';
+                       p = number(p, pend, res->end, *specp);
+               }
        }
        if (decode) {
                if (res->flags & IORESOURCE_MEM_64)
@@ -670,7 +756,7 @@ static noinline_for_stack
 char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
                 const char *fmt)
 {
-       int i, len = 1;         /* if we pass '%ph[CDN]', field witdh remains
+       int i, len = 1;         /* if we pass '%ph[CDN]', field width remains
                                   negative value, fallback to the default */
        char separator;
 
@@ -700,16 +786,105 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
        if (spec.field_width > 0)
                len = min_t(int, spec.field_width, 64);
 
-       for (i = 0; i < len && buf < end - 1; i++) {
-               buf = hex_byte_pack(buf, addr[i]);
+       for (i = 0; i < len; ++i) {
+               if (buf < end)
+                       *buf = hex_asc_hi(addr[i]);
+               ++buf;
+               if (buf < end)
+                       *buf = hex_asc_lo(addr[i]);
+               ++buf;
 
-               if (buf < end && separator && i != len - 1)
-                       *buf++ = separator;
+               if (separator && i != len - 1) {
+                       if (buf < end)
+                               *buf = separator;
+                       ++buf;
+               }
        }
 
        return buf;
 }
 
+static noinline_for_stack
+char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
+                   struct printf_spec spec, const char *fmt)
+{
+       const int CHUNKSZ = 32;
+       int nr_bits = max_t(int, spec.field_width, 0);
+       int i, chunksz;
+       bool first = true;
+
+       /* reused to print numbers */
+       spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 };
+
+       chunksz = nr_bits & (CHUNKSZ - 1);
+       if (chunksz == 0)
+               chunksz = CHUNKSZ;
+
+       i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ;
+       for (; i >= 0; i -= CHUNKSZ) {
+               u32 chunkmask, val;
+               int word, bit;
+
+               chunkmask = ((1ULL << chunksz) - 1);
+               word = i / BITS_PER_LONG;
+               bit = i % BITS_PER_LONG;
+               val = (bitmap[word] >> bit) & chunkmask;
+
+               if (!first) {
+                       if (buf < end)
+                               *buf = ',';
+                       buf++;
+               }
+               first = false;
+
+               spec.field_width = DIV_ROUND_UP(chunksz, 4);
+               buf = number(buf, end, val, spec);
+
+               chunksz = CHUNKSZ;
+       }
+       return buf;
+}
+
+static noinline_for_stack
+char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
+                        struct printf_spec spec, const char *fmt)
+{
+       int nr_bits = max_t(int, spec.field_width, 0);
+       /* current bit is 'cur', most recently seen range is [rbot, rtop] */
+       int cur, rbot, rtop;
+       bool first = true;
+
+       /* reused to print numbers */
+       spec = (struct printf_spec){ .base = 10 };
+
+       rbot = cur = find_first_bit(bitmap, nr_bits);
+       while (cur < nr_bits) {
+               rtop = cur;
+               cur = find_next_bit(bitmap, nr_bits, cur + 1);
+               if (cur < nr_bits && cur <= rtop + 1)
+                       continue;
+
+               if (!first) {
+                       if (buf < end)
+                               *buf = ',';
+                       buf++;
+               }
+               first = false;
+
+               buf = number(buf, end, rbot, spec);
+               if (rbot < rtop) {
+                       if (buf < end)
+                               *buf = '-';
+                       buf++;
+
+                       buf = number(buf, end, rtop, spec);
+               }
+
+               rbot = cur;
+       }
+       return buf;
+}
+
 static noinline_for_stack
 char *mac_address_string(char *buf, char *end, u8 *addr,
                         struct printf_spec spec, const char *fmt)
@@ -778,7 +953,7 @@ char *ip4_string(char *p, const u8 *addr, const char *fmt)
                break;
        }
        for (i = 0; i < 4; i++) {
-               char temp[3];   /* hold each IP quad in reverse order */
+               char temp[4] __aligned(2);      /* hold each IP quad in reverse order */
                int digits = put_dec_trunc8(temp, addr[index]) - temp;
                if (leading_zeros) {
                        if (digits < 3)
@@ -922,6 +1097,163 @@ char *ip4_addr_string(char *buf, char *end, const u8 *addr,
        return string(buf, end, ip4_addr, spec);
 }
 
+static noinline_for_stack
+char *ip6_addr_string_sa(char *buf, char *end, const struct sockaddr_in6 *sa,
+                        struct printf_spec spec, const char *fmt)
+{
+       bool have_p = false, have_s = false, have_f = false, have_c = false;
+       char ip6_addr[sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") +
+                     sizeof(":12345") + sizeof("/123456789") +
+                     sizeof("%1234567890")];
+       char *p = ip6_addr, *pend = ip6_addr + sizeof(ip6_addr);
+       const u8 *addr = (const u8 *) &sa->sin6_addr;
+       char fmt6[2] = { fmt[0], '6' };
+       u8 off = 0;
+
+       fmt++;
+       while (isalpha(*++fmt)) {
+               switch (*fmt) {
+               case 'p':
+                       have_p = true;
+                       break;
+               case 'f':
+                       have_f = true;
+                       break;
+               case 's':
+                       have_s = true;
+                       break;
+               case 'c':
+                       have_c = true;
+                       break;
+               }
+       }
+
+       if (have_p || have_s || have_f) {
+               *p = '[';
+               off = 1;
+       }
+
+       if (fmt6[0] == 'I' && have_c)
+               p = ip6_compressed_string(ip6_addr + off, addr);
+       else
+               p = ip6_string(ip6_addr + off, addr, fmt6);
+
+       if (have_p || have_s || have_f)
+               *p++ = ']';
+
+       if (have_p) {
+               *p++ = ':';
+               p = number(p, pend, ntohs(sa->sin6_port), spec);
+       }
+       if (have_f) {
+               *p++ = '/';
+               p = number(p, pend, ntohl(sa->sin6_flowinfo &
+                                         IPV6_FLOWINFO_MASK), spec);
+       }
+       if (have_s) {
+               *p++ = '%';
+               p = number(p, pend, sa->sin6_scope_id, spec);
+       }
+       *p = '\0';
+
+       return string(buf, end, ip6_addr, spec);
+}
+
+static noinline_for_stack
+char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa,
+                        struct printf_spec spec, const char *fmt)
+{
+       bool have_p = false;
+       char *p, ip4_addr[sizeof("255.255.255.255") + sizeof(":12345")];
+       char *pend = ip4_addr + sizeof(ip4_addr);
+       const u8 *addr = (const u8 *) &sa->sin_addr.s_addr;
+       char fmt4[3] = { fmt[0], '4', 0 };
+
+       fmt++;
+       while (isalpha(*++fmt)) {
+               switch (*fmt) {
+               case 'p':
+                       have_p = true;
+                       break;
+               case 'h':
+               case 'l':
+               case 'n':
+               case 'b':
+                       fmt4[2] = *fmt;
+                       break;
+               }
+       }
+
+       p = ip4_string(ip4_addr, addr, fmt4);
+       if (have_p) {
+               *p++ = ':';
+               p = number(p, pend, ntohs(sa->sin_port), spec);
+       }
+       *p = '\0';
+
+       return string(buf, end, ip4_addr, spec);
+}
+
+static noinline_for_stack
+char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
+                    const char *fmt)
+{
+       bool found = true;
+       int count = 1;
+       unsigned int flags = 0;
+       int len;
+
+       if (spec.field_width == 0)
+               return buf;                             /* nothing to print */
+
+       if (ZERO_OR_NULL_PTR(addr))
+               return string(buf, end, NULL, spec);    /* NULL pointer */
+
+
+       do {
+               switch (fmt[count++]) {
+               case 'a':
+                       flags |= ESCAPE_ANY;
+                       break;
+               case 'c':
+                       flags |= ESCAPE_SPECIAL;
+                       break;
+               case 'h':
+                       flags |= ESCAPE_HEX;
+                       break;
+               case 'n':
+                       flags |= ESCAPE_NULL;
+                       break;
+               case 'o':
+                       flags |= ESCAPE_OCTAL;
+                       break;
+               case 'p':
+                       flags |= ESCAPE_NP;
+                       break;
+               case 's':
+                       flags |= ESCAPE_SPACE;
+                       break;
+               default:
+                       found = false;
+                       break;
+               }
+       } while (found);
+
+       if (!flags)
+               flags = ESCAPE_ANY_NP;
+
+       len = spec.field_width < 0 ? 1 : spec.field_width;
+
+       /*
+        * string_escape_mem() writes as many characters as it can to
+        * the given buffer, and returns the total size of the output
+        * had the buffer been big enough.
+        */
+       buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL);
+
+       return buf;
+}
+
 static noinline_for_stack
 char *uuid_string(char *buf, char *end, const u8 *addr,
                  struct printf_spec spec, const char *fmt)
@@ -981,6 +1313,54 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr,
        return number(buf, end, *(const netdev_features_t *)addr, spec);
 }
 
+static noinline_for_stack
+char *address_val(char *buf, char *end, const void *addr,
+                 struct printf_spec spec, const char *fmt)
+{
+       unsigned long long num;
+
+       spec.flags |= SPECIAL | SMALL | ZEROPAD;
+       spec.base = 16;
+
+       switch (fmt[1]) {
+       case 'd':
+               num = *(const dma_addr_t *)addr;
+               spec.field_width = sizeof(dma_addr_t) * 2 + 2;
+               break;
+       case 'p':
+       default:
+               num = *(const phys_addr_t *)addr;
+               spec.field_width = sizeof(phys_addr_t) * 2 + 2;
+               break;
+       }
+
+       return number(buf, end, num, spec);
+}
+
+static noinline_for_stack
+char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
+           const char *fmt)
+{
+       if (!IS_ENABLED(CONFIG_HAVE_CLK) || !clk)
+               return string(buf, end, NULL, spec);
+
+       switch (fmt[1]) {
+       case 'r':
+               return number(buf, end, clk_get_rate(clk), spec);
+
+       case 'n':
+       default:
+#ifdef CONFIG_COMMON_CLK
+               return string(buf, end, __clk_get_name(clk), spec);
+#else
+               spec.base = 16;
+               spec.field_width = sizeof(unsigned long) * 2 + 2;
+               spec.flags |= SPECIAL | SMALL | ZEROPAD;
+               return number(buf, end, (unsigned long)clk, spec);
+#endif
+       }
+}
+
 int kptr_restrict __read_mostly;
 
 /*
@@ -998,6 +1378,10 @@ int kptr_restrict __read_mostly;
  * - 'B' For backtraced symbolic direct pointers with offset
  * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
  * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
+ * - 'b[l]' For a bitmap, the number of bits is determined by the field
+ *       width which must be explicitly specified either as part of the
+ *       format string '%32b[l]' or through '%*b[l]', [l] selects
+ *       range-list format instead of hex format
  * - 'M' For a 6-byte MAC address, it prints the address in the
  *       usual colon-separated hex notation
  * - 'm' For a 6-byte MAC address, it prints the hex address without colons
@@ -1007,12 +1391,29 @@ int kptr_restrict __read_mostly;
  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
  *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
  *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
+ *       [S][pfs]
+ *       Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
+ *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
  * - 'i' [46] for 'raw' IPv4/IPv6 addresses
  *       IPv6 omits the colons (01020304...0f)
  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
- * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
- * - 'I6c' for IPv6 addresses printed as specified by
+ *       [S][pfs]
+ *       Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
+ *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
+ * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
+ * - 'I[6S]c' for IPv6 addresses printed as specified by
  *       http://tools.ietf.org/html/rfc5952
+ * - 'E[achnops]' For an escaped buffer, where rules are defined by combination
+ *                of the following flags (see string_escape_mem() for the
+ *                details):
+ *                  a - ESCAPE_ANY
+ *                  c - ESCAPE_SPECIAL
+ *                  h - ESCAPE_HEX
+ *                  n - ESCAPE_NULL
+ *                  o - ESCAPE_OCTAL
+ *                  p - ESCAPE_NP
+ *                  s - ESCAPE_SPACE
+ *                By default ESCAPE_ANY_NP is used.
  * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
  *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  *       Options for %pU are:
@@ -1038,7 +1439,17 @@ int kptr_restrict __read_mostly;
  *              N no separator
  *            The maximum supported length is 64 bytes of the input. Consider
  *            to use print_hex_dump() for the larger input.
- * - 'a' For a phys_addr_t type and its derivative types (passed by reference)
+ * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives
+ *           (default assumed to be phys_addr_t, passed by reference)
+ * - 'd[234]' For a dentry name (optionally 2-4 last components)
+ * - 'D[234]' Same as 'd' but for a struct file
+ * - 'C' For a clock, it prints the name (Common Clock Framework) or address
+ *       (legacy clock framework) of the clock
+ * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
+ *        (legacy clock framework) of the clock
+ * - 'Cr' For a clock, it prints the current rate of the clock
+ *
+ * ** Please update also Documentation/printk-formats.txt when making changes **
  *
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
@@ -1048,7 +1459,7 @@ static noinline_for_stack
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
              struct printf_spec spec)
 {
-       int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0);
+       const int default_width = 2 * sizeof(void *);
 
        if (!ptr && *fmt != 'K') {
                /*
@@ -1074,6 +1485,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                return resource_string(buf, end, ptr, spec, fmt);
        case 'h':
                return hex_string(buf, end, ptr, spec, fmt);
+       case 'b':
+               switch (fmt[1]) {
+               case 'l':
+                       return bitmap_list_string(buf, end, ptr, spec, fmt);
+               default:
+                       return bitmap_string(buf, end, ptr, spec, fmt);
+               }
        case 'M':                       /* Colon separated: 00:01:02:03:04:05 */
        case 'm':                       /* Contiguous: 000102030405 */
                                        /* [mM]F (FDDI) */
@@ -1093,8 +1511,25 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                        return ip6_addr_string(buf, end, ptr, spec, fmt);
                case '4':
                        return ip4_addr_string(buf, end, ptr, spec, fmt);
+               case 'S': {
+                       const union {
+                               struct sockaddr         raw;
+                               struct sockaddr_in      v4;
+                               struct sockaddr_in6     v6;
+                       } *sa = ptr;
+
+                       switch (sa->raw.sa_family) {
+                       case AF_INET:
+                               return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt);
+                       case AF_INET6:
+                               return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt);
+                       default:
+                               return string(buf, end, "(invalid address)", spec);
+                       }}
                }
                break;
+       case 'E':
+               return escaped_string(buf, end, ptr, spec, fmt);
        case 'U':
                return uuid_string(buf, end, ptr, spec, fmt);
        case 'V':
@@ -1118,11 +1553,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                                spec.field_width = default_width;
                        return string(buf, end, "pK-error", spec);
                }
-               if (!((kptr_restrict == 0) ||
-                     (kptr_restrict == 1 &&
-                      has_capability_noaudit(current, CAP_SYSLOG))))
+
+               switch (kptr_restrict) {
+               case 0:
+                       /* Always print %pK values */
+                       break;
+               case 1: {
+                       /*
+                        * Only print the real pointer value if the current
+                        * process has CAP_SYSLOG and is running with the
+                        * same credentials it started with. This is because
+                        * access to files is checked at open() time, but %pK
+                        * checks permission at read() time. We don't want to
+                        * leak pointer values if a binary opens a file using
+                        * %pK and then elevates privileges before reading it.
+                        */
+                       const struct cred *cred = current_cred();
+
+                       if (!has_capability_noaudit(current, CAP_SYSLOG) ||
+                           !uid_eq(cred->euid, cred->uid) ||
+                           !gid_eq(cred->egid, cred->gid))
+                               ptr = NULL;
+                       break;
+               }
+               case 2:
+               default:
+                       /* Always print 0's for %pK */
                        ptr = NULL;
+                       break;
+               }
                break;
+
        case 'N':
                switch (fmt[1]) {
                case 'F':
@@ -1130,11 +1591,15 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                }
                break;
        case 'a':
-               spec.flags |= SPECIAL | SMALL | ZEROPAD;
-               spec.field_width = sizeof(phys_addr_t) * 2 + 2;
-               spec.base = 16;
-               return number(buf, end,
-                             (unsigned long long) *((phys_addr_t *)ptr), spec);
+               return address_val(buf, end, ptr, spec, fmt);
+       case 'd':
+               return dentry_name(buf, end, ptr, spec, fmt);
+       case 'C':
+               return clock(buf, end, ptr, spec, fmt);
+       case 'D':
+               return dentry_name(buf, end,
+                                  ((const struct file *)ptr)->f_path.dentry,
+                                  spec, fmt);
        }
        spec.flags |= SMALL;
        if (spec.field_width == -1) {
@@ -1280,11 +1745,6 @@ qualifier:
 
        case 'p':
                spec->type = FORMAT_TYPE_PTR;
-               return fmt - start;
-               /* skip alnum */
-
-       case 'n':
-               spec->type = FORMAT_TYPE_NRCHARS;
                return ++fmt - start;
 
        case '%':
@@ -1309,7 +1769,16 @@ qualifier:
        case 'u':
                break;
 
+       case 'n':
+               /*
+                * Since %n poses a greater security risk than
+                * utility, treat it as any other invalid or
+                * unsupported format specifier.
+                */
+               /* Fall-through */
+
        default:
+               WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt);
                spec->type = FORMAT_TYPE_INVALID;
                return fmt - start;
        }
@@ -1317,29 +1786,21 @@ qualifier:
        if (spec->qualifier == 'L')
                spec->type = FORMAT_TYPE_LONG_LONG;
        else if (spec->qualifier == 'l') {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_LONG;
-               else
-                       spec->type = FORMAT_TYPE_ULONG;
+               BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG);
+               spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN);
        } else if (_tolower(spec->qualifier) == 'z') {
                spec->type = FORMAT_TYPE_SIZE_T;
        } else if (spec->qualifier == 't') {
                spec->type = FORMAT_TYPE_PTRDIFF;
        } else if (spec->qualifier == 'H') {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_BYTE;
-               else
-                       spec->type = FORMAT_TYPE_UBYTE;
+               BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE);
+               spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN);
        } else if (spec->qualifier == 'h') {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_SHORT;
-               else
-                       spec->type = FORMAT_TYPE_USHORT;
+               BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT);
+               spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN);
        } else {
-               if (spec->flags & SIGN)
-                       spec->type = FORMAT_TYPE_INT;
-               else
-                       spec->type = FORMAT_TYPE_UINT;
+               BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT);
+               spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN);
        }
 
        return ++fmt - start;
@@ -1352,31 +1813,16 @@ qualifier:
  * @fmt: The format string to use
  * @args: Arguments for the format string
  *
- * This function follows C99 vsnprintf, but has some extensions:
- * %pS output the name of a text symbol with offset
- * %ps output the name of a text symbol without offset
- * %pF output the name of a function pointer with its offset
- * %pf output the name of a function pointer without its offset
- * %pB output the name of a backtrace symbol with its offset
- * %pR output the address range in a struct resource with decoded flags
- * %pr output the address range in a struct resource with raw flags
- * %pM output a 6-byte MAC address with colons
- * %pMR output a 6-byte MAC address with colons in reversed order
- * %pMF output a 6-byte MAC address with dashes
- * %pm output a 6-byte MAC address without colons
- * %pmR output a 6-byte MAC address without colons in reversed order
- * %pI4 print an IPv4 address without leading zeros
- * %pi4 print an IPv4 address with leading zeros
- * %pI6 print an IPv6 address with colons
- * %pi6 print an IPv6 address without colons
- * %pI6c print an IPv6 address as specified by RFC 5952
- * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
- *   case.
- * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
- *           bytes of the input)
- * %n is ignored
+ * This function generally follows C99 vsnprintf, but has some
+ * extensions and a few limitations:
+ *
+ * %n is unsupported
+ * %p* is handled by pointer()
  *
- * ** Please update Documentation/printk-formats.txt when making changes **
+ * See pointer() or Documentation/printk-formats.txt for more
+ * extensive description.
+ *
+ * ** Please update the documentation in both places when making changes **
  *
  * The return value is the number of characters which would
  * be generated for the given input, excluding the trailing
@@ -1396,7 +1842,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 
        /* Reject out-of-range values early.  Large positive sizes are
           used for unknown buffer sizes. */
-       if (WARN_ON_ONCE((int) size < 0))
+       if (WARN_ON_ONCE(size > INT_MAX))
                return 0;
 
        str = buf;
@@ -1462,7 +1908,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                        break;
 
                case FORMAT_TYPE_PTR:
-                       str = pointer(fmt+1, str, end, va_arg(args, void *),
+                       str = pointer(fmt, str, end, va_arg(args, void *),
                                      spec);
                        while (isalnum(*fmt))
                                fmt++;
@@ -1475,26 +1921,15 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                        break;
 
                case FORMAT_TYPE_INVALID:
-                       if (str < end)
-                               *str = '%';
-                       ++str;
-                       break;
-
-               case FORMAT_TYPE_NRCHARS: {
-                       u8 qualifier = spec.qualifier;
-
-                       if (qualifier == 'l') {
-                               long *ip = va_arg(args, long *);
-                               *ip = (str - buf);
-                       } else if (_tolower(qualifier) == 'z') {
-                               size_t *ip = va_arg(args, size_t *);
-                               *ip = (str - buf);
-                       } else {
-                               int *ip = va_arg(args, int *);
-                               *ip = (str - buf);
-                       }
-                       break;
-               }
+                       /*
+                        * Presumably the arguments passed gcc's type
+                        * checking, but there is no safe or sane way
+                        * for us to continue parsing the format and
+                        * fetching from the va_list; the remaining
+                        * specifiers and arguments would be out of
+                        * sync.
+                        */
+                       goto out;
 
                default:
                        switch (spec.type) {
@@ -1539,6 +1974,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                }
        }
 
+out:
        if (size > 0) {
                if (str < end)
                        *str = '\0';
@@ -1692,7 +2128,7 @@ EXPORT_SYMBOL(sprintf);
  * @args: Arguments for the format string
  *
  * The format follows C99 vsnprintf, except %n is ignored, and its argument
- * is skiped.
+ * is skipped.
  *
  * The return value is the number of words(32bits) which would be generated for
  * the given input.
@@ -1736,9 +2172,10 @@ do {                                                                     \
 
                switch (spec.type) {
                case FORMAT_TYPE_NONE:
-               case FORMAT_TYPE_INVALID:
                case FORMAT_TYPE_PERCENT_CHAR:
                        break;
+               case FORMAT_TYPE_INVALID:
+                       goto out;
 
                case FORMAT_TYPE_WIDTH:
                case FORMAT_TYPE_PRECISION:
@@ -1770,19 +2207,6 @@ do {                                                                     \
                                fmt++;
                        break;
 
-               case FORMAT_TYPE_NRCHARS: {
-                       /* skip %n 's argument */
-                       u8 qualifier = spec.qualifier;
-                       void *skip_arg;
-                       if (qualifier == 'l')
-                               skip_arg = va_arg(args, long *);
-                       else if (_tolower(qualifier) == 'z')
-                               skip_arg = va_arg(args, size_t *);
-                       else
-                               skip_arg = va_arg(args, int *);
-                       break;
-               }
-
                default:
                        switch (spec.type) {
 
@@ -1813,6 +2237,7 @@ do {                                                                      \
                }
        }
 
+out:
        return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
 #undef save_arg
 }
@@ -1846,7 +2271,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
        char *str, *end;
        const char *args = (const char *)bin_buf;
 
-       if (WARN_ON_ONCE((int) size < 0))
+       if (WARN_ON_ONCE(size > INT_MAX))
                return 0;
 
        str = buf;
@@ -1929,21 +2354,19 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
                }
 
                case FORMAT_TYPE_PTR:
-                       str = pointer(fmt+1, str, end, get_arg(void *), spec);
+                       str = pointer(fmt, str, end, get_arg(void *), spec);
                        while (isalnum(*fmt))
                                fmt++;
                        break;
 
                case FORMAT_TYPE_PERCENT_CHAR:
-               case FORMAT_TYPE_INVALID:
                        if (str < end)
                                *str = '%';
                        ++str;
                        break;
 
-               case FORMAT_TYPE_NRCHARS:
-                       /* skip */
-                       break;
+               case FORMAT_TYPE_INVALID:
+                       goto out;
 
                default: {
                        unsigned long long num;
@@ -1987,6 +2410,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
                } /* switch(spec.type) */
        } /* while(*fmt) */
 
+out:
        if (size > 0) {
                if (str < end)
                        *str = '\0';
@@ -2119,7 +2543,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                        break;
 
                base = 10;
-               is_sign = 0;
+               is_sign = false;
 
                switch (*fmt++) {
                case 'c':
@@ -2158,7 +2582,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
                case 'i':
                        base = 0;
                case 'd':
-                       is_sign = 1;
+                       is_sign = true;
                case 'u':
                        break;
                case '%':