diff options
| author | Ingo Molnar <mingo@kernel.org> | 2015-02-28 02:03:10 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-02-28 02:03:10 -0500 |
| commit | 5838d18955b52467f4b30486e62a31727b39998d (patch) | |
| tree | 8aeb8412156bab93a6b39f2de4a8d6c912ddb31a /lib/vsprintf.c | |
| parent | 579deee571a755c485ad702ef82c77a98a2ccc05 (diff) | |
| parent | 895c8b7b4623d4f55e260e5dee2574b4f7113105 (diff) | |
Merge branch 'linus' into x86/urgent, to merge dependent patch
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 106 |
1 files changed, 100 insertions, 6 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index ec337f64f52d..b235c96167d3 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -114,8 +114,9 @@ int skip_atoi(const char **s) | |||
| 114 | { | 114 | { |
| 115 | int i = 0; | 115 | int i = 0; |
| 116 | 116 | ||
| 117 | while (isdigit(**s)) | 117 | do { |
| 118 | i = i*10 + *((*s)++) - '0'; | 118 | i = i*10 + *((*s)++) - '0'; |
| 119 | } while (isdigit(**s)); | ||
| 119 | 120 | ||
| 120 | return i; | 121 | return i; |
| 121 | } | 122 | } |
| @@ -793,6 +794,87 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
| 793 | } | 794 | } |
| 794 | 795 | ||
| 795 | static noinline_for_stack | 796 | static noinline_for_stack |
| 797 | char *bitmap_string(char *buf, char *end, unsigned long *bitmap, | ||
| 798 | struct printf_spec spec, const char *fmt) | ||
| 799 | { | ||
| 800 | const int CHUNKSZ = 32; | ||
| 801 | int nr_bits = max_t(int, spec.field_width, 0); | ||
| 802 | int i, chunksz; | ||
| 803 | bool first = true; | ||
| 804 | |||
| 805 | /* reused to print numbers */ | ||
| 806 | spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 }; | ||
| 807 | |||
| 808 | chunksz = nr_bits & (CHUNKSZ - 1); | ||
| 809 | if (chunksz == 0) | ||
| 810 | chunksz = CHUNKSZ; | ||
| 811 | |||
| 812 | i = ALIGN(nr_bits, CHUNKSZ) - CHUNKSZ; | ||
| 813 | for (; i >= 0; i -= CHUNKSZ) { | ||
| 814 | u32 chunkmask, val; | ||
| 815 | int word, bit; | ||
| 816 | |||
| 817 | chunkmask = ((1ULL << chunksz) - 1); | ||
| 818 | word = i / BITS_PER_LONG; | ||
| 819 | bit = i % BITS_PER_LONG; | ||
| 820 | val = (bitmap[word] >> bit) & chunkmask; | ||
| 821 | |||
| 822 | if (!first) { | ||
| 823 | if (buf < end) | ||
| 824 | *buf = ','; | ||
| 825 | buf++; | ||
| 826 | } | ||
| 827 | first = false; | ||
| 828 | |||
| 829 | spec.field_width = DIV_ROUND_UP(chunksz, 4); | ||
| 830 | buf = number(buf, end, val, spec); | ||
| 831 | |||
| 832 | chunksz = CHUNKSZ; | ||
| 833 | } | ||
| 834 | return buf; | ||
| 835 | } | ||
| 836 | |||
| 837 | static noinline_for_stack | ||
| 838 | char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, | ||
| 839 | struct printf_spec spec, const char *fmt) | ||
| 840 | { | ||
| 841 | int nr_bits = max_t(int, spec.field_width, 0); | ||
| 842 | /* current bit is 'cur', most recently seen range is [rbot, rtop] */ | ||
| 843 | int cur, rbot, rtop; | ||
| 844 | bool first = true; | ||
| 845 | |||
| 846 | /* reused to print numbers */ | ||
| 847 | spec = (struct printf_spec){ .base = 10 }; | ||
| 848 | |||
| 849 | rbot = cur = find_first_bit(bitmap, nr_bits); | ||
| 850 | while (cur < nr_bits) { | ||
| 851 | rtop = cur; | ||
| 852 | cur = find_next_bit(bitmap, nr_bits, cur + 1); | ||
| 853 | if (cur < nr_bits && cur <= rtop + 1) | ||
| 854 | continue; | ||
| 855 | |||
| 856 | if (!first) { | ||
| 857 | if (buf < end) | ||
| 858 | *buf = ','; | ||
| 859 | buf++; | ||
| 860 | } | ||
| 861 | first = false; | ||
| 862 | |||
| 863 | buf = number(buf, end, rbot, spec); | ||
| 864 | if (rbot < rtop) { | ||
| 865 | if (buf < end) | ||
| 866 | *buf = '-'; | ||
| 867 | buf++; | ||
| 868 | |||
| 869 | buf = number(buf, end, rtop, spec); | ||
| 870 | } | ||
| 871 | |||
| 872 | rbot = cur; | ||
| 873 | } | ||
| 874 | return buf; | ||
| 875 | } | ||
| 876 | |||
| 877 | static noinline_for_stack | ||
| 796 | char *mac_address_string(char *buf, char *end, u8 *addr, | 878 | char *mac_address_string(char *buf, char *end, u8 *addr, |
| 797 | struct printf_spec spec, const char *fmt) | 879 | struct printf_spec spec, const char *fmt) |
| 798 | { | 880 | { |
| @@ -1257,6 +1339,10 @@ int kptr_restrict __read_mostly; | |||
| 1257 | * - 'B' For backtraced symbolic direct pointers with offset | 1339 | * - 'B' For backtraced symbolic direct pointers with offset |
| 1258 | * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] | 1340 | * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] |
| 1259 | * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] | 1341 | * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201] |
| 1342 | * - 'b[l]' For a bitmap, the number of bits is determined by the field | ||
| 1343 | * width which must be explicitly specified either as part of the | ||
| 1344 | * format string '%32b[l]' or through '%*b[l]', [l] selects | ||
| 1345 | * range-list format instead of hex format | ||
| 1260 | * - 'M' For a 6-byte MAC address, it prints the address in the | 1346 | * - 'M' For a 6-byte MAC address, it prints the address in the |
| 1261 | * usual colon-separated hex notation | 1347 | * usual colon-separated hex notation |
| 1262 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons | 1348 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons |
| @@ -1353,6 +1439,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1353 | return resource_string(buf, end, ptr, spec, fmt); | 1439 | return resource_string(buf, end, ptr, spec, fmt); |
| 1354 | case 'h': | 1440 | case 'h': |
| 1355 | return hex_string(buf, end, ptr, spec, fmt); | 1441 | return hex_string(buf, end, ptr, spec, fmt); |
| 1442 | case 'b': | ||
| 1443 | switch (fmt[1]) { | ||
| 1444 | case 'l': | ||
| 1445 | return bitmap_list_string(buf, end, ptr, spec, fmt); | ||
| 1446 | default: | ||
| 1447 | return bitmap_string(buf, end, ptr, spec, fmt); | ||
| 1448 | } | ||
| 1356 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 1449 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
| 1357 | case 'm': /* Contiguous: 000102030405 */ | 1450 | case 'm': /* Contiguous: 000102030405 */ |
| 1358 | /* [mM]F (FDDI) */ | 1451 | /* [mM]F (FDDI) */ |
| @@ -1604,8 +1697,7 @@ qualifier: | |||
| 1604 | 1697 | ||
| 1605 | case 'p': | 1698 | case 'p': |
| 1606 | spec->type = FORMAT_TYPE_PTR; | 1699 | spec->type = FORMAT_TYPE_PTR; |
| 1607 | return fmt - start; | 1700 | return ++fmt - start; |
| 1608 | /* skip alnum */ | ||
| 1609 | 1701 | ||
| 1610 | case '%': | 1702 | case '%': |
| 1611 | spec->type = FORMAT_TYPE_PERCENT_CHAR; | 1703 | spec->type = FORMAT_TYPE_PERCENT_CHAR; |
| @@ -1689,6 +1781,8 @@ qualifier: | |||
| 1689 | * %pB output the name of a backtrace symbol with its offset | 1781 | * %pB output the name of a backtrace symbol with its offset |
| 1690 | * %pR output the address range in a struct resource with decoded flags | 1782 | * %pR output the address range in a struct resource with decoded flags |
| 1691 | * %pr output the address range in a struct resource with raw flags | 1783 | * %pr output the address range in a struct resource with raw flags |
| 1784 | * %pb output the bitmap with field width as the number of bits | ||
| 1785 | * %pbl output the bitmap as range list with field width as the number of bits | ||
| 1692 | * %pM output a 6-byte MAC address with colons | 1786 | * %pM output a 6-byte MAC address with colons |
| 1693 | * %pMR output a 6-byte MAC address with colons in reversed order | 1787 | * %pMR output a 6-byte MAC address with colons in reversed order |
| 1694 | * %pMF output a 6-byte MAC address with dashes | 1788 | * %pMF output a 6-byte MAC address with dashes |
| @@ -1728,7 +1822,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1728 | 1822 | ||
| 1729 | /* Reject out-of-range values early. Large positive sizes are | 1823 | /* Reject out-of-range values early. Large positive sizes are |
| 1730 | used for unknown buffer sizes. */ | 1824 | used for unknown buffer sizes. */ |
| 1731 | if (WARN_ON_ONCE((int) size < 0)) | 1825 | if (WARN_ON_ONCE(size > INT_MAX)) |
| 1732 | return 0; | 1826 | return 0; |
| 1733 | 1827 | ||
| 1734 | str = buf; | 1828 | str = buf; |
| @@ -1794,7 +1888,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1794 | break; | 1888 | break; |
| 1795 | 1889 | ||
| 1796 | case FORMAT_TYPE_PTR: | 1890 | case FORMAT_TYPE_PTR: |
| 1797 | str = pointer(fmt+1, str, end, va_arg(args, void *), | 1891 | str = pointer(fmt, str, end, va_arg(args, void *), |
| 1798 | spec); | 1892 | spec); |
| 1799 | while (isalnum(*fmt)) | 1893 | while (isalnum(*fmt)) |
| 1800 | fmt++; | 1894 | fmt++; |
| @@ -2232,7 +2326,7 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf) | |||
| 2232 | } | 2326 | } |
| 2233 | 2327 | ||
| 2234 | case FORMAT_TYPE_PTR: | 2328 | case FORMAT_TYPE_PTR: |
| 2235 | str = pointer(fmt+1, str, end, get_arg(void *), spec); | 2329 | str = pointer(fmt, str, end, get_arg(void *), spec); |
| 2236 | while (isalnum(*fmt)) | 2330 | while (isalnum(*fmt)) |
| 2237 | fmt++; | 2331 | fmt++; |
| 2238 | break; | 2332 | break; |
