aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c137
1 files changed, 95 insertions, 42 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d4996cf46eb6..46d34b0b74a8 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}
121EXPORT_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
@@ -381,8 +382,8 @@ static noinline char *put_dec(char *buf, unsigned long long num)
381#define PLUS 4 /* show plus */ 382#define PLUS 4 /* show plus */
382#define SPACE 8 /* space if plus */ 383#define SPACE 8 /* space if plus */
383#define LEFT 16 /* left justified */ 384#define LEFT 16 /* left justified */
384#define SMALL 32 /* Must be 32 == 0x20 */ 385#define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
385#define SPECIAL 64 /* 0x */ 386#define SPECIAL 64 /* prefix hex with "0x", octal with "0" */
386 387
387enum format_type { 388enum format_type {
388 FORMAT_TYPE_NONE, /* Just a string part */ 389 FORMAT_TYPE_NONE, /* Just a string part */
@@ -408,12 +409,12 @@ enum format_type {
408}; 409};
409 410
410struct printf_spec { 411struct printf_spec {
411 enum format_type type; 412 u8 type; /* format_type enum */
412 int flags; /* flags to number() */ 413 u8 flags; /* flags to number() */
413 int field_width; /* width of output field */ 414 u8 base; /* number base, 8, 10 or 16 only */
414 int base; 415 u8 qualifier; /* number qualifier, one of 'hHlLtzZ' */
415 int precision; /* # of digits/chars */ 416 s16 field_width; /* width of output field */
416 int qualifier; 417 s16 precision; /* # of digits/chars */
417}; 418};
418 419
419static char *number(char *buf, char *end, unsigned long long num, 420static char *number(char *buf, char *end, unsigned long long num,
@@ -597,22 +598,35 @@ static char *resource_string(char *buf, char *end, struct resource *res,
597#ifndef MEM_RSRC_PRINTK_SIZE 598#ifndef MEM_RSRC_PRINTK_SIZE
598#define MEM_RSRC_PRINTK_SIZE 10 599#define MEM_RSRC_PRINTK_SIZE 10
599#endif 600#endif
600 struct printf_spec hex_spec = { 601 static const struct printf_spec io_spec = {
601 .base = 16, 602 .base = 16,
603 .field_width = IO_RSRC_PRINTK_SIZE,
602 .precision = -1, 604 .precision = -1,
603 .flags = SPECIAL | SMALL | ZEROPAD, 605 .flags = SPECIAL | SMALL | ZEROPAD,
604 }; 606 };
605 struct printf_spec dec_spec = { 607 static const struct printf_spec mem_spec = {
608 .base = 16,
609 .field_width = MEM_RSRC_PRINTK_SIZE,
610 .precision = -1,
611 .flags = SPECIAL | SMALL | ZEROPAD,
612 };
613 static const struct printf_spec bus_spec = {
614 .base = 16,
615 .field_width = 2,
616 .precision = -1,
617 .flags = SMALL | ZEROPAD,
618 };
619 static const struct printf_spec dec_spec = {
606 .base = 10, 620 .base = 10,
607 .precision = -1, 621 .precision = -1,
608 .flags = 0, 622 .flags = 0,
609 }; 623 };
610 struct printf_spec str_spec = { 624 static const struct printf_spec str_spec = {
611 .field_width = -1, 625 .field_width = -1,
612 .precision = 10, 626 .precision = 10,
613 .flags = LEFT, 627 .flags = LEFT,
614 }; 628 };
615 struct printf_spec flag_spec = { 629 static const struct printf_spec flag_spec = {
616 .base = 16, 630 .base = 16,
617 .precision = -1, 631 .precision = -1,
618 .flags = SPECIAL | SMALL, 632 .flags = SPECIAL | SMALL,
@@ -622,47 +636,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) */ 636 * 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) 637#define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4)
624#define FLAG_BUF_SIZE (2 * sizeof(res->flags)) 638#define FLAG_BUF_SIZE (2 * sizeof(res->flags))
625#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref disabled]") 639#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")
626#define RAW_BUF_SIZE sizeof("[mem - flags 0x]") 640#define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
627 char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE, 641 char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
628 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)]; 642 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
629 643
630 char *p = sym, *pend = sym + sizeof(sym); 644 char *p = sym, *pend = sym + sizeof(sym);
631 int size = -1, addr = 0;
632 int decode = (fmt[0] == 'R') ? 1 : 0; 645 int decode = (fmt[0] == 'R') ? 1 : 0;
633 646 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 647
642 *p++ = '['; 648 *p++ = '[';
643 if (res->flags & IORESOURCE_IO) 649 if (res->flags & IORESOURCE_IO) {
644 p = string(p, pend, "io ", str_spec); 650 p = string(p, pend, "io ", str_spec);
645 else if (res->flags & IORESOURCE_MEM) 651 specp = &io_spec;
652 } else if (res->flags & IORESOURCE_MEM) {
646 p = string(p, pend, "mem ", str_spec); 653 p = string(p, pend, "mem ", str_spec);
647 else if (res->flags & IORESOURCE_IRQ) 654 specp = &mem_spec;
655 } else if (res->flags & IORESOURCE_IRQ) {
648 p = string(p, pend, "irq ", str_spec); 656 p = string(p, pend, "irq ", str_spec);
649 else if (res->flags & IORESOURCE_DMA) 657 specp = &dec_spec;
658 } else if (res->flags & IORESOURCE_DMA) {
650 p = string(p, pend, "dma ", str_spec); 659 p = string(p, pend, "dma ", str_spec);
651 else { 660 specp = &dec_spec;
661 } else if (res->flags & IORESOURCE_BUS) {
662 p = string(p, pend, "bus ", str_spec);
663 specp = &bus_spec;
664 } else {
652 p = string(p, pend, "??? ", str_spec); 665 p = string(p, pend, "??? ", str_spec);
666 specp = &mem_spec;
653 decode = 0; 667 decode = 0;
654 } 668 }
655 hex_spec.field_width = size; 669 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) { 670 if (res->start != res->end) {
658 *p++ = '-'; 671 *p++ = '-';
659 p = number(p, pend, res->end, addr ? hex_spec : dec_spec); 672 p = number(p, pend, res->end, *specp);
660 } 673 }
661 if (decode) { 674 if (decode) {
662 if (res->flags & IORESOURCE_MEM_64) 675 if (res->flags & IORESOURCE_MEM_64)
663 p = string(p, pend, " 64bit", str_spec); 676 p = string(p, pend, " 64bit", str_spec);
664 if (res->flags & IORESOURCE_PREFETCH) 677 if (res->flags & IORESOURCE_PREFETCH)
665 p = string(p, pend, " pref", str_spec); 678 p = string(p, pend, " pref", str_spec);
679 if (res->flags & IORESOURCE_WINDOW)
680 p = string(p, pend, " window", str_spec);
666 if (res->flags & IORESOURCE_DISABLED) 681 if (res->flags & IORESOURCE_DISABLED)
667 p = string(p, pend, " disabled", str_spec); 682 p = string(p, pend, " disabled", str_spec);
668 } else { 683 } else {
@@ -681,24 +696,55 @@ static char *mac_address_string(char *buf, char *end, u8 *addr,
681 char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")]; 696 char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
682 char *p = mac_addr; 697 char *p = mac_addr;
683 int i; 698 int i;
699 char separator;
700
701 if (fmt[1] == 'F') { /* FDDI canonical format */
702 separator = '-';
703 } else {
704 separator = ':';
705 }
684 706
685 for (i = 0; i < 6; i++) { 707 for (i = 0; i < 6; i++) {
686 p = pack_hex_byte(p, addr[i]); 708 p = pack_hex_byte(p, addr[i]);
687 if (fmt[0] == 'M' && i != 5) 709 if (fmt[0] == 'M' && i != 5)
688 *p++ = ':'; 710 *p++ = separator;
689 } 711 }
690 *p = '\0'; 712 *p = '\0';
691 713
692 return string(buf, end, mac_addr, spec); 714 return string(buf, end, mac_addr, spec);
693} 715}
694 716
695static char *ip4_string(char *p, const u8 *addr, bool leading_zeros) 717static char *ip4_string(char *p, const u8 *addr, const char *fmt)
696{ 718{
697 int i; 719 int i;
698 720 bool leading_zeros = (fmt[0] == 'i');
721 int index;
722 int step;
723
724 switch (fmt[2]) {
725 case 'h':
726#ifdef __BIG_ENDIAN
727 index = 0;
728 step = 1;
729#else
730 index = 3;
731 step = -1;
732#endif
733 break;
734 case 'l':
735 index = 3;
736 step = -1;
737 break;
738 case 'n':
739 case 'b':
740 default:
741 index = 0;
742 step = 1;
743 break;
744 }
699 for (i = 0; i < 4; i++) { 745 for (i = 0; i < 4; i++) {
700 char temp[3]; /* hold each IP quad in reverse order */ 746 char temp[3]; /* hold each IP quad in reverse order */
701 int digits = put_dec_trunc(temp, addr[i]) - temp; 747 int digits = put_dec_trunc(temp, addr[index]) - temp;
702 if (leading_zeros) { 748 if (leading_zeros) {
703 if (digits < 3) 749 if (digits < 3)
704 *p++ = '0'; 750 *p++ = '0';
@@ -710,6 +756,7 @@ static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
710 *p++ = temp[digits]; 756 *p++ = temp[digits];
711 if (i < 3) 757 if (i < 3)
712 *p++ = '.'; 758 *p++ = '.';
759 index += step;
713 } 760 }
714 *p = '\0'; 761 *p = '\0';
715 762
@@ -789,7 +836,7 @@ static char *ip6_compressed_string(char *p, const char *addr)
789 if (useIPv4) { 836 if (useIPv4) {
790 if (needcolon) 837 if (needcolon)
791 *p++ = ':'; 838 *p++ = ':';
792 p = ip4_string(p, &in6.s6_addr[12], false); 839 p = ip4_string(p, &in6.s6_addr[12], "I4");
793 } 840 }
794 *p = '\0'; 841 *p = '\0';
795 842
@@ -829,7 +876,7 @@ static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
829{ 876{
830 char ip4_addr[sizeof("255.255.255.255")]; 877 char ip4_addr[sizeof("255.255.255.255")];
831 878
832 ip4_string(ip4_addr, addr, fmt[0] == 'i'); 879 ip4_string(ip4_addr, addr, fmt);
833 880
834 return string(buf, end, ip4_addr, spec); 881 return string(buf, end, ip4_addr, spec);
835} 882}
@@ -896,14 +943,17 @@ 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 943 * - 'M' For a 6-byte MAC address, it prints the address in the
897 * usual colon-separated hex notation 944 * usual colon-separated hex notation
898 * - 'm' For a 6-byte MAC address, it prints the hex address without colons 945 * - 'm' For a 6-byte MAC address, it prints the hex address without colons
946 * - 'MF' For a 6-byte MAC FDDI address, it prints the address
947 * with a dash-separated hex notation
899 * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way 948 * - '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) 949 * 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 950 * IPv6 uses colon separated network-order 16 bit hex with leading 0's
902 * - 'i' [46] for 'raw' IPv4/IPv6 addresses 951 * - 'i' [46] for 'raw' IPv4/IPv6 addresses
903 * IPv6 omits the colons (01020304...0f) 952 * IPv6 omits the colons (01020304...0f)
904 * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006) 953 * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
954 * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
905 * - 'I6c' for IPv6 addresses printed as specified by 955 * - 'I6c' for IPv6 addresses printed as specified by
906 * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt 956 * 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 957 * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
908 * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 958 * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
909 * Options for %pU are: 959 * Options for %pU are:
@@ -939,6 +989,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
939 return resource_string(buf, end, ptr, spec, fmt); 989 return resource_string(buf, end, ptr, spec, fmt);
940 case 'M': /* Colon separated: 00:01:02:03:04:05 */ 990 case 'M': /* Colon separated: 00:01:02:03:04:05 */
941 case 'm': /* Contiguous: 000102030405 */ 991 case 'm': /* Contiguous: 000102030405 */
992 /* [mM]F (FDDI, bit reversed) */
942 return mac_address_string(buf, end, ptr, spec, fmt); 993 return mac_address_string(buf, end, ptr, spec, fmt);
943 case 'I': /* Formatted IP supported 994 case 'I': /* Formatted IP supported
944 * 4: 1.2.3.4 995 * 4: 1.2.3.4
@@ -1188,7 +1239,7 @@ qualifier:
1188 * %pI6 print an IPv6 address with colons 1239 * %pI6 print an IPv6 address with colons
1189 * %pi6 print an IPv6 address without colons 1240 * %pi6 print an IPv6 address without colons
1190 * %pI6c print an IPv6 address as specified by 1241 * %pI6c print an IPv6 address as specified by
1191 * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt 1242 * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
1192 * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper 1243 * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
1193 * case. 1244 * case.
1194 * %n is ignored 1245 * %n is ignored
@@ -1297,7 +1348,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1297 break; 1348 break;
1298 1349
1299 case FORMAT_TYPE_NRCHARS: { 1350 case FORMAT_TYPE_NRCHARS: {
1300 int qualifier = spec.qualifier; 1351 u8 qualifier = spec.qualifier;
1301 1352
1302 if (qualifier == 'l') { 1353 if (qualifier == 'l') {
1303 long *ip = va_arg(args, long *); 1354 long *ip = va_arg(args, long *);
@@ -1583,7 +1634,7 @@ do { \
1583 1634
1584 case FORMAT_TYPE_NRCHARS: { 1635 case FORMAT_TYPE_NRCHARS: {
1585 /* skip %n 's argument */ 1636 /* skip %n 's argument */
1586 int qualifier = spec.qualifier; 1637 u8 qualifier = spec.qualifier;
1587 void *skip_arg; 1638 void *skip_arg;
1588 if (qualifier == 'l') 1639 if (qualifier == 'l')
1589 skip_arg = va_arg(args, long *); 1640 skip_arg = va_arg(args, long *);
@@ -1849,7 +1900,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
1849 char *next; 1900 char *next;
1850 char digit; 1901 char digit;
1851 int num = 0; 1902 int num = 0;
1852 int qualifier, base, field_width; 1903 u8 qualifier;
1904 u8 base;
1905 s16 field_width;
1853 bool is_sign; 1906 bool is_sign;
1854 1907
1855 while (*fmt && *str) { 1908 while (*fmt && *str) {
@@ -1927,7 +1980,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
1927 { 1980 {
1928 char *s = (char *)va_arg(args, char *); 1981 char *s = (char *)va_arg(args, char *);
1929 if (field_width == -1) 1982 if (field_width == -1)
1930 field_width = INT_MAX; 1983 field_width = SHORT_MAX;
1931 /* first, skip leading white space in buffer */ 1984 /* first, skip leading white space in buffer */
1932 str = skip_spaces(str); 1985 str = skip_spaces(str);
1933 1986