diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 89 |
1 files changed, 58 insertions, 31 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 24112e5a5780..4ee19d0d3910 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -118,6 +118,7 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base) | |||
| 118 | 118 | ||
| 119 | return simple_strtoull(cp, endp, base); | 119 | return simple_strtoull(cp, endp, base); |
| 120 | } | 120 | } |
| 121 | EXPORT_SYMBOL(simple_strtoll); | ||
| 121 | 122 | ||
| 122 | /** | 123 | /** |
| 123 | * strict_strtoul - convert a string to an unsigned long strictly | 124 | * strict_strtoul - convert a string to an unsigned long strictly |
| @@ -266,7 +267,8 @@ int strict_strtoll(const char *cp, unsigned int base, long long *res) | |||
| 266 | } | 267 | } |
| 267 | EXPORT_SYMBOL(strict_strtoll); | 268 | EXPORT_SYMBOL(strict_strtoll); |
| 268 | 269 | ||
| 269 | static int skip_atoi(const char **s) | 270 | static noinline_for_stack |
| 271 | int skip_atoi(const char **s) | ||
| 270 | { | 272 | { |
| 271 | int i = 0; | 273 | int i = 0; |
| 272 | 274 | ||
| @@ -286,7 +288,8 @@ static int skip_atoi(const char **s) | |||
| 286 | /* Formats correctly any integer in [0,99999]. | 288 | /* Formats correctly any integer in [0,99999]. |
| 287 | * Outputs from one to five digits depending on input. | 289 | * Outputs from one to five digits depending on input. |
| 288 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ | 290 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ |
| 289 | static char *put_dec_trunc(char *buf, unsigned q) | 291 | static noinline_for_stack |
| 292 | char *put_dec_trunc(char *buf, unsigned q) | ||
| 290 | { | 293 | { |
| 291 | unsigned d3, d2, d1, d0; | 294 | unsigned d3, d2, d1, d0; |
| 292 | d1 = (q>>4) & 0xf; | 295 | d1 = (q>>4) & 0xf; |
| @@ -323,7 +326,8 @@ static char *put_dec_trunc(char *buf, unsigned q) | |||
| 323 | return buf; | 326 | return buf; |
| 324 | } | 327 | } |
| 325 | /* Same with if's removed. Always emits five digits */ | 328 | /* Same with if's removed. Always emits five digits */ |
| 326 | static char *put_dec_full(char *buf, unsigned q) | 329 | static noinline_for_stack |
| 330 | char *put_dec_full(char *buf, unsigned q) | ||
| 327 | { | 331 | { |
| 328 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ | 332 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ |
| 329 | /* but anyway, gcc produces better code with full-sized ints */ | 333 | /* but anyway, gcc produces better code with full-sized ints */ |
| @@ -365,7 +369,8 @@ static char *put_dec_full(char *buf, unsigned q) | |||
| 365 | return buf; | 369 | return buf; |
| 366 | } | 370 | } |
| 367 | /* No inlining helps gcc to use registers better */ | 371 | /* No inlining helps gcc to use registers better */ |
| 368 | static noinline char *put_dec(char *buf, unsigned long long num) | 372 | static noinline_for_stack |
| 373 | char *put_dec(char *buf, unsigned long long num) | ||
| 369 | { | 374 | { |
| 370 | while (1) { | 375 | while (1) { |
| 371 | unsigned rem; | 376 | unsigned rem; |
| @@ -408,16 +413,17 @@ enum format_type { | |||
| 408 | }; | 413 | }; |
| 409 | 414 | ||
| 410 | struct printf_spec { | 415 | struct printf_spec { |
| 411 | u16 type; | 416 | u8 type; /* format_type enum */ |
| 412 | s16 field_width; /* width of output field */ | ||
| 413 | u8 flags; /* flags to number() */ | 417 | u8 flags; /* flags to number() */ |
| 414 | u8 base; | 418 | u8 base; /* number base, 8, 10 or 16 only */ |
| 415 | s8 precision; /* # of digits/chars */ | 419 | u8 qualifier; /* number qualifier, one of 'hHlLtzZ' */ |
| 416 | u8 qualifier; | 420 | s16 field_width; /* width of output field */ |
| 421 | s16 precision; /* # of digits/chars */ | ||
| 417 | }; | 422 | }; |
| 418 | 423 | ||
| 419 | static char *number(char *buf, char *end, unsigned long long num, | 424 | static noinline_for_stack |
| 420 | struct printf_spec spec) | 425 | char *number(char *buf, char *end, unsigned long long num, |
| 426 | struct printf_spec spec) | ||
| 421 | { | 427 | { |
| 422 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ | 428 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ |
| 423 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ | 429 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ |
| @@ -536,7 +542,8 @@ static char *number(char *buf, char *end, unsigned long long num, | |||
| 536 | return buf; | 542 | return buf; |
| 537 | } | 543 | } |
| 538 | 544 | ||
| 539 | static char *string(char *buf, char *end, const char *s, struct printf_spec spec) | 545 | static noinline_for_stack |
| 546 | char *string(char *buf, char *end, const char *s, struct printf_spec spec) | ||
| 540 | { | 547 | { |
| 541 | int len, i; | 548 | int len, i; |
| 542 | 549 | ||
| @@ -566,8 +573,9 @@ static char *string(char *buf, char *end, const char *s, struct printf_spec spec | |||
| 566 | return buf; | 573 | return buf; |
| 567 | } | 574 | } |
| 568 | 575 | ||
| 569 | static char *symbol_string(char *buf, char *end, void *ptr, | 576 | static noinline_for_stack |
| 570 | struct printf_spec spec, char ext) | 577 | char *symbol_string(char *buf, char *end, void *ptr, |
| 578 | struct printf_spec spec, char ext) | ||
| 571 | { | 579 | { |
| 572 | unsigned long value = (unsigned long) ptr; | 580 | unsigned long value = (unsigned long) ptr; |
| 573 | #ifdef CONFIG_KALLSYMS | 581 | #ifdef CONFIG_KALLSYMS |
| @@ -587,8 +595,9 @@ static char *symbol_string(char *buf, char *end, void *ptr, | |||
| 587 | #endif | 595 | #endif |
| 588 | } | 596 | } |
| 589 | 597 | ||
| 590 | static char *resource_string(char *buf, char *end, struct resource *res, | 598 | static noinline_for_stack |
| 591 | struct printf_spec spec, const char *fmt) | 599 | char *resource_string(char *buf, char *end, struct resource *res, |
| 600 | struct printf_spec spec, const char *fmt) | ||
| 592 | { | 601 | { |
| 593 | #ifndef IO_RSRC_PRINTK_SIZE | 602 | #ifndef IO_RSRC_PRINTK_SIZE |
| 594 | #define IO_RSRC_PRINTK_SIZE 6 | 603 | #define IO_RSRC_PRINTK_SIZE 6 |
| @@ -689,8 +698,9 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
| 689 | return string(buf, end, sym, spec); | 698 | return string(buf, end, sym, spec); |
| 690 | } | 699 | } |
| 691 | 700 | ||
| 692 | static char *mac_address_string(char *buf, char *end, u8 *addr, | 701 | static noinline_for_stack |
| 693 | struct printf_spec spec, const char *fmt) | 702 | char *mac_address_string(char *buf, char *end, u8 *addr, |
| 703 | struct printf_spec spec, const char *fmt) | ||
| 694 | { | 704 | { |
| 695 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; | 705 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; |
| 696 | char *p = mac_addr; | 706 | char *p = mac_addr; |
| @@ -713,7 +723,8 @@ static char *mac_address_string(char *buf, char *end, u8 *addr, | |||
| 713 | return string(buf, end, mac_addr, spec); | 723 | return string(buf, end, mac_addr, spec); |
| 714 | } | 724 | } |
| 715 | 725 | ||
| 716 | static char *ip4_string(char *p, const u8 *addr, const char *fmt) | 726 | static noinline_for_stack |
| 727 | char *ip4_string(char *p, const u8 *addr, const char *fmt) | ||
| 717 | { | 728 | { |
| 718 | int i; | 729 | int i; |
| 719 | bool leading_zeros = (fmt[0] == 'i'); | 730 | bool leading_zeros = (fmt[0] == 'i'); |
| @@ -762,7 +773,8 @@ static char *ip4_string(char *p, const u8 *addr, const char *fmt) | |||
| 762 | return p; | 773 | return p; |
| 763 | } | 774 | } |
| 764 | 775 | ||
| 765 | static char *ip6_compressed_string(char *p, const char *addr) | 776 | static noinline_for_stack |
| 777 | char *ip6_compressed_string(char *p, const char *addr) | ||
| 766 | { | 778 | { |
| 767 | int i, j, range; | 779 | int i, j, range; |
| 768 | unsigned char zerolength[8]; | 780 | unsigned char zerolength[8]; |
| @@ -842,7 +854,8 @@ static char *ip6_compressed_string(char *p, const char *addr) | |||
| 842 | return p; | 854 | return p; |
| 843 | } | 855 | } |
| 844 | 856 | ||
| 845 | static char *ip6_string(char *p, const char *addr, const char *fmt) | 857 | static noinline_for_stack |
| 858 | char *ip6_string(char *p, const char *addr, const char *fmt) | ||
| 846 | { | 859 | { |
| 847 | int i; | 860 | int i; |
| 848 | 861 | ||
| @@ -857,8 +870,9 @@ static char *ip6_string(char *p, const char *addr, const char *fmt) | |||
| 857 | return p; | 870 | return p; |
| 858 | } | 871 | } |
| 859 | 872 | ||
| 860 | static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | 873 | static noinline_for_stack |
| 861 | struct printf_spec spec, const char *fmt) | 874 | char *ip6_addr_string(char *buf, char *end, const u8 *addr, |
| 875 | struct printf_spec spec, const char *fmt) | ||
| 862 | { | 876 | { |
| 863 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; | 877 | char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; |
| 864 | 878 | ||
| @@ -870,8 +884,9 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | |||
| 870 | return string(buf, end, ip6_addr, spec); | 884 | return string(buf, end, ip6_addr, spec); |
| 871 | } | 885 | } |
| 872 | 886 | ||
| 873 | static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | 887 | static noinline_for_stack |
| 874 | struct printf_spec spec, const char *fmt) | 888 | char *ip4_addr_string(char *buf, char *end, const u8 *addr, |
| 889 | struct printf_spec spec, const char *fmt) | ||
| 875 | { | 890 | { |
| 876 | char ip4_addr[sizeof("255.255.255.255")]; | 891 | char ip4_addr[sizeof("255.255.255.255")]; |
| 877 | 892 | ||
| @@ -880,8 +895,9 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | |||
| 880 | return string(buf, end, ip4_addr, spec); | 895 | return string(buf, end, ip4_addr, spec); |
| 881 | } | 896 | } |
| 882 | 897 | ||
| 883 | static char *uuid_string(char *buf, char *end, const u8 *addr, | 898 | static noinline_for_stack |
| 884 | struct printf_spec spec, const char *fmt) | 899 | char *uuid_string(char *buf, char *end, const u8 *addr, |
| 900 | struct printf_spec spec, const char *fmt) | ||
| 885 | { | 901 | { |
| 886 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; | 902 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; |
| 887 | char *p = uuid; | 903 | char *p = uuid; |
| @@ -964,13 +980,19 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
| 964 | * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] | 980 | * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] |
| 965 | * little endian output byte order is: | 981 | * little endian output byte order is: |
| 966 | * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] | 982 | * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] |
| 983 | * - 'V' For a struct va_format which contains a format string * and va_list *, | ||
| 984 | * call vsnprintf(->format, *->va_list). | ||
| 985 | * Implements a "recursive vsnprintf". | ||
| 986 | * Do not use this feature without some mechanism to verify the | ||
| 987 | * correctness of the format string and va_list arguments. | ||
| 967 | * | 988 | * |
| 968 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 989 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
| 969 | * function pointers are really function descriptors, which contain a | 990 | * function pointers are really function descriptors, which contain a |
| 970 | * pointer to the real address. | 991 | * pointer to the real address. |
| 971 | */ | 992 | */ |
| 972 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 993 | static noinline_for_stack |
| 973 | struct printf_spec spec) | 994 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
| 995 | struct printf_spec spec) | ||
| 974 | { | 996 | { |
| 975 | if (!ptr) | 997 | if (!ptr) |
| 976 | return string(buf, end, "(null)", spec); | 998 | return string(buf, end, "(null)", spec); |
| @@ -1008,6 +1030,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1008 | break; | 1030 | break; |
| 1009 | case 'U': | 1031 | case 'U': |
| 1010 | return uuid_string(buf, end, ptr, spec, fmt); | 1032 | return uuid_string(buf, end, ptr, spec, fmt); |
| 1033 | case 'V': | ||
| 1034 | return buf + vsnprintf(buf, end - buf, | ||
| 1035 | ((struct va_format *)ptr)->fmt, | ||
| 1036 | *(((struct va_format *)ptr)->va)); | ||
| 1011 | } | 1037 | } |
| 1012 | spec.flags |= SMALL; | 1038 | spec.flags |= SMALL; |
| 1013 | if (spec.field_width == -1) { | 1039 | if (spec.field_width == -1) { |
| @@ -1039,7 +1065,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1039 | * @precision: precision of a number | 1065 | * @precision: precision of a number |
| 1040 | * @qualifier: qualifier of a number (long, size_t, ...) | 1066 | * @qualifier: qualifier of a number (long, size_t, ...) |
| 1041 | */ | 1067 | */ |
| 1042 | static int format_decode(const char *fmt, struct printf_spec *spec) | 1068 | static noinline_for_stack |
| 1069 | int format_decode(const char *fmt, struct printf_spec *spec) | ||
| 1043 | { | 1070 | { |
| 1044 | const char *start = fmt; | 1071 | const char *start = fmt; |
| 1045 | 1072 | ||
| @@ -1979,7 +2006,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
| 1979 | { | 2006 | { |
| 1980 | char *s = (char *)va_arg(args, char *); | 2007 | char *s = (char *)va_arg(args, char *); |
| 1981 | if (field_width == -1) | 2008 | if (field_width == -1) |
| 1982 | field_width = SHORT_MAX; | 2009 | field_width = SHRT_MAX; |
| 1983 | /* first, skip leading white space in buffer */ | 2010 | /* first, skip leading white space in buffer */ |
| 1984 | str = skip_spaces(str); | 2011 | str = skip_spaces(str); |
| 1985 | 2012 | ||
