diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /lib/vsprintf.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 616 |
1 files changed, 198 insertions, 418 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index fab33a9c531..d7222a9c826 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -17,40 +17,57 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <stdarg.h> | 19 | #include <stdarg.h> |
20 | #include <linux/module.h> /* for KSYM_SYMBOL_LEN */ | 20 | #include <linux/module.h> |
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
23 | #include <linux/ctype.h> | 23 | #include <linux/ctype.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/kallsyms.h> | 25 | #include <linux/kallsyms.h> |
26 | #include <linux/math64.h> | ||
27 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
28 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
29 | #include <net/addrconf.h> | 28 | #include <net/addrconf.h> |
30 | 29 | ||
31 | #include <asm/page.h> /* for PAGE_SIZE */ | 30 | #include <asm/page.h> /* for PAGE_SIZE */ |
31 | #include <asm/div64.h> | ||
32 | #include <asm/sections.h> /* for dereference_function_descriptor() */ | 32 | #include <asm/sections.h> /* for dereference_function_descriptor() */ |
33 | 33 | ||
34 | #include "kstrtox.h" | 34 | static unsigned int simple_guess_base(const char *cp) |
35 | { | ||
36 | if (cp[0] == '0') { | ||
37 | if (_tolower(cp[1]) == 'x' && isxdigit(cp[2])) | ||
38 | return 16; | ||
39 | else | ||
40 | return 8; | ||
41 | } else { | ||
42 | return 10; | ||
43 | } | ||
44 | } | ||
35 | 45 | ||
36 | /** | 46 | /** |
37 | * simple_strtoull - convert a string to an unsigned long long | 47 | * simple_strtoull - convert a string to an unsigned long long |
38 | * @cp: The start of the string | 48 | * @cp: The start of the string |
39 | * @endp: A pointer to the end of the parsed string will be placed here | 49 | * @endp: A pointer to the end of the parsed string will be placed here |
40 | * @base: The number base to use | 50 | * @base: The number base to use |
41 | * | ||
42 | * This function is obsolete. Please use kstrtoull instead. | ||
43 | */ | 51 | */ |
44 | unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) | 52 | unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) |
45 | { | 53 | { |
46 | unsigned long long result; | 54 | unsigned long long result = 0; |
47 | unsigned int rv; | ||
48 | 55 | ||
49 | cp = _parse_integer_fixup_radix(cp, &base); | 56 | if (!base) |
50 | rv = _parse_integer(cp, base, &result); | 57 | base = simple_guess_base(cp); |
51 | /* FIXME */ | ||
52 | cp += (rv & ~KSTRTOX_OVERFLOW); | ||
53 | 58 | ||
59 | if (base == 16 && cp[0] == '0' && _tolower(cp[1]) == 'x') | ||
60 | cp += 2; | ||
61 | |||
62 | while (isxdigit(*cp)) { | ||
63 | unsigned int value; | ||
64 | |||
65 | value = isdigit(*cp) ? *cp - '0' : _tolower(*cp) - 'a' + 10; | ||
66 | if (value >= base) | ||
67 | break; | ||
68 | result = result * base + value; | ||
69 | cp++; | ||
70 | } | ||
54 | if (endp) | 71 | if (endp) |
55 | *endp = (char *)cp; | 72 | *endp = (char *)cp; |
56 | 73 | ||
@@ -63,8 +80,6 @@ EXPORT_SYMBOL(simple_strtoull); | |||
63 | * @cp: The start of the string | 80 | * @cp: The start of the string |
64 | * @endp: A pointer to the end of the parsed string will be placed here | 81 | * @endp: A pointer to the end of the parsed string will be placed here |
65 | * @base: The number base to use | 82 | * @base: The number base to use |
66 | * | ||
67 | * This function is obsolete. Please use kstrtoul instead. | ||
68 | */ | 83 | */ |
69 | unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) | 84 | unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) |
70 | { | 85 | { |
@@ -77,8 +92,6 @@ EXPORT_SYMBOL(simple_strtoul); | |||
77 | * @cp: The start of the string | 92 | * @cp: The start of the string |
78 | * @endp: A pointer to the end of the parsed string will be placed here | 93 | * @endp: A pointer to the end of the parsed string will be placed here |
79 | * @base: The number base to use | 94 | * @base: The number base to use |
80 | * | ||
81 | * This function is obsolete. Please use kstrtol instead. | ||
82 | */ | 95 | */ |
83 | long simple_strtol(const char *cp, char **endp, unsigned int base) | 96 | long simple_strtol(const char *cp, char **endp, unsigned int base) |
84 | { | 97 | { |
@@ -94,8 +107,6 @@ EXPORT_SYMBOL(simple_strtol); | |||
94 | * @cp: The start of the string | 107 | * @cp: The start of the string |
95 | * @endp: A pointer to the end of the parsed string will be placed here | 108 | * @endp: A pointer to the end of the parsed string will be placed here |
96 | * @base: The number base to use | 109 | * @base: The number base to use |
97 | * | ||
98 | * This function is obsolete. Please use kstrtoll instead. | ||
99 | */ | 110 | */ |
100 | long long simple_strtoll(const char *cp, char **endp, unsigned int base) | 111 | long long simple_strtoll(const char *cp, char **endp, unsigned int base) |
101 | { | 112 | { |
@@ -120,220 +131,104 @@ int skip_atoi(const char **s) | |||
120 | /* Decimal conversion is by far the most typical, and is used | 131 | /* Decimal conversion is by far the most typical, and is used |
121 | * for /proc and /sys data. This directly impacts e.g. top performance | 132 | * for /proc and /sys data. This directly impacts e.g. top performance |
122 | * with many processes running. We optimize it for speed | 133 | * with many processes running. We optimize it for speed |
123 | * using ideas described at <http://www.cs.uiowa.edu/~jones/bcd/divide.html> | 134 | * using code from |
124 | * (with permission from the author, Douglas W. Jones). | 135 | * http://www.cs.uiowa.edu/~jones/bcd/decimal.html |
125 | */ | 136 | * (with permission from the author, Douglas W. Jones). */ |
126 | |||
127 | #if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64 | ||
128 | /* Formats correctly any integer in [0, 999999999] */ | ||
129 | static noinline_for_stack | ||
130 | char *put_dec_full9(char *buf, unsigned q) | ||
131 | { | ||
132 | unsigned r; | ||
133 | |||
134 | /* | ||
135 | * Possible ways to approx. divide by 10 | ||
136 | * (x * 0x1999999a) >> 32 x < 1073741829 (multiply must be 64-bit) | ||
137 | * (x * 0xcccd) >> 19 x < 81920 (x < 262149 when 64-bit mul) | ||
138 | * (x * 0x6667) >> 18 x < 43699 | ||
139 | * (x * 0x3334) >> 17 x < 16389 | ||
140 | * (x * 0x199a) >> 16 x < 16389 | ||
141 | * (x * 0x0ccd) >> 15 x < 16389 | ||
142 | * (x * 0x0667) >> 14 x < 2739 | ||
143 | * (x * 0x0334) >> 13 x < 1029 | ||
144 | * (x * 0x019a) >> 12 x < 1029 | ||
145 | * (x * 0x00cd) >> 11 x < 1029 shorter code than * 0x67 (on i386) | ||
146 | * (x * 0x0067) >> 10 x < 179 | ||
147 | * (x * 0x0034) >> 9 x < 69 same | ||
148 | * (x * 0x001a) >> 8 x < 69 same | ||
149 | * (x * 0x000d) >> 7 x < 69 same, shortest code (on i386) | ||
150 | * (x * 0x0007) >> 6 x < 19 | ||
151 | * See <http://www.cs.uiowa.edu/~jones/bcd/divide.html> | ||
152 | */ | ||
153 | r = (q * (uint64_t)0x1999999a) >> 32; | ||
154 | *buf++ = (q - 10 * r) + '0'; /* 1 */ | ||
155 | q = (r * (uint64_t)0x1999999a) >> 32; | ||
156 | *buf++ = (r - 10 * q) + '0'; /* 2 */ | ||
157 | r = (q * (uint64_t)0x1999999a) >> 32; | ||
158 | *buf++ = (q - 10 * r) + '0'; /* 3 */ | ||
159 | q = (r * (uint64_t)0x1999999a) >> 32; | ||
160 | *buf++ = (r - 10 * q) + '0'; /* 4 */ | ||
161 | r = (q * (uint64_t)0x1999999a) >> 32; | ||
162 | *buf++ = (q - 10 * r) + '0'; /* 5 */ | ||
163 | /* Now value is under 10000, can avoid 64-bit multiply */ | ||
164 | q = (r * 0x199a) >> 16; | ||
165 | *buf++ = (r - 10 * q) + '0'; /* 6 */ | ||
166 | r = (q * 0xcd) >> 11; | ||
167 | *buf++ = (q - 10 * r) + '0'; /* 7 */ | ||
168 | q = (r * 0xcd) >> 11; | ||
169 | *buf++ = (r - 10 * q) + '0'; /* 8 */ | ||
170 | *buf++ = q + '0'; /* 9 */ | ||
171 | return buf; | ||
172 | } | ||
173 | #endif | ||
174 | 137 | ||
175 | /* Similar to above but do not pad with zeros. | 138 | /* Formats correctly any integer in [0,99999]. |
176 | * Code can be easily arranged to print 9 digits too, but our callers | 139 | * Outputs from one to five digits depending on input. |
177 | * always call put_dec_full9() instead when the number has 9 decimal digits. | 140 | * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ |
178 | */ | ||
179 | static noinline_for_stack | 141 | static noinline_for_stack |
180 | char *put_dec_trunc8(char *buf, unsigned r) | 142 | char *put_dec_trunc(char *buf, unsigned q) |
181 | { | 143 | { |
182 | unsigned q; | 144 | unsigned d3, d2, d1, d0; |
183 | 145 | d1 = (q>>4) & 0xf; | |
184 | /* Copy of previous function's body with added early returns */ | 146 | d2 = (q>>8) & 0xf; |
185 | while (r >= 10000) { | 147 | d3 = (q>>12); |
186 | q = r + '0'; | 148 | |
187 | r = (r * (uint64_t)0x1999999a) >> 32; | 149 | d0 = 6*(d3 + d2 + d1) + (q & 0xf); |
188 | *buf++ = q - 10*r; | 150 | q = (d0 * 0xcd) >> 11; |
151 | d0 = d0 - 10*q; | ||
152 | *buf++ = d0 + '0'; /* least significant digit */ | ||
153 | d1 = q + 9*d3 + 5*d2 + d1; | ||
154 | if (d1 != 0) { | ||
155 | q = (d1 * 0xcd) >> 11; | ||
156 | d1 = d1 - 10*q; | ||
157 | *buf++ = d1 + '0'; /* next digit */ | ||
158 | |||
159 | d2 = q + 2*d2; | ||
160 | if ((d2 != 0) || (d3 != 0)) { | ||
161 | q = (d2 * 0xd) >> 7; | ||
162 | d2 = d2 - 10*q; | ||
163 | *buf++ = d2 + '0'; /* next digit */ | ||
164 | |||
165 | d3 = q + 4*d3; | ||
166 | if (d3 != 0) { | ||
167 | q = (d3 * 0xcd) >> 11; | ||
168 | d3 = d3 - 10*q; | ||
169 | *buf++ = d3 + '0'; /* next digit */ | ||
170 | if (q != 0) | ||
171 | *buf++ = q + '0'; /* most sign. digit */ | ||
172 | } | ||
173 | } | ||
189 | } | 174 | } |
190 | 175 | ||
191 | q = (r * 0x199a) >> 16; /* r <= 9999 */ | ||
192 | *buf++ = (r - 10 * q) + '0'; | ||
193 | if (q == 0) | ||
194 | return buf; | ||
195 | r = (q * 0xcd) >> 11; /* q <= 999 */ | ||
196 | *buf++ = (q - 10 * r) + '0'; | ||
197 | if (r == 0) | ||
198 | return buf; | ||
199 | q = (r * 0xcd) >> 11; /* r <= 99 */ | ||
200 | *buf++ = (r - 10 * q) + '0'; | ||
201 | if (q == 0) | ||
202 | return buf; | ||
203 | *buf++ = q + '0'; /* q <= 9 */ | ||
204 | return buf; | 176 | return buf; |
205 | } | 177 | } |
206 | 178 | /* Same with if's removed. Always emits five digits */ | |
207 | /* There are two algorithms to print larger numbers. | ||
208 | * One is generic: divide by 1000000000 and repeatedly print | ||
209 | * groups of (up to) 9 digits. It's conceptually simple, | ||
210 | * but requires a (unsigned long long) / 1000000000 division. | ||
211 | * | ||
212 | * Second algorithm splits 64-bit unsigned long long into 16-bit chunks, | ||
213 | * manipulates them cleverly and generates groups of 4 decimal digits. | ||
214 | * It so happens that it does NOT require long long division. | ||
215 | * | ||
216 | * If long is > 32 bits, division of 64-bit values is relatively easy, | ||
217 | * and we will use the first algorithm. | ||
218 | * If long long is > 64 bits (strange architecture with VERY large long long), | ||
219 | * second algorithm can't be used, and we again use the first one. | ||
220 | * | ||
221 | * Else (if long is 32 bits and long long is 64 bits) we use second one. | ||
222 | */ | ||
223 | |||
224 | #if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64 | ||
225 | |||
226 | /* First algorithm: generic */ | ||
227 | |||
228 | static | ||
229 | char *put_dec(char *buf, unsigned long long n) | ||
230 | { | ||
231 | if (n >= 100*1000*1000) { | ||
232 | while (n >= 1000*1000*1000) | ||
233 | buf = put_dec_full9(buf, do_div(n, 1000*1000*1000)); | ||
234 | if (n >= 100*1000*1000) | ||
235 | return put_dec_full9(buf, n); | ||
236 | } | ||
237 | return put_dec_trunc8(buf, n); | ||
238 | } | ||
239 | |||
240 | #else | ||
241 | |||
242 | /* Second algorithm: valid only for 64-bit long longs */ | ||
243 | |||
244 | /* See comment in put_dec_full9 for choice of constants */ | ||
245 | static noinline_for_stack | 179 | static noinline_for_stack |
246 | void put_dec_full4(char *buf, unsigned q) | 180 | char *put_dec_full(char *buf, unsigned q) |
247 | { | ||
248 | unsigned r; | ||
249 | r = (q * 0xccd) >> 15; | ||
250 | buf[0] = (q - 10 * r) + '0'; | ||
251 | q = (r * 0xcd) >> 11; | ||
252 | buf[1] = (r - 10 * q) + '0'; | ||
253 | r = (q * 0xcd) >> 11; | ||
254 | buf[2] = (q - 10 * r) + '0'; | ||
255 | buf[3] = r + '0'; | ||
256 | } | ||
257 | |||
258 | /* | ||
259 | * Call put_dec_full4 on x % 10000, return x / 10000. | ||
260 | * The approximation x/10000 == (x * 0x346DC5D7) >> 43 | ||
261 | * holds for all x < 1,128,869,999. The largest value this | ||
262 | * helper will ever be asked to convert is 1,125,520,955. | ||
263 | * (d1 in the put_dec code, assuming n is all-ones). | ||
264 | */ | ||
265 | static | ||
266 | unsigned put_dec_helper4(char *buf, unsigned x) | ||
267 | { | ||
268 | uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43; | ||
269 | |||
270 | put_dec_full4(buf, x - q * 10000); | ||
271 | return q; | ||
272 | } | ||
273 | |||
274 | /* Based on code by Douglas W. Jones found at | ||
275 | * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour> | ||
276 | * (with permission from the author). | ||
277 | * Performs no 64-bit division and hence should be fast on 32-bit machines. | ||
278 | */ | ||
279 | static | ||
280 | char *put_dec(char *buf, unsigned long long n) | ||
281 | { | 181 | { |
282 | uint32_t d3, d2, d1, q, h; | 182 | /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ |
183 | /* but anyway, gcc produces better code with full-sized ints */ | ||
184 | unsigned d3, d2, d1, d0; | ||
185 | d1 = (q>>4) & 0xf; | ||
186 | d2 = (q>>8) & 0xf; | ||
187 | d3 = (q>>12); | ||
283 | 188 | ||
284 | if (n < 100*1000*1000) | 189 | /* |
285 | return put_dec_trunc8(buf, n); | 190 | * Possible ways to approx. divide by 10 |
286 | 191 | * gcc -O2 replaces multiply with shifts and adds | |
287 | d1 = ((uint32_t)n >> 16); /* implicit "& 0xffff" */ | 192 | * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386) |
288 | h = (n >> 32); | 193 | * (x * 0x67) >> 10: 1100111 |
289 | d2 = (h ) & 0xffff; | 194 | * (x * 0x34) >> 9: 110100 - same |
290 | d3 = (h >> 16); /* implicit "& 0xffff" */ | 195 | * (x * 0x1a) >> 8: 11010 - same |
291 | 196 | * (x * 0x0d) >> 7: 1101 - same, shortest code (on i386) | |
292 | q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff); | 197 | */ |
293 | q = put_dec_helper4(buf, q); | 198 | d0 = 6*(d3 + d2 + d1) + (q & 0xf); |
294 | 199 | q = (d0 * 0xcd) >> 11; | |
295 | q += 7671 * d3 + 9496 * d2 + 6 * d1; | 200 | d0 = d0 - 10*q; |
296 | q = put_dec_helper4(buf+4, q); | 201 | *buf++ = d0 + '0'; |
297 | 202 | d1 = q + 9*d3 + 5*d2 + d1; | |
298 | q += 4749 * d3 + 42 * d2; | 203 | q = (d1 * 0xcd) >> 11; |
299 | q = put_dec_helper4(buf+8, q); | 204 | d1 = d1 - 10*q; |
300 | 205 | *buf++ = d1 + '0'; | |
301 | q += 281 * d3; | 206 | |
302 | buf += 12; | 207 | d2 = q + 2*d2; |
303 | if (q) | 208 | q = (d2 * 0xd) >> 7; |
304 | buf = put_dec_trunc8(buf, q); | 209 | d2 = d2 - 10*q; |
305 | else while (buf[-1] == '0') | 210 | *buf++ = d2 + '0'; |
306 | --buf; | 211 | |
212 | d3 = q + 4*d3; | ||
213 | q = (d3 * 0xcd) >> 11; /* - shorter code */ | ||
214 | /* q = (d3 * 0x67) >> 10; - would also work */ | ||
215 | d3 = d3 - 10*q; | ||
216 | *buf++ = d3 + '0'; | ||
217 | *buf++ = q + '0'; | ||
307 | 218 | ||
308 | return buf; | 219 | return buf; |
309 | } | 220 | } |
310 | 221 | /* No inlining helps gcc to use registers better */ | |
311 | #endif | 222 | static noinline_for_stack |
312 | 223 | char *put_dec(char *buf, unsigned long long num) | |
313 | /* | ||
314 | * Convert passed number to decimal string. | ||
315 | * Returns the length of string. On buffer overflow, returns 0. | ||
316 | * | ||
317 | * If speed is not important, use snprintf(). It's easy to read the code. | ||
318 | */ | ||
319 | int num_to_str(char *buf, int size, unsigned long long num) | ||
320 | { | 224 | { |
321 | char tmp[sizeof(num) * 3]; | 225 | while (1) { |
322 | int idx, len; | 226 | unsigned rem; |
323 | 227 | if (num < 100000) | |
324 | /* put_dec() may work incorrectly for num = 0 (generate "", not "0") */ | 228 | return put_dec_trunc(buf, num); |
325 | if (num <= 9) { | 229 | rem = do_div(num, 100000); |
326 | tmp[0] = '0' + num; | 230 | buf = put_dec_full(buf, rem); |
327 | len = 1; | ||
328 | } else { | ||
329 | len = put_dec(tmp, num) - tmp; | ||
330 | } | 231 | } |
331 | |||
332 | if (len > size) | ||
333 | return 0; | ||
334 | for (idx = 0; idx < len; ++idx) | ||
335 | buf[idx] = tmp[len - idx - 1]; | ||
336 | return len; | ||
337 | } | 232 | } |
338 | 233 | ||
339 | #define ZEROPAD 1 /* pad with zero */ | 234 | #define ZEROPAD 1 /* pad with zero */ |
@@ -388,7 +283,6 @@ char *number(char *buf, char *end, unsigned long long num, | |||
388 | char locase; | 283 | char locase; |
389 | int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); | 284 | int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); |
390 | int i; | 285 | int i; |
391 | bool is_zero = num == 0LL; | ||
392 | 286 | ||
393 | /* locase = 0 or 0x20. ORing digits or letters with 'locase' | 287 | /* locase = 0 or 0x20. ORing digits or letters with 'locase' |
394 | * produces same digits or (maybe lowercased) letters */ | 288 | * produces same digits or (maybe lowercased) letters */ |
@@ -410,16 +304,15 @@ char *number(char *buf, char *end, unsigned long long num, | |||
410 | } | 304 | } |
411 | } | 305 | } |
412 | if (need_pfx) { | 306 | if (need_pfx) { |
307 | spec.field_width--; | ||
413 | if (spec.base == 16) | 308 | if (spec.base == 16) |
414 | spec.field_width -= 2; | ||
415 | else if (!is_zero) | ||
416 | spec.field_width--; | 309 | spec.field_width--; |
417 | } | 310 | } |
418 | 311 | ||
419 | /* generate full string in tmp[], in reverse order */ | 312 | /* generate full string in tmp[], in reverse order */ |
420 | i = 0; | 313 | i = 0; |
421 | if (num < spec.base) | 314 | if (num == 0) |
422 | tmp[i++] = digits[num] | locase; | 315 | tmp[i++] = '0'; |
423 | /* Generic code, for any base: | 316 | /* Generic code, for any base: |
424 | else do { | 317 | else do { |
425 | tmp[i++] = (digits[do_div(num,base)] | locase); | 318 | tmp[i++] = (digits[do_div(num,base)] | locase); |
@@ -459,11 +352,9 @@ char *number(char *buf, char *end, unsigned long long num, | |||
459 | } | 352 | } |
460 | /* "0x" / "0" prefix */ | 353 | /* "0x" / "0" prefix */ |
461 | if (need_pfx) { | 354 | if (need_pfx) { |
462 | if (spec.base == 16 || !is_zero) { | 355 | if (buf < end) |
463 | if (buf < end) | 356 | *buf = '0'; |
464 | *buf = '0'; | 357 | ++buf; |
465 | ++buf; | ||
466 | } | ||
467 | if (spec.base == 16) { | 358 | if (spec.base == 16) { |
468 | if (buf < end) | 359 | if (buf < end) |
469 | *buf = ('X' | locase); | 360 | *buf = ('X' | locase); |
@@ -544,7 +435,7 @@ char *symbol_string(char *buf, char *end, void *ptr, | |||
544 | else if (ext != 'f' && ext != 's') | 435 | else if (ext != 'f' && ext != 's') |
545 | sprint_symbol(sym, value); | 436 | sprint_symbol(sym, value); |
546 | else | 437 | else |
547 | sprint_symbol_no_offset(sym, value); | 438 | kallsyms_lookup(value, NULL, NULL, NULL, sym); |
548 | 439 | ||
549 | return string(buf, end, sym, spec); | 440 | return string(buf, end, sym, spec); |
550 | #else | 441 | #else |
@@ -660,50 +551,6 @@ char *resource_string(char *buf, char *end, struct resource *res, | |||
660 | } | 551 | } |
661 | 552 | ||
662 | static noinline_for_stack | 553 | static noinline_for_stack |
663 | char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | ||
664 | const char *fmt) | ||
665 | { | ||
666 | int i, len = 1; /* if we pass '%ph[CDN]', field witdh remains | ||
667 | negative value, fallback to the default */ | ||
668 | char separator; | ||
669 | |||
670 | if (spec.field_width == 0) | ||
671 | /* nothing to print */ | ||
672 | return buf; | ||
673 | |||
674 | if (ZERO_OR_NULL_PTR(addr)) | ||
675 | /* NULL pointer */ | ||
676 | return string(buf, end, NULL, spec); | ||
677 | |||
678 | switch (fmt[1]) { | ||
679 | case 'C': | ||
680 | separator = ':'; | ||
681 | break; | ||
682 | case 'D': | ||
683 | separator = '-'; | ||
684 | break; | ||
685 | case 'N': | ||
686 | separator = 0; | ||
687 | break; | ||
688 | default: | ||
689 | separator = ' '; | ||
690 | break; | ||
691 | } | ||
692 | |||
693 | if (spec.field_width > 0) | ||
694 | len = min_t(int, spec.field_width, 64); | ||
695 | |||
696 | for (i = 0; i < len && buf < end - 1; i++) { | ||
697 | buf = hex_byte_pack(buf, addr[i]); | ||
698 | |||
699 | if (buf < end && separator && i != len - 1) | ||
700 | *buf++ = separator; | ||
701 | } | ||
702 | |||
703 | return buf; | ||
704 | } | ||
705 | |||
706 | static noinline_for_stack | ||
707 | char *mac_address_string(char *buf, char *end, u8 *addr, | 554 | char *mac_address_string(char *buf, char *end, u8 *addr, |
708 | struct printf_spec spec, const char *fmt) | 555 | struct printf_spec spec, const char *fmt) |
709 | { | 556 | { |
@@ -711,28 +558,15 @@ char *mac_address_string(char *buf, char *end, u8 *addr, | |||
711 | char *p = mac_addr; | 558 | char *p = mac_addr; |
712 | int i; | 559 | int i; |
713 | char separator; | 560 | char separator; |
714 | bool reversed = false; | ||
715 | 561 | ||
716 | switch (fmt[1]) { | 562 | if (fmt[1] == 'F') { /* FDDI canonical format */ |
717 | case 'F': | ||
718 | separator = '-'; | 563 | separator = '-'; |
719 | break; | 564 | } else { |
720 | |||
721 | case 'R': | ||
722 | reversed = true; | ||
723 | /* fall through */ | ||
724 | |||
725 | default: | ||
726 | separator = ':'; | 565 | separator = ':'; |
727 | break; | ||
728 | } | 566 | } |
729 | 567 | ||
730 | for (i = 0; i < 6; i++) { | 568 | for (i = 0; i < 6; i++) { |
731 | if (reversed) | 569 | p = pack_hex_byte(p, addr[i]); |
732 | p = hex_byte_pack(p, addr[5 - i]); | ||
733 | else | ||
734 | p = hex_byte_pack(p, addr[i]); | ||
735 | |||
736 | if (fmt[0] == 'M' && i != 5) | 570 | if (fmt[0] == 'M' && i != 5) |
737 | *p++ = separator; | 571 | *p++ = separator; |
738 | } | 572 | } |
@@ -772,7 +606,7 @@ char *ip4_string(char *p, const u8 *addr, const char *fmt) | |||
772 | } | 606 | } |
773 | for (i = 0; i < 4; i++) { | 607 | for (i = 0; i < 4; i++) { |
774 | char temp[3]; /* hold each IP quad in reverse order */ | 608 | char temp[3]; /* hold each IP quad in reverse order */ |
775 | int digits = put_dec_trunc8(temp, addr[index]) - temp; | 609 | int digits = put_dec_trunc(temp, addr[index]) - temp; |
776 | if (leading_zeros) { | 610 | if (leading_zeros) { |
777 | if (digits < 3) | 611 | if (digits < 3) |
778 | *p++ = '0'; | 612 | *p++ = '0'; |
@@ -852,13 +686,13 @@ char *ip6_compressed_string(char *p, const char *addr) | |||
852 | lo = word & 0xff; | 686 | lo = word & 0xff; |
853 | if (hi) { | 687 | if (hi) { |
854 | if (hi > 0x0f) | 688 | if (hi > 0x0f) |
855 | p = hex_byte_pack(p, hi); | 689 | p = pack_hex_byte(p, hi); |
856 | else | 690 | else |
857 | *p++ = hex_asc_lo(hi); | 691 | *p++ = hex_asc_lo(hi); |
858 | p = hex_byte_pack(p, lo); | 692 | p = pack_hex_byte(p, lo); |
859 | } | 693 | } |
860 | else if (lo > 0x0f) | 694 | else if (lo > 0x0f) |
861 | p = hex_byte_pack(p, lo); | 695 | p = pack_hex_byte(p, lo); |
862 | else | 696 | else |
863 | *p++ = hex_asc_lo(lo); | 697 | *p++ = hex_asc_lo(lo); |
864 | needcolon = true; | 698 | needcolon = true; |
@@ -880,8 +714,8 @@ char *ip6_string(char *p, const char *addr, const char *fmt) | |||
880 | int i; | 714 | int i; |
881 | 715 | ||
882 | for (i = 0; i < 8; i++) { | 716 | for (i = 0; i < 8; i++) { |
883 | p = hex_byte_pack(p, *addr++); | 717 | p = pack_hex_byte(p, *addr++); |
884 | p = hex_byte_pack(p, *addr++); | 718 | p = pack_hex_byte(p, *addr++); |
885 | if (fmt[0] == 'I' && i != 7) | 719 | if (fmt[0] == 'I' && i != 7) |
886 | *p++ = ':'; | 720 | *p++ = ':'; |
887 | } | 721 | } |
@@ -939,7 +773,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
939 | } | 773 | } |
940 | 774 | ||
941 | for (i = 0; i < 16; i++) { | 775 | for (i = 0; i < 16; i++) { |
942 | p = hex_byte_pack(p, addr[index[i]]); | 776 | p = pack_hex_byte(p, addr[index[i]]); |
943 | switch (i) { | 777 | switch (i) { |
944 | case 3: | 778 | case 3: |
945 | case 5: | 779 | case 5: |
@@ -962,18 +796,6 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
962 | return string(buf, end, uuid, spec); | 796 | return string(buf, end, uuid, spec); |
963 | } | 797 | } |
964 | 798 | ||
965 | static | ||
966 | char *netdev_feature_string(char *buf, char *end, const u8 *addr, | ||
967 | struct printf_spec spec) | ||
968 | { | ||
969 | spec.flags |= SPECIAL | SMALL | ZEROPAD; | ||
970 | if (spec.field_width == -1) | ||
971 | spec.field_width = 2 + 2 * sizeof(netdev_features_t); | ||
972 | spec.base = 16; | ||
973 | |||
974 | return number(buf, end, *(const netdev_features_t *)addr, spec); | ||
975 | } | ||
976 | |||
977 | int kptr_restrict __read_mostly; | 799 | int kptr_restrict __read_mostly; |
978 | 800 | ||
979 | /* | 801 | /* |
@@ -995,7 +817,6 @@ int kptr_restrict __read_mostly; | |||
995 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons | 817 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons |
996 | * - 'MF' For a 6-byte MAC FDDI address, it prints the address | 818 | * - 'MF' For a 6-byte MAC FDDI address, it prints the address |
997 | * with a dash-separated hex notation | 819 | * with a dash-separated hex notation |
998 | * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth) | ||
999 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way | 820 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way |
1000 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) | 821 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) |
1001 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's | 822 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's |
@@ -1022,14 +843,6 @@ int kptr_restrict __read_mostly; | |||
1022 | * Do not use this feature without some mechanism to verify the | 843 | * Do not use this feature without some mechanism to verify the |
1023 | * correctness of the format string and va_list arguments. | 844 | * correctness of the format string and va_list arguments. |
1024 | * - 'K' For a kernel pointer that should be hidden from unprivileged users | 845 | * - 'K' For a kernel pointer that should be hidden from unprivileged users |
1025 | * - 'NF' For a netdev_features_t | ||
1026 | * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with | ||
1027 | * a certain separator (' ' by default): | ||
1028 | * C colon | ||
1029 | * D dash | ||
1030 | * N no separator | ||
1031 | * The maximum supported length is 64 bytes of the input. Consider | ||
1032 | * to use print_hex_dump() for the larger input. | ||
1033 | * | 846 | * |
1034 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 847 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
1035 | * function pointers are really function descriptors, which contain a | 848 | * function pointers are really function descriptors, which contain a |
@@ -1039,15 +852,13 @@ static noinline_for_stack | |||
1039 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 852 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
1040 | struct printf_spec spec) | 853 | struct printf_spec spec) |
1041 | { | 854 | { |
1042 | int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0); | ||
1043 | |||
1044 | if (!ptr && *fmt != 'K') { | 855 | if (!ptr && *fmt != 'K') { |
1045 | /* | 856 | /* |
1046 | * Print (null) with the same width as a pointer so it makes | 857 | * Print (null) with the same width as a pointer so it makes |
1047 | * tabular output look nice. | 858 | * tabular output look nice. |
1048 | */ | 859 | */ |
1049 | if (spec.field_width == -1) | 860 | if (spec.field_width == -1) |
1050 | spec.field_width = default_width; | 861 | spec.field_width = 2 * sizeof(void *); |
1051 | return string(buf, end, "(null)", spec); | 862 | return string(buf, end, "(null)", spec); |
1052 | } | 863 | } |
1053 | 864 | ||
@@ -1063,12 +874,9 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1063 | case 'R': | 874 | case 'R': |
1064 | case 'r': | 875 | case 'r': |
1065 | return resource_string(buf, end, ptr, spec, fmt); | 876 | return resource_string(buf, end, ptr, spec, fmt); |
1066 | case 'h': | ||
1067 | return hex_string(buf, end, ptr, spec, fmt); | ||
1068 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 877 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
1069 | case 'm': /* Contiguous: 000102030405 */ | 878 | case 'm': /* Contiguous: 000102030405 */ |
1070 | /* [mM]F (FDDI) */ | 879 | /* [mM]F (FDDI, bit reversed) */ |
1071 | /* [mM]R (Reverse order; Bluetooth) */ | ||
1072 | return mac_address_string(buf, end, ptr, spec, fmt); | 880 | return mac_address_string(buf, end, ptr, spec, fmt); |
1073 | case 'I': /* Formatted IP supported | 881 | case 'I': /* Formatted IP supported |
1074 | * 4: 1.2.3.4 | 882 | * 4: 1.2.3.4 |
@@ -1089,24 +897,17 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1089 | case 'U': | 897 | case 'U': |
1090 | return uuid_string(buf, end, ptr, spec, fmt); | 898 | return uuid_string(buf, end, ptr, spec, fmt); |
1091 | case 'V': | 899 | case 'V': |
1092 | { | 900 | return buf + vsnprintf(buf, end > buf ? end - buf : 0, |
1093 | va_list va; | 901 | ((struct va_format *)ptr)->fmt, |
1094 | 902 | *(((struct va_format *)ptr)->va)); | |
1095 | va_copy(va, *((struct va_format *)ptr)->va); | ||
1096 | buf += vsnprintf(buf, end > buf ? end - buf : 0, | ||
1097 | ((struct va_format *)ptr)->fmt, va); | ||
1098 | va_end(va); | ||
1099 | return buf; | ||
1100 | } | ||
1101 | case 'K': | 903 | case 'K': |
1102 | /* | 904 | /* |
1103 | * %pK cannot be used in IRQ context because its test | 905 | * %pK cannot be used in IRQ context because its test |
1104 | * for CAP_SYSLOG would be meaningless. | 906 | * for CAP_SYSLOG would be meaningless. |
1105 | */ | 907 | */ |
1106 | if (kptr_restrict && (in_irq() || in_serving_softirq() || | 908 | if (in_irq() || in_serving_softirq() || in_nmi()) { |
1107 | in_nmi())) { | ||
1108 | if (spec.field_width == -1) | 909 | if (spec.field_width == -1) |
1109 | spec.field_width = default_width; | 910 | spec.field_width = 2 * sizeof(void *); |
1110 | return string(buf, end, "pK-error", spec); | 911 | return string(buf, end, "pK-error", spec); |
1111 | } | 912 | } |
1112 | if (!((kptr_restrict == 0) || | 913 | if (!((kptr_restrict == 0) || |
@@ -1114,16 +915,10 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1114 | has_capability_noaudit(current, CAP_SYSLOG)))) | 915 | has_capability_noaudit(current, CAP_SYSLOG)))) |
1115 | ptr = NULL; | 916 | ptr = NULL; |
1116 | break; | 917 | break; |
1117 | case 'N': | ||
1118 | switch (fmt[1]) { | ||
1119 | case 'F': | ||
1120 | return netdev_feature_string(buf, end, ptr, spec); | ||
1121 | } | ||
1122 | break; | ||
1123 | } | 918 | } |
1124 | spec.flags |= SMALL; | 919 | spec.flags |= SMALL; |
1125 | if (spec.field_width == -1) { | 920 | if (spec.field_width == -1) { |
1126 | spec.field_width = default_width; | 921 | spec.field_width = 2 * sizeof(void *); |
1127 | spec.flags |= ZEROPAD; | 922 | spec.flags |= ZEROPAD; |
1128 | } | 923 | } |
1129 | spec.base = 16; | 924 | spec.base = 16; |
@@ -1346,10 +1141,7 @@ qualifier: | |||
1346 | * %pR output the address range in a struct resource with decoded flags | 1141 | * %pR output the address range in a struct resource with decoded flags |
1347 | * %pr output the address range in a struct resource with raw flags | 1142 | * %pr output the address range in a struct resource with raw flags |
1348 | * %pM output a 6-byte MAC address with colons | 1143 | * %pM output a 6-byte MAC address with colons |
1349 | * %pMR output a 6-byte MAC address with colons in reversed order | ||
1350 | * %pMF output a 6-byte MAC address with dashes | ||
1351 | * %pm output a 6-byte MAC address without colons | 1144 | * %pm output a 6-byte MAC address without colons |
1352 | * %pmR output a 6-byte MAC address without colons in reversed order | ||
1353 | * %pI4 print an IPv4 address without leading zeros | 1145 | * %pI4 print an IPv4 address without leading zeros |
1354 | * %pi4 print an IPv4 address with leading zeros | 1146 | * %pi4 print an IPv4 address with leading zeros |
1355 | * %pI6 print an IPv6 address with colons | 1147 | * %pI6 print an IPv6 address with colons |
@@ -1357,12 +1149,8 @@ qualifier: | |||
1357 | * %pI6c print an IPv6 address as specified by RFC 5952 | 1149 | * %pI6c print an IPv6 address as specified by RFC 5952 |
1358 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | 1150 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper |
1359 | * case. | 1151 | * case. |
1360 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | ||
1361 | * bytes of the input) | ||
1362 | * %n is ignored | 1152 | * %n is ignored |
1363 | * | 1153 | * |
1364 | * ** Please update Documentation/printk-formats.txt when making changes ** | ||
1365 | * | ||
1366 | * The return value is the number of characters which would | 1154 | * The return value is the number of characters which would |
1367 | * be generated for the given input, excluding the trailing | 1155 | * be generated for the given input, excluding the trailing |
1368 | * '\0', as per ISO C99. If you want to have the exact | 1156 | * '\0', as per ISO C99. If you want to have the exact |
@@ -1493,10 +1281,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
1493 | num = va_arg(args, long); | 1281 | num = va_arg(args, long); |
1494 | break; | 1282 | break; |
1495 | case FORMAT_TYPE_SIZE_T: | 1283 | case FORMAT_TYPE_SIZE_T: |
1496 | if (spec.flags & SIGN) | 1284 | num = va_arg(args, size_t); |
1497 | num = va_arg(args, ssize_t); | ||
1498 | else | ||
1499 | num = va_arg(args, size_t); | ||
1500 | break; | 1285 | break; |
1501 | case FORMAT_TYPE_PTRDIFF: | 1286 | case FORMAT_TYPE_PTRDIFF: |
1502 | num = va_arg(args, ptrdiff_t); | 1287 | num = va_arg(args, ptrdiff_t); |
@@ -2024,15 +1809,11 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2024 | char digit; | 1809 | char digit; |
2025 | int num = 0; | 1810 | int num = 0; |
2026 | u8 qualifier; | 1811 | u8 qualifier; |
2027 | unsigned int base; | 1812 | u8 base; |
2028 | union { | ||
2029 | long long s; | ||
2030 | unsigned long long u; | ||
2031 | } val; | ||
2032 | s16 field_width; | 1813 | s16 field_width; |
2033 | bool is_sign; | 1814 | bool is_sign; |
2034 | 1815 | ||
2035 | while (*fmt) { | 1816 | while (*fmt && *str) { |
2036 | /* skip any white space in format */ | 1817 | /* skip any white space in format */ |
2037 | /* white space in format matchs any amount of | 1818 | /* white space in format matchs any amount of |
2038 | * white space, including none, in the input. | 1819 | * white space, including none, in the input. |
@@ -2057,8 +1838,6 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2057 | * advance both strings to next white space | 1838 | * advance both strings to next white space |
2058 | */ | 1839 | */ |
2059 | if (*fmt == '*') { | 1840 | if (*fmt == '*') { |
2060 | if (!*str) | ||
2061 | break; | ||
2062 | while (!isspace(*fmt) && *fmt != '%' && *fmt) | 1841 | while (!isspace(*fmt) && *fmt != '%' && *fmt) |
2063 | fmt++; | 1842 | fmt++; |
2064 | while (!isspace(*str) && *str) | 1843 | while (!isspace(*str) && *str) |
@@ -2068,11 +1847,8 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2068 | 1847 | ||
2069 | /* get field width */ | 1848 | /* get field width */ |
2070 | field_width = -1; | 1849 | field_width = -1; |
2071 | if (isdigit(*fmt)) { | 1850 | if (isdigit(*fmt)) |
2072 | field_width = skip_atoi(&fmt); | 1851 | field_width = skip_atoi(&fmt); |
2073 | if (field_width <= 0) | ||
2074 | break; | ||
2075 | } | ||
2076 | 1852 | ||
2077 | /* get conversion qualifier */ | 1853 | /* get conversion qualifier */ |
2078 | qualifier = -1; | 1854 | qualifier = -1; |
@@ -2090,17 +1866,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2090 | } | 1866 | } |
2091 | } | 1867 | } |
2092 | 1868 | ||
2093 | if (!*fmt) | 1869 | if (!*fmt || !*str) |
2094 | break; | ||
2095 | |||
2096 | if (*fmt == 'n') { | ||
2097 | /* return number of characters read so far */ | ||
2098 | *va_arg(args, int *) = str - buf; | ||
2099 | ++fmt; | ||
2100 | continue; | ||
2101 | } | ||
2102 | |||
2103 | if (!*str) | ||
2104 | break; | 1870 | break; |
2105 | 1871 | ||
2106 | base = 10; | 1872 | base = 10; |
@@ -2133,6 +1899,13 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2133 | num++; | 1899 | num++; |
2134 | } | 1900 | } |
2135 | continue; | 1901 | continue; |
1902 | case 'n': | ||
1903 | /* return number of characters read so far */ | ||
1904 | { | ||
1905 | int *i = (int *)va_arg(args, int*); | ||
1906 | *i = str - buf; | ||
1907 | } | ||
1908 | continue; | ||
2136 | case 'o': | 1909 | case 'o': |
2137 | base = 8; | 1910 | base = 8; |
2138 | break; | 1911 | break; |
@@ -2172,61 +1945,58 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2172 | || (base == 0 && !isdigit(digit))) | 1945 | || (base == 0 && !isdigit(digit))) |
2173 | break; | 1946 | break; |
2174 | 1947 | ||
2175 | if (is_sign) | ||
2176 | val.s = qualifier != 'L' ? | ||
2177 | simple_strtol(str, &next, base) : | ||
2178 | simple_strtoll(str, &next, base); | ||
2179 | else | ||
2180 | val.u = qualifier != 'L' ? | ||
2181 | simple_strtoul(str, &next, base) : | ||
2182 | simple_strtoull(str, &next, base); | ||
2183 | |||
2184 | if (field_width > 0 && next - str > field_width) { | ||
2185 | if (base == 0) | ||
2186 | _parse_integer_fixup_radix(str, &base); | ||
2187 | while (next - str > field_width) { | ||
2188 | if (is_sign) | ||
2189 | val.s = div_s64(val.s, base); | ||
2190 | else | ||
2191 | val.u = div_u64(val.u, base); | ||
2192 | --next; | ||
2193 | } | ||
2194 | } | ||
2195 | |||
2196 | switch (qualifier) { | 1948 | switch (qualifier) { |
2197 | case 'H': /* that's 'hh' in format */ | 1949 | case 'H': /* that's 'hh' in format */ |
2198 | if (is_sign) | 1950 | if (is_sign) { |
2199 | *va_arg(args, signed char *) = val.s; | 1951 | signed char *s = (signed char *)va_arg(args, signed char *); |
2200 | else | 1952 | *s = (signed char)simple_strtol(str, &next, base); |
2201 | *va_arg(args, unsigned char *) = val.u; | 1953 | } else { |
1954 | unsigned char *s = (unsigned char *)va_arg(args, unsigned char *); | ||
1955 | *s = (unsigned char)simple_strtoul(str, &next, base); | ||
1956 | } | ||
2202 | break; | 1957 | break; |
2203 | case 'h': | 1958 | case 'h': |
2204 | if (is_sign) | 1959 | if (is_sign) { |
2205 | *va_arg(args, short *) = val.s; | 1960 | short *s = (short *)va_arg(args, short *); |
2206 | else | 1961 | *s = (short)simple_strtol(str, &next, base); |
2207 | *va_arg(args, unsigned short *) = val.u; | 1962 | } else { |
1963 | unsigned short *s = (unsigned short *)va_arg(args, unsigned short *); | ||
1964 | *s = (unsigned short)simple_strtoul(str, &next, base); | ||
1965 | } | ||
2208 | break; | 1966 | break; |
2209 | case 'l': | 1967 | case 'l': |
2210 | if (is_sign) | 1968 | if (is_sign) { |
2211 | *va_arg(args, long *) = val.s; | 1969 | long *l = (long *)va_arg(args, long *); |
2212 | else | 1970 | *l = simple_strtol(str, &next, base); |
2213 | *va_arg(args, unsigned long *) = val.u; | 1971 | } else { |
1972 | unsigned long *l = (unsigned long *)va_arg(args, unsigned long *); | ||
1973 | *l = simple_strtoul(str, &next, base); | ||
1974 | } | ||
2214 | break; | 1975 | break; |
2215 | case 'L': | 1976 | case 'L': |
2216 | if (is_sign) | 1977 | if (is_sign) { |
2217 | *va_arg(args, long long *) = val.s; | 1978 | long long *l = (long long *)va_arg(args, long long *); |
2218 | else | 1979 | *l = simple_strtoll(str, &next, base); |
2219 | *va_arg(args, unsigned long long *) = val.u; | 1980 | } else { |
1981 | unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *); | ||
1982 | *l = simple_strtoull(str, &next, base); | ||
1983 | } | ||
2220 | break; | 1984 | break; |
2221 | case 'Z': | 1985 | case 'Z': |
2222 | case 'z': | 1986 | case 'z': |
2223 | *va_arg(args, size_t *) = val.u; | 1987 | { |
2224 | break; | 1988 | size_t *s = (size_t *)va_arg(args, size_t *); |
1989 | *s = (size_t)simple_strtoul(str, &next, base); | ||
1990 | } | ||
1991 | break; | ||
2225 | default: | 1992 | default: |
2226 | if (is_sign) | 1993 | if (is_sign) { |
2227 | *va_arg(args, int *) = val.s; | 1994 | int *i = (int *)va_arg(args, int *); |
2228 | else | 1995 | *i = (int)simple_strtol(str, &next, base); |
2229 | *va_arg(args, unsigned int *) = val.u; | 1996 | } else { |
1997 | unsigned int *i = (unsigned int *)va_arg(args, unsigned int*); | ||
1998 | *i = (unsigned int)simple_strtoul(str, &next, base); | ||
1999 | } | ||
2230 | break; | 2000 | break; |
2231 | } | 2001 | } |
2232 | num++; | 2002 | num++; |
@@ -2236,6 +2006,16 @@ int vsscanf(const char *buf, const char *fmt, va_list args) | |||
2236 | str = next; | 2006 | str = next; |
2237 | } | 2007 | } |
2238 | 2008 | ||
2009 | /* | ||
2010 | * Now we've come all the way through so either the input string or the | ||
2011 | * format ended. In the former case, there can be a %n at the current | ||
2012 | * position in the format that needs to be filled. | ||
2013 | */ | ||
2014 | if (*fmt == '%' && *(fmt + 1) == 'n') { | ||
2015 | int *p = (int *)va_arg(args, int *); | ||
2016 | *p = str - buf; | ||
2017 | } | ||
2018 | |||
2239 | return num; | 2019 | return num; |
2240 | } | 2020 | } |
2241 | EXPORT_SYMBOL(vsscanf); | 2021 | EXPORT_SYMBOL(vsscanf); |