aboutsummaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c284
1 files changed, 174 insertions, 110 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index c399bc1093cb..a013bbc23717 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -24,6 +24,7 @@
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/kallsyms.h> 25#include <linux/kallsyms.h>
26#include <linux/uaccess.h> 26#include <linux/uaccess.h>
27#include <linux/ioport.h>
27 28
28#include <asm/page.h> /* for PAGE_SIZE */ 29#include <asm/page.h> /* for PAGE_SIZE */
29#include <asm/div64.h> 30#include <asm/div64.h>
@@ -32,40 +33,48 @@
32/* Works only for digits and letters, but small and fast */ 33/* Works only for digits and letters, but small and fast */
33#define TOLOWER(x) ((x) | 0x20) 34#define TOLOWER(x) ((x) | 0x20)
34 35
36static unsigned int simple_guess_base(const char *cp)
37{
38 if (cp[0] == '0') {
39 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
40 return 16;
41 else
42 return 8;
43 } else {
44 return 10;
45 }
46}
47
35/** 48/**
36 * simple_strtoul - convert a string to an unsigned long 49 * simple_strtoul - convert a string to an unsigned long
37 * @cp: The start of the string 50 * @cp: The start of the string
38 * @endp: A pointer to the end of the parsed string will be placed here 51 * @endp: A pointer to the end of the parsed string will be placed here
39 * @base: The number base to use 52 * @base: The number base to use
40 */ 53 */
41unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 54unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
42{ 55{
43 unsigned long result = 0,value; 56 unsigned long result = 0;
44 57
45 if (!base) { 58 if (!base)
46 base = 10; 59 base = simple_guess_base(cp);
47 if (*cp == '0') { 60
48 base = 8; 61 if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
49 cp++; 62 cp += 2;
50 if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) { 63
51 cp++; 64 while (isxdigit(*cp)) {
52 base = 16; 65 unsigned int value;
53 } 66
54 } 67 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
55 } else if (base == 16) { 68 if (value >= base)
56 if (cp[0] == '0' && TOLOWER(cp[1]) == 'x') 69 break;
57 cp += 2; 70 result = result * base + value;
58 }
59 while (isxdigit(*cp) &&
60 (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
61 result = result*base + value;
62 cp++; 71 cp++;
63 } 72 }
73
64 if (endp) 74 if (endp)
65 *endp = (char *)cp; 75 *endp = (char *)cp;
66 return result; 76 return result;
67} 77}
68
69EXPORT_SYMBOL(simple_strtoul); 78EXPORT_SYMBOL(simple_strtoul);
70 79
71/** 80/**
@@ -74,13 +83,12 @@ EXPORT_SYMBOL(simple_strtoul);
74 * @endp: A pointer to the end of the parsed string will be placed here 83 * @endp: A pointer to the end of the parsed string will be placed here
75 * @base: The number base to use 84 * @base: The number base to use
76 */ 85 */
77long simple_strtol(const char *cp,char **endp,unsigned int base) 86long simple_strtol(const char *cp, char **endp, unsigned int base)
78{ 87{
79 if(*cp=='-') 88 if(*cp == '-')
80 return -simple_strtoul(cp+1,endp,base); 89 return -simple_strtoul(cp + 1, endp, base);
81 return simple_strtoul(cp,endp,base); 90 return simple_strtoul(cp, endp, base);
82} 91}
83
84EXPORT_SYMBOL(simple_strtol); 92EXPORT_SYMBOL(simple_strtol);
85 93
86/** 94/**
@@ -89,34 +97,30 @@ EXPORT_SYMBOL(simple_strtol);
89 * @endp: A pointer to the end of the parsed string will be placed here 97 * @endp: A pointer to the end of the parsed string will be placed here
90 * @base: The number base to use 98 * @base: The number base to use
91 */ 99 */
92unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) 100unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
93{ 101{
94 unsigned long long result = 0,value; 102 unsigned long long result = 0;
95 103
96 if (!base) { 104 if (!base)
97 base = 10; 105 base = simple_guess_base(cp);
98 if (*cp == '0') { 106
99 base = 8; 107 if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
100 cp++; 108 cp += 2;
101 if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) { 109
102 cp++; 110 while (isxdigit(*cp)) {
103 base = 16; 111 unsigned int value;
104 } 112
105 } 113 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
106 } else if (base == 16) { 114 if (value >= base)
107 if (cp[0] == '0' && TOLOWER(cp[1]) == 'x') 115 break;
108 cp += 2; 116 result = result * base + value;
109 }
110 while (isxdigit(*cp)
111 && (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
112 result = result*base + value;
113 cp++; 117 cp++;
114 } 118 }
119
115 if (endp) 120 if (endp)
116 *endp = (char *)cp; 121 *endp = (char *)cp;
117 return result; 122 return result;
118} 123}
119
120EXPORT_SYMBOL(simple_strtoull); 124EXPORT_SYMBOL(simple_strtoull);
121 125
122/** 126/**
@@ -125,14 +129,13 @@ EXPORT_SYMBOL(simple_strtoull);
125 * @endp: A pointer to the end of the parsed string will be placed here 129 * @endp: A pointer to the end of the parsed string will be placed here
126 * @base: The number base to use 130 * @base: The number base to use
127 */ 131 */
128long long simple_strtoll(const char *cp,char **endp,unsigned int base) 132long long simple_strtoll(const char *cp, char **endp, unsigned int base)
129{ 133{
130 if(*cp=='-') 134 if(*cp=='-')
131 return -simple_strtoull(cp+1,endp,base); 135 return -simple_strtoull(cp + 1, endp, base);
132 return simple_strtoull(cp,endp,base); 136 return simple_strtoull(cp, endp, base);
133} 137}
134 138
135
136/** 139/**
137 * strict_strtoul - convert a string to an unsigned long strictly 140 * strict_strtoul - convert a string to an unsigned long strictly
138 * @cp: The string to be converted 141 * @cp: The string to be converted
@@ -155,7 +158,27 @@ long long simple_strtoll(const char *cp,char **endp,unsigned int base)
155 * simple_strtoul just ignores the successive invalid characters and 158 * simple_strtoul just ignores the successive invalid characters and
156 * return the converted value of prefix part of the string. 159 * return the converted value of prefix part of the string.
157 */ 160 */
158int strict_strtoul(const char *cp, unsigned int base, unsigned long *res); 161int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
162{
163 char *tail;
164 unsigned long val;
165 size_t len;
166
167 *res = 0;
168 len = strlen(cp);
169 if (len == 0)
170 return -EINVAL;
171
172 val = simple_strtoul(cp, &tail, base);
173 if ((*tail == '\0') ||
174 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
175 *res = val;
176 return 0;
177 }
178
179 return -EINVAL;
180}
181EXPORT_SYMBOL(strict_strtoul);
159 182
160/** 183/**
161 * strict_strtol - convert a string to a long strictly 184 * strict_strtol - convert a string to a long strictly
@@ -169,7 +192,20 @@ int strict_strtoul(const char *cp, unsigned int base, unsigned long *res);
169 * It returns 0 if conversion is successful and *res is set to the converted 192 * It returns 0 if conversion is successful and *res is set to the converted
170 * value, otherwise it returns -EINVAL and *res is set to 0. 193 * value, otherwise it returns -EINVAL and *res is set to 0.
171 */ 194 */
172int strict_strtol(const char *cp, unsigned int base, long *res); 195int strict_strtol(const char *cp, unsigned int base, long *res)
196{
197 int ret;
198 if (*cp == '-') {
199 ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
200 if (!ret)
201 *res = -(*res);
202 } else {
203 ret = strict_strtoul(cp, base, (unsigned long *)res);
204 }
205
206 return ret;
207}
208EXPORT_SYMBOL(strict_strtol);
173 209
174/** 210/**
175 * strict_strtoull - convert a string to an unsigned long long strictly 211 * strict_strtoull - convert a string to an unsigned long long strictly
@@ -193,7 +229,27 @@ int strict_strtol(const char *cp, unsigned int base, long *res);
193 * simple_strtoull just ignores the successive invalid characters and 229 * simple_strtoull just ignores the successive invalid characters and
194 * return the converted value of prefix part of the string. 230 * return the converted value of prefix part of the string.
195 */ 231 */
196int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res); 232int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
233{
234 char *tail;
235 unsigned long long val;
236 size_t len;
237
238 *res = 0;
239 len = strlen(cp);
240 if (len == 0)
241 return -EINVAL;
242
243 val = simple_strtoull(cp, &tail, base);
244 if ((*tail == '\0') ||
245 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
246 *res = val;
247 return 0;
248 }
249
250 return -EINVAL;
251}
252EXPORT_SYMBOL(strict_strtoull);
197 253
198/** 254/**
199 * strict_strtoll - convert a string to a long long strictly 255 * strict_strtoll - convert a string to a long long strictly
@@ -207,53 +263,20 @@ int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res);
207 * It returns 0 if conversion is successful and *res is set to the converted 263 * It returns 0 if conversion is successful and *res is set to the converted
208 * value, otherwise it returns -EINVAL and *res is set to 0. 264 * value, otherwise it returns -EINVAL and *res is set to 0.
209 */ 265 */
210int strict_strtoll(const char *cp, unsigned int base, long long *res); 266int strict_strtoll(const char *cp, unsigned int base, long long *res)
211 267{
212#define define_strict_strtoux(type, valtype) \ 268 int ret;
213int strict_strtou##type(const char *cp, unsigned int base, valtype *res)\ 269 if (*cp == '-') {
214{ \ 270 ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
215 char *tail; \ 271 if (!ret)
216 valtype val; \ 272 *res = -(*res);
217 size_t len; \ 273 } else {
218 \ 274 ret = strict_strtoull(cp, base, (unsigned long long *)res);
219 *res = 0; \ 275 }
220 len = strlen(cp); \
221 if (len == 0) \
222 return -EINVAL; \
223 \
224 val = simple_strtou##type(cp, &tail, base); \
225 if ((*tail == '\0') || \
226 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {\
227 *res = val; \
228 return 0; \
229 } \
230 \
231 return -EINVAL; \
232} \
233
234#define define_strict_strtox(type, valtype) \
235int strict_strto##type(const char *cp, unsigned int base, valtype *res) \
236{ \
237 int ret; \
238 if (*cp == '-') { \
239 ret = strict_strtou##type(cp+1, base, res); \
240 if (!ret) \
241 *res = -(*res); \
242 } else \
243 ret = strict_strtou##type(cp, base, res); \
244 \
245 return ret; \
246} \
247
248define_strict_strtoux(l, unsigned long)
249define_strict_strtox(l, long)
250define_strict_strtoux(ll, unsigned long long)
251define_strict_strtox(ll, long long)
252 276
253EXPORT_SYMBOL(strict_strtoul); 277 return ret;
254EXPORT_SYMBOL(strict_strtol); 278}
255EXPORT_SYMBOL(strict_strtoll); 279EXPORT_SYMBOL(strict_strtoll);
256EXPORT_SYMBOL(strict_strtoull);
257 280
258static int skip_atoi(const char **s) 281static int skip_atoi(const char **s)
259{ 282{
@@ -528,18 +551,51 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
528#endif 551#endif
529} 552}
530 553
554static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags)
555{
556#ifndef IO_RSRC_PRINTK_SIZE
557#define IO_RSRC_PRINTK_SIZE 4
558#endif
559
560#ifndef MEM_RSRC_PRINTK_SIZE
561#define MEM_RSRC_PRINTK_SIZE 8
562#endif
563
564 /* room for the actual numbers, the two "0x", -, [, ] and the final zero */
565 char sym[4*sizeof(resource_size_t) + 8];
566 char *p = sym, *pend = sym + sizeof(sym);
567 int size = -1;
568
569 if (res->flags & IORESOURCE_IO)
570 size = IO_RSRC_PRINTK_SIZE;
571 else if (res->flags & IORESOURCE_MEM)
572 size = MEM_RSRC_PRINTK_SIZE;
573
574 *p++ = '[';
575 p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
576 *p++ = '-';
577 p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
578 *p++ = ']';
579 *p = 0;
580
581 return string(buf, end, sym, field_width, precision, flags);
582}
583
531/* 584/*
532 * Show a '%p' thing. A kernel extension is that the '%p' is followed 585 * Show a '%p' thing. A kernel extension is that the '%p' is followed
533 * by an extra set of alphanumeric characters that are extended format 586 * by an extra set of alphanumeric characters that are extended format
534 * specifiers. 587 * specifiers.
535 * 588 *
536 * Right now we just handle 'F' (for symbolic Function descriptor pointers) 589 * Right now we handle:
537 * and 'S' (for Symbolic direct pointers), but this can easily be 590 *
538 * extended in the future (network address types etc). 591 * - 'F' For symbolic function descriptor pointers
592 * - 'S' For symbolic direct pointers
593 * - 'R' For a struct resource pointer, it prints the range of
594 * addresses (not the name nor the flags)
539 * 595 *
540 * The difference between 'S' and 'F' is that on ia64 and ppc64 function 596 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
541 * pointers are really function descriptors, which contain a pointer the 597 * function pointers are really function descriptors, which contain a
542 * real address. 598 * pointer to the real address.
543 */ 599 */
544static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) 600static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
545{ 601{
@@ -549,6 +605,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
549 /* Fallthrough */ 605 /* Fallthrough */
550 case 'S': 606 case 'S':
551 return symbol_string(buf, end, ptr, field_width, precision, flags); 607 return symbol_string(buf, end, ptr, field_width, precision, flags);
608 case 'R':
609 return resource_string(buf, end, ptr, field_width, precision, flags);
552 } 610 }
553 flags |= SMALL; 611 flags |= SMALL;
554 if (field_width == -1) { 612 if (field_width == -1) {
@@ -565,6 +623,11 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
565 * @fmt: The format string to use 623 * @fmt: The format string to use
566 * @args: Arguments for the format string 624 * @args: Arguments for the format string
567 * 625 *
626 * This function follows C99 vsnprintf, but has some extensions:
627 * %pS output the name of a text symbol
628 * %pF output the name of a function pointer
629 * %pR output the address range in a struct resource
630 *
568 * The return value is the number of characters which would 631 * The return value is the number of characters which would
569 * be generated for the given input, excluding the trailing 632 * be generated for the given input, excluding the trailing
570 * '\0', as per ISO C99. If you want to have the exact 633 * '\0', as per ISO C99. If you want to have the exact
@@ -790,7 +853,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
790 /* the trailing null byte doesn't count towards the total */ 853 /* the trailing null byte doesn't count towards the total */
791 return str-buf; 854 return str-buf;
792} 855}
793
794EXPORT_SYMBOL(vsnprintf); 856EXPORT_SYMBOL(vsnprintf);
795 857
796/** 858/**
@@ -806,6 +868,8 @@ EXPORT_SYMBOL(vsnprintf);
806 * 868 *
807 * Call this function if you are already dealing with a va_list. 869 * Call this function if you are already dealing with a va_list.
808 * You probably want scnprintf() instead. 870 * You probably want scnprintf() instead.
871 *
872 * See the vsnprintf() documentation for format string extensions over C99.
809 */ 873 */
810int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) 874int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
811{ 875{
@@ -814,7 +878,6 @@ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
814 i=vsnprintf(buf,size,fmt,args); 878 i=vsnprintf(buf,size,fmt,args);
815 return (i >= size) ? (size - 1) : i; 879 return (i >= size) ? (size - 1) : i;
816} 880}
817
818EXPORT_SYMBOL(vscnprintf); 881EXPORT_SYMBOL(vscnprintf);
819 882
820/** 883/**
@@ -828,6 +891,8 @@ EXPORT_SYMBOL(vscnprintf);
828 * generated for the given input, excluding the trailing null, 891 * generated for the given input, excluding the trailing null,
829 * as per ISO C99. If the return is greater than or equal to 892 * as per ISO C99. If the return is greater than or equal to
830 * @size, the resulting string is truncated. 893 * @size, the resulting string is truncated.
894 *
895 * See the vsnprintf() documentation for format string extensions over C99.
831 */ 896 */
832int snprintf(char * buf, size_t size, const char *fmt, ...) 897int snprintf(char * buf, size_t size, const char *fmt, ...)
833{ 898{
@@ -839,7 +904,6 @@ int snprintf(char * buf, size_t size, const char *fmt, ...)
839 va_end(args); 904 va_end(args);
840 return i; 905 return i;
841} 906}
842
843EXPORT_SYMBOL(snprintf); 907EXPORT_SYMBOL(snprintf);
844 908
845/** 909/**
@@ -877,12 +941,13 @@ EXPORT_SYMBOL(scnprintf);
877 * 941 *
878 * Call this function if you are already dealing with a va_list. 942 * Call this function if you are already dealing with a va_list.
879 * You probably want sprintf() instead. 943 * You probably want sprintf() instead.
944 *
945 * See the vsnprintf() documentation for format string extensions over C99.
880 */ 946 */
881int vsprintf(char *buf, const char *fmt, va_list args) 947int vsprintf(char *buf, const char *fmt, va_list args)
882{ 948{
883 return vsnprintf(buf, INT_MAX, fmt, args); 949 return vsnprintf(buf, INT_MAX, fmt, args);
884} 950}
885
886EXPORT_SYMBOL(vsprintf); 951EXPORT_SYMBOL(vsprintf);
887 952
888/** 953/**
@@ -894,6 +959,8 @@ EXPORT_SYMBOL(vsprintf);
894 * The function returns the number of characters written 959 * The function returns the number of characters written
895 * into @buf. Use snprintf() or scnprintf() in order to avoid 960 * into @buf. Use snprintf() or scnprintf() in order to avoid
896 * buffer overflows. 961 * buffer overflows.
962 *
963 * See the vsnprintf() documentation for format string extensions over C99.
897 */ 964 */
898int sprintf(char * buf, const char *fmt, ...) 965int sprintf(char * buf, const char *fmt, ...)
899{ 966{
@@ -905,7 +972,6 @@ int sprintf(char * buf, const char *fmt, ...)
905 va_end(args); 972 va_end(args);
906 return i; 973 return i;
907} 974}
908
909EXPORT_SYMBOL(sprintf); 975EXPORT_SYMBOL(sprintf);
910 976
911/** 977/**
@@ -1134,7 +1200,6 @@ int vsscanf(const char * buf, const char * fmt, va_list args)
1134 1200
1135 return num; 1201 return num;
1136} 1202}
1137
1138EXPORT_SYMBOL(vsscanf); 1203EXPORT_SYMBOL(vsscanf);
1139 1204
1140/** 1205/**
@@ -1153,5 +1218,4 @@ int sscanf(const char * buf, const char * fmt, ...)
1153 va_end(args); 1218 va_end(args);
1154 return i; 1219 return i;
1155} 1220}
1156
1157EXPORT_SYMBOL(sscanf); 1221EXPORT_SYMBOL(sscanf);