diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 198 |
1 files changed, 134 insertions, 64 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3b8aeec4e327..b8a2f549ab0e 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; |
| @@ -381,8 +386,8 @@ static noinline char *put_dec(char *buf, unsigned long long num) | |||
| 381 | #define PLUS 4 /* show plus */ | 386 | #define PLUS 4 /* show plus */ |
| 382 | #define SPACE 8 /* space if plus */ | 387 | #define SPACE 8 /* space if plus */ |
| 383 | #define LEFT 16 /* left justified */ | 388 | #define LEFT 16 /* left justified */ |
| 384 | #define SMALL 32 /* Must be 32 == 0x20 */ | 389 | #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */ |
| 385 | #define SPECIAL 64 /* 0x */ | 390 | #define SPECIAL 64 /* prefix hex with "0x", octal with "0" */ |
| 386 | 391 | ||
| 387 | enum format_type { | 392 | enum format_type { |
| 388 | FORMAT_TYPE_NONE, /* Just a string part */ | 393 | FORMAT_TYPE_NONE, /* Just a string part */ |
| @@ -408,16 +413,17 @@ enum format_type { | |||
| 408 | }; | 413 | }; |
| 409 | 414 | ||
| 410 | struct printf_spec { | 415 | struct printf_spec { |
| 411 | enum format_type type; | 416 | u8 type; /* format_type enum */ |
| 412 | int flags; /* flags to number() */ | 417 | u8 flags; /* flags to number() */ |
| 413 | int field_width; /* width of output field */ | 418 | u8 base; /* number base, 8, 10 or 16 only */ |
| 414 | int base; | 419 | u8 qualifier; /* number qualifier, one of 'hHlLtzZ' */ |
| 415 | int precision; /* # of digits/chars */ | 420 | s16 field_width; /* width of output field */ |
| 416 | int qualifier; | 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 |
| @@ -597,22 +606,35 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
| 597 | #ifndef MEM_RSRC_PRINTK_SIZE | 606 | #ifndef MEM_RSRC_PRINTK_SIZE |
| 598 | #define MEM_RSRC_PRINTK_SIZE 10 | 607 | #define MEM_RSRC_PRINTK_SIZE 10 |
| 599 | #endif | 608 | #endif |
| 600 | struct printf_spec hex_spec = { | 609 | static const struct printf_spec io_spec = { |
| 601 | .base = 16, | 610 | .base = 16, |
| 611 | .field_width = IO_RSRC_PRINTK_SIZE, | ||
| 602 | .precision = -1, | 612 | .precision = -1, |
| 603 | .flags = SPECIAL | SMALL | ZEROPAD, | 613 | .flags = SPECIAL | SMALL | ZEROPAD, |
| 604 | }; | 614 | }; |
| 605 | struct printf_spec dec_spec = { | 615 | static const struct printf_spec mem_spec = { |
| 616 | .base = 16, | ||
| 617 | .field_width = MEM_RSRC_PRINTK_SIZE, | ||
| 618 | .precision = -1, | ||
| 619 | .flags = SPECIAL | SMALL | ZEROPAD, | ||
| 620 | }; | ||
| 621 | static const struct printf_spec bus_spec = { | ||
| 622 | .base = 16, | ||
| 623 | .field_width = 2, | ||
| 624 | .precision = -1, | ||
| 625 | .flags = SMALL | ZEROPAD, | ||
| 626 | }; | ||
| 627 | static const struct printf_spec dec_spec = { | ||
| 606 | .base = 10, | 628 | .base = 10, |
| 607 | .precision = -1, | 629 | .precision = -1, |
| 608 | .flags = 0, | 630 | .flags = 0, |
| 609 | }; | 631 | }; |
| 610 | struct printf_spec str_spec = { | 632 | static const struct printf_spec str_spec = { |
| 611 | .field_width = -1, | 633 | .field_width = -1, |
| 612 | .precision = 10, | 634 | .precision = 10, |
| 613 | .flags = LEFT, | 635 | .flags = LEFT, |
| 614 | }; | 636 | }; |
| 615 | struct printf_spec flag_spec = { | 637 | static const struct printf_spec flag_spec = { |
| 616 | .base = 16, | 638 | .base = 16, |
| 617 | .precision = -1, | 639 | .precision = -1, |
| 618 | .flags = SPECIAL | SMALL, | 640 | .flags = SPECIAL | SMALL, |
| @@ -622,47 +644,48 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
| 622 | * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ | 644 | * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ |
| 623 | #define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4) | 645 | #define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4) |
| 624 | #define FLAG_BUF_SIZE (2 * sizeof(res->flags)) | 646 | #define FLAG_BUF_SIZE (2 * sizeof(res->flags)) |
| 625 | #define DECODED_BUF_SIZE sizeof("[mem - 64bit pref disabled]") | 647 | #define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]") |
| 626 | #define RAW_BUF_SIZE sizeof("[mem - flags 0x]") | 648 | #define RAW_BUF_SIZE sizeof("[mem - flags 0x]") |
| 627 | char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, | 649 | char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, |
| 628 | 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; | 650 | 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; |
| 629 | 651 | ||
| 630 | char *p = sym, *pend = sym + sizeof(sym); | 652 | char *p = sym, *pend = sym + sizeof(sym); |
| 631 | int size = -1, addr = 0; | ||
| 632 | int decode = (fmt[0] == 'R') ? 1 : 0; | 653 | int decode = (fmt[0] == 'R') ? 1 : 0; |
| 633 | 654 | const struct printf_spec *specp; | |
| 634 | if (res->flags & IORESOURCE_IO) { | ||
| 635 | size = IO_RSRC_PRINTK_SIZE; | ||
| 636 | addr = 1; | ||
| 637 | } else if (res->flags & IORESOURCE_MEM) { | ||
| 638 | size = MEM_RSRC_PRINTK_SIZE; | ||
| 639 | addr = 1; | ||
| 640 | } | ||
| 641 | 655 | ||
| 642 | *p++ = '['; | 656 | *p++ = '['; |
| 643 | if (res->flags & IORESOURCE_IO) | 657 | if (res->flags & IORESOURCE_IO) { |
| 644 | p = string(p, pend, "io ", str_spec); | 658 | p = string(p, pend, "io ", str_spec); |
| 645 | else if (res->flags & IORESOURCE_MEM) | 659 | specp = &io_spec; |
| 660 | } else if (res->flags & IORESOURCE_MEM) { | ||
| 646 | p = string(p, pend, "mem ", str_spec); | 661 | p = string(p, pend, "mem ", str_spec); |
| 647 | else if (res->flags & IORESOURCE_IRQ) | 662 | specp = &mem_spec; |
| 663 | } else if (res->flags & IORESOURCE_IRQ) { | ||
| 648 | p = string(p, pend, "irq ", str_spec); | 664 | p = string(p, pend, "irq ", str_spec); |
| 649 | else if (res->flags & IORESOURCE_DMA) | 665 | specp = &dec_spec; |
| 666 | } else if (res->flags & IORESOURCE_DMA) { | ||
| 650 | p = string(p, pend, "dma ", str_spec); | 667 | p = string(p, pend, "dma ", str_spec); |
| 651 | else { | 668 | specp = &dec_spec; |
| 669 | } else if (res->flags & IORESOURCE_BUS) { | ||
| 670 | p = string(p, pend, "bus ", str_spec); | ||
| 671 | specp = &bus_spec; | ||
| 672 | } else { | ||
| 652 | p = string(p, pend, "??? ", str_spec); | 673 | p = string(p, pend, "??? ", str_spec); |
| 674 | specp = &mem_spec; | ||
| 653 | decode = 0; | 675 | decode = 0; |
| 654 | } | 676 | } |
| 655 | hex_spec.field_width = size; | 677 | p = number(p, pend, res->start, *specp); |
| 656 | p = number(p, pend, res->start, addr ? hex_spec : dec_spec); | ||
| 657 | if (res->start != res->end) { | 678 | if (res->start != res->end) { |
| 658 | *p++ = '-'; | 679 | *p++ = '-'; |
| 659 | p = number(p, pend, res->end, addr ? hex_spec : dec_spec); | 680 | p = number(p, pend, res->end, *specp); |
| 660 | } | 681 | } |
| 661 | if (decode) { | 682 | if (decode) { |
| 662 | if (res->flags & IORESOURCE_MEM_64) | 683 | if (res->flags & IORESOURCE_MEM_64) |
| 663 | p = string(p, pend, " 64bit", str_spec); | 684 | p = string(p, pend, " 64bit", str_spec); |
| 664 | if (res->flags & IORESOURCE_PREFETCH) | 685 | if (res->flags & IORESOURCE_PREFETCH) |
| 665 | p = string(p, pend, " pref", str_spec); | 686 | p = string(p, pend, " pref", str_spec); |
| 687 | if (res->flags & IORESOURCE_WINDOW) | ||
| 688 | p = string(p, pend, " window", str_spec); | ||
| 666 | if (res->flags & IORESOURCE_DISABLED) | 689 | if (res->flags & IORESOURCE_DISABLED) |
| 667 | p = string(p, pend, " disabled", str_spec); | 690 | p = string(p, pend, " disabled", str_spec); |
| 668 | } else { | 691 | } else { |
| @@ -675,30 +698,63 @@ static char *resource_string(char *buf, char *end, struct resource *res, | |||
| 675 | return string(buf, end, sym, spec); | 698 | return string(buf, end, sym, spec); |
| 676 | } | 699 | } |
| 677 | 700 | ||
| 678 | static char *mac_address_string(char *buf, char *end, u8 *addr, | 701 | static noinline_for_stack |
| 679 | 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) | ||
| 680 | { | 704 | { |
| 681 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; | 705 | char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; |
| 682 | char *p = mac_addr; | 706 | char *p = mac_addr; |
| 683 | int i; | 707 | int i; |
| 708 | char separator; | ||
| 709 | |||
| 710 | if (fmt[1] == 'F') { /* FDDI canonical format */ | ||
| 711 | separator = '-'; | ||
| 712 | } else { | ||
| 713 | separator = ':'; | ||
| 714 | } | ||
| 684 | 715 | ||
| 685 | for (i = 0; i < 6; i++) { | 716 | for (i = 0; i < 6; i++) { |
| 686 | p = pack_hex_byte(p, addr[i]); | 717 | p = pack_hex_byte(p, addr[i]); |
| 687 | if (fmt[0] == 'M' && i != 5) | 718 | if (fmt[0] == 'M' && i != 5) |
| 688 | *p++ = ':'; | 719 | *p++ = separator; |
| 689 | } | 720 | } |
| 690 | *p = '\0'; | 721 | *p = '\0'; |
| 691 | 722 | ||
| 692 | return string(buf, end, mac_addr, spec); | 723 | return string(buf, end, mac_addr, spec); |
| 693 | } | 724 | } |
| 694 | 725 | ||
| 695 | static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) | 726 | static noinline_for_stack |
| 727 | char *ip4_string(char *p, const u8 *addr, const char *fmt) | ||
| 696 | { | 728 | { |
| 697 | int i; | 729 | int i; |
| 698 | 730 | bool leading_zeros = (fmt[0] == 'i'); | |
| 731 | int index; | ||
| 732 | int step; | ||
| 733 | |||
| 734 | switch (fmt[2]) { | ||
| 735 | case 'h': | ||
| 736 | #ifdef __BIG_ENDIAN | ||
| 737 | index = 0; | ||
| 738 | step = 1; | ||
| 739 | #else | ||
| 740 | index = 3; | ||
| 741 | step = -1; | ||
| 742 | #endif | ||
| 743 | break; | ||
| 744 | case 'l': | ||
| 745 | index = 3; | ||
| 746 | step = -1; | ||
| 747 | break; | ||
| 748 | case 'n': | ||
| 749 | case 'b': | ||
| 750 | default: | ||
| 751 | index = 0; | ||
| 752 | step = 1; | ||
| 753 | break; | ||
| 754 | } | ||
| 699 | for (i = 0; i < 4; i++) { | 755 | for (i = 0; i < 4; i++) { |
| 700 | char temp[3]; /* hold each IP quad in reverse order */ | 756 | char temp[3]; /* hold each IP quad in reverse order */ |
| 701 | int digits = put_dec_trunc(temp, addr[i]) - temp; | 757 | int digits = put_dec_trunc(temp, addr[index]) - temp; |
| 702 | if (leading_zeros) { | 758 | if (leading_zeros) { |
| 703 | if (digits < 3) | 759 | if (digits < 3) |
| 704 | *p++ = '0'; | 760 | *p++ = '0'; |
| @@ -710,13 +766,15 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) | |||
| 710 | *p++ = temp[digits]; | 766 | *p++ = temp[digits]; |
| 711 | if (i < 3) | 767 | if (i < 3) |
| 712 | *p++ = '.'; | 768 | *p++ = '.'; |
| 769 | index += step; | ||
| 713 | } | 770 | } |
| 714 | *p = '\0'; | 771 | *p = '\0'; |
| 715 | 772 | ||
| 716 | return p; | 773 | return p; |
| 717 | } | 774 | } |
| 718 | 775 | ||
| 719 | 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) | ||
| 720 | { | 778 | { |
| 721 | int i, j, range; | 779 | int i, j, range; |
| 722 | unsigned char zerolength[8]; | 780 | unsigned char zerolength[8]; |
| @@ -789,14 +847,15 @@ static char *ip6_compressed_string(char *p, const char *addr) | |||
| 789 | if (useIPv4) { | 847 | if (useIPv4) { |
| 790 | if (needcolon) | 848 | if (needcolon) |
| 791 | *p++ = ':'; | 849 | *p++ = ':'; |
| 792 | p = ip4_string(p, &in6.s6_addr[12], false); | 850 | p = ip4_string(p, &in6.s6_addr[12], "I4"); |
| 793 | } | 851 | } |
| 794 | *p = '\0'; | 852 | *p = '\0'; |
| 795 | 853 | ||
| 796 | return p; | 854 | return p; |
| 797 | } | 855 | } |
| 798 | 856 | ||
| 799 | 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) | ||
| 800 | { | 859 | { |
| 801 | int i; | 860 | int i; |
| 802 | 861 | ||
| @@ -811,8 +870,9 @@ static char *ip6_string(char *p, const char *addr, const char *fmt) | |||
| 811 | return p; | 870 | return p; |
| 812 | } | 871 | } |
| 813 | 872 | ||
| 814 | static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | 873 | static noinline_for_stack |
| 815 | 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) | ||
| 816 | { | 876 | { |
| 817 | 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")]; |
| 818 | 878 | ||
| @@ -824,18 +884,20 @@ static char *ip6_addr_string(char *buf, char *end, const u8 *addr, | |||
| 824 | return string(buf, end, ip6_addr, spec); | 884 | return string(buf, end, ip6_addr, spec); |
| 825 | } | 885 | } |
| 826 | 886 | ||
| 827 | static char *ip4_addr_string(char *buf, char *end, const u8 *addr, | 887 | static noinline_for_stack |
| 828 | 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) | ||
| 829 | { | 890 | { |
| 830 | char ip4_addr[sizeof("255.255.255.255")]; | 891 | char ip4_addr[sizeof("255.255.255.255")]; |
| 831 | 892 | ||
| 832 | ip4_string(ip4_addr, addr, fmt[0] == 'i'); | 893 | ip4_string(ip4_addr, addr, fmt); |
| 833 | 894 | ||
| 834 | return string(buf, end, ip4_addr, spec); | 895 | return string(buf, end, ip4_addr, spec); |
| 835 | } | 896 | } |
| 836 | 897 | ||
| 837 | static char *uuid_string(char *buf, char *end, const u8 *addr, | 898 | static noinline_for_stack |
| 838 | 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) | ||
| 839 | { | 901 | { |
| 840 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; | 902 | char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; |
| 841 | char *p = uuid; | 903 | char *p = uuid; |
| @@ -896,12 +958,15 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
| 896 | * - 'M' For a 6-byte MAC address, it prints the address in the | 958 | * - 'M' For a 6-byte MAC address, it prints the address in the |
| 897 | * usual colon-separated hex notation | 959 | * usual colon-separated hex notation |
| 898 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons | 960 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons |
| 961 | * - 'MF' For a 6-byte MAC FDDI address, it prints the address | ||
| 962 | * with a dash-separated hex notation | ||
| 899 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way | 963 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way |
| 900 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) | 964 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) |
| 901 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's | 965 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's |
| 902 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses | 966 | * - 'i' [46] for 'raw' IPv4/IPv6 addresses |
| 903 | * IPv6 omits the colons (01020304...0f) | 967 | * IPv6 omits the colons (01020304...0f) |
| 904 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) | 968 | * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) |
| 969 | * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order | ||
| 905 | * - 'I6c' for IPv6 addresses printed as specified by | 970 | * - 'I6c' for IPv6 addresses printed as specified by |
| 906 | * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 | 971 | * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 |
| 907 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form | 972 | * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form |
| @@ -920,8 +985,9 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
| 920 | * function pointers are really function descriptors, which contain a | 985 | * function pointers are really function descriptors, which contain a |
| 921 | * pointer to the real address. | 986 | * pointer to the real address. |
| 922 | */ | 987 | */ |
| 923 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 988 | static noinline_for_stack |
| 924 | struct printf_spec spec) | 989 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
| 990 | struct printf_spec spec) | ||
| 925 | { | 991 | { |
| 926 | if (!ptr) | 992 | if (!ptr) |
| 927 | return string(buf, end, "(null)", spec); | 993 | return string(buf, end, "(null)", spec); |
| @@ -939,6 +1005,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 939 | return resource_string(buf, end, ptr, spec, fmt); | 1005 | return resource_string(buf, end, ptr, spec, fmt); |
| 940 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 1006 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
| 941 | case 'm': /* Contiguous: 000102030405 */ | 1007 | case 'm': /* Contiguous: 000102030405 */ |
| 1008 | /* [mM]F (FDDI, bit reversed) */ | ||
| 942 | return mac_address_string(buf, end, ptr, spec, fmt); | 1009 | return mac_address_string(buf, end, ptr, spec, fmt); |
| 943 | case 'I': /* Formatted IP supported | 1010 | case 'I': /* Formatted IP supported |
| 944 | * 4: 1.2.3.4 | 1011 | * 4: 1.2.3.4 |
| @@ -989,7 +1056,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 989 | * @precision: precision of a number | 1056 | * @precision: precision of a number |
| 990 | * @qualifier: qualifier of a number (long, size_t, ...) | 1057 | * @qualifier: qualifier of a number (long, size_t, ...) |
| 991 | */ | 1058 | */ |
| 992 | static int format_decode(const char *fmt, struct printf_spec *spec) | 1059 | static noinline_for_stack |
| 1060 | int format_decode(const char *fmt, struct printf_spec *spec) | ||
| 993 | { | 1061 | { |
| 994 | const char *start = fmt; | 1062 | const char *start = fmt; |
| 995 | 1063 | ||
| @@ -1297,7 +1365,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1297 | break; | 1365 | break; |
| 1298 | 1366 | ||
| 1299 | case FORMAT_TYPE_NRCHARS: { | 1367 | case FORMAT_TYPE_NRCHARS: { |
| 1300 | int qualifier = spec.qualifier; | 1368 | u8 qualifier = spec.qualifier; |
| 1301 | 1369 | ||
| 1302 | if (qualifier == 'l') { | 1370 | if (qualifier == 'l') { |
| 1303 | long *ip = va_arg(args, long *); | 1371 | long *ip = va_arg(args, long *); |
| @@ -1583,7 +1651,7 @@ do { \ | |||
| 1583 | 1651 | ||
| 1584 | case FORMAT_TYPE_NRCHARS: { | 1652 | case FORMAT_TYPE_NRCHARS: { |
| 1585 | /* skip %n 's argument */ | 1653 | /* skip %n 's argument */ |
| 1586 | int qualifier = spec.qualifier; | 1654 | u8 qualifier = spec.qualifier; |
| 1587 | void *skip_arg; | 1655 | void *skip_arg; |
| 1588 | if (qualifier == 'l') | 1656 | if (qualifier == 'l') |
| 1589 | skip_arg = va_arg(args, long *); | 1657 | skip_arg = va_arg(args, long *); |
| @@ -1849,7 +1917,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
| 1849 | char *next; | 1917 | char *next; |
| 1850 | char digit; | 1918 | char digit; |
| 1851 | int num = 0; | 1919 | int num = 0; |
| 1852 | int qualifier, base, field_width; | 1920 | u8 qualifier; |
| 1921 | u8 base; | ||
| 1922 | s16 field_width; | ||
| 1853 | bool is_sign; | 1923 | bool is_sign; |
| 1854 | 1924 | ||
| 1855 | while (*fmt && *str) { | 1925 | while (*fmt && *str) { |
| @@ -1927,7 +1997,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
| 1927 | { | 1997 | { |
| 1928 | char *s = (char *)va_arg(args, char *); | 1998 | char *s = (char *)va_arg(args, char *); |
| 1929 | if (field_width == -1) | 1999 | if (field_width == -1) |
| 1930 | field_width = INT_MAX; | 2000 | field_width = SHRT_MAX; |
| 1931 | /* first, skip leading white space in buffer */ | 2001 | /* first, skip leading white space in buffer */ |
| 1932 | str = skip_spaces(str); | 2002 | str = skip_spaces(str); |
| 1933 | 2003 | ||
