diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 207 |
1 files changed, 143 insertions, 64 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3b8aeec4e327..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; |
@@ -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 |
@@ -915,13 +980,19 @@ static char *uuid_string(char *buf, char *end, const u8 *addr, | |||
915 | * [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] |
916 | * little endian output byte order is: | 981 | * little endian output byte order is: |
917 | * [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. | ||
918 | * | 988 | * |
919 | * 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 |
920 | * function pointers are really function descriptors, which contain a | 990 | * function pointers are really function descriptors, which contain a |
921 | * pointer to the real address. | 991 | * pointer to the real address. |
922 | */ | 992 | */ |
923 | static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 993 | static noinline_for_stack |
924 | struct printf_spec spec) | 994 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
995 | struct printf_spec spec) | ||
925 | { | 996 | { |
926 | if (!ptr) | 997 | if (!ptr) |
927 | return string(buf, end, "(null)", spec); | 998 | return string(buf, end, "(null)", spec); |
@@ -939,6 +1010,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
939 | return resource_string(buf, end, ptr, spec, fmt); | 1010 | return resource_string(buf, end, ptr, spec, fmt); |
940 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 1011 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
941 | case 'm': /* Contiguous: 000102030405 */ | 1012 | case 'm': /* Contiguous: 000102030405 */ |
1013 | /* [mM]F (FDDI, bit reversed) */ | ||
942 | return mac_address_string(buf, end, ptr, spec, fmt); | 1014 | return mac_address_string(buf, end, ptr, spec, fmt); |
943 | case 'I': /* Formatted IP supported | 1015 | case 'I': /* Formatted IP supported |
944 | * 4: 1.2.3.4 | 1016 | * 4: 1.2.3.4 |
@@ -958,6 +1030,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
958 | break; | 1030 | break; |
959 | case 'U': | 1031 | case 'U': |
960 | 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)); | ||
961 | } | 1037 | } |
962 | spec.flags |= SMALL; | 1038 | spec.flags |= SMALL; |
963 | if (spec.field_width == -1) { | 1039 | if (spec.field_width == -1) { |
@@ -989,7 +1065,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
989 | * @precision: precision of a number | 1065 | * @precision: precision of a number |
990 | * @qualifier: qualifier of a number (long, size_t, ...) | 1066 | * @qualifier: qualifier of a number (long, size_t, ...) |
991 | */ | 1067 | */ |
992 | 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) | ||
993 | { | 1070 | { |
994 | const char *start = fmt; | 1071 | const char *start = fmt; |
995 | 1072 | ||
@@ -1297,7 +1374,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1297 | break; | 1374 | break; |
1298 | 1375 | ||
1299 | case FORMAT_TYPE_NRCHARS: { | 1376 | case FORMAT_TYPE_NRCHARS: { |
1300 | int qualifier = spec.qualifier; | 1377 | u8 qualifier = spec.qualifier; |
1301 | 1378 | ||
1302 | if (qualifier == 'l') { | 1379 | if (qualifier == 'l') { |
1303 | long *ip = va_arg(args, long *); | 1380 | long *ip = va_arg(args, long *); |
@@ -1583,7 +1660,7 @@ do { \ | |||
1583 | 1660 | ||
1584 | case FORMAT_TYPE_NRCHARS: { | 1661 | case FORMAT_TYPE_NRCHARS: { |
1585 | /* skip %n 's argument */ | 1662 | /* skip %n 's argument */ |
1586 | int qualifier = spec.qualifier; | 1663 | u8 qualifier = spec.qualifier; |
1587 | void *skip_arg; | 1664 | void *skip_arg; |
1588 | if (qualifier == 'l') | 1665 | if (qualifier == 'l') |
1589 | skip_arg = va_arg(args, long *); | 1666 | skip_arg = va_arg(args, long *); |
@@ -1849,7 +1926,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
1849 | char *next; | 1926 | char *next; |
1850 | char digit; | 1927 | char digit; |
1851 | int num = 0; | 1928 | int num = 0; |
1852 | int qualifier, base, field_width; | 1929 | u8 qualifier; |
1930 | u8 base; | ||
1931 | s16 field_width; | ||
1853 | bool is_sign; | 1932 | bool is_sign; |
1854 | 1933 | ||
1855 | while (*fmt && *str) { | 1934 | while (*fmt && *str) { |
@@ -1927,7 +2006,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
1927 | { | 2006 | { |
1928 | char *s = (char *)va_arg(args, char *); | 2007 | char *s = (char *)va_arg(args, char *); |
1929 | if (field_width == -1) | 2008 | if (field_width == -1) |
1930 | field_width = INT_MAX; | 2009 | field_width = SHRT_MAX; |
1931 | /* first, skip leading white space in buffer */ | 2010 | /* first, skip leading white space in buffer */ |
1932 | str = skip_spaces(str); | 2011 | str = skip_spaces(str); |
1933 | 2012 | ||