1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <stdarg.h>
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/string.h>
23#include <linux/ctype.h>
24#include <linux/kernel.h>
25#include <linux/kallsyms.h>
26#include <linux/uaccess.h>
27#include <linux/ioport.h>
28#include <net/addrconf.h>
29
30#include <asm/page.h>
31#include <asm/div64.h>
32#include <asm/sections.h>
33
34
35#define TOLOWER(x) ((x) | 0x20)
36
37static unsigned int simple_guess_base(const char *cp)
38{
39 if (cp[0] == '0') {
40 if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
41 return 16;
42 else
43 return 8;
44 } else {
45 return 10;
46 }
47}
48
49
50
51
52
53
54
55unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
56{
57 unsigned long long result = 0;
58
59 if (!base)
60 base = simple_guess_base(cp);
61
62 if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
63 cp += 2;
64
65 while (isxdigit(*cp)) {
66 unsigned int value;
67
68 value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
69 if (value >= base)
70 break;
71 result = result * base + value;
72 cp++;
73 }
74 if (endp)
75 *endp = (char *)cp;
76
77 return result;
78}
79EXPORT_SYMBOL(simple_strtoull);
80
81
82
83
84
85
86
87unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
88{
89 return simple_strtoull(cp, endp, base);
90}
91EXPORT_SYMBOL(simple_strtoul);
92
93
94
95
96
97
98
99long simple_strtol(const char *cp, char **endp, unsigned int base)
100{
101 if (*cp == '-')
102 return -simple_strtoul(cp + 1, endp, base);
103
104 return simple_strtoul(cp, endp, base);
105}
106EXPORT_SYMBOL(simple_strtol);
107
108
109
110
111
112
113
114long long simple_strtoll(const char *cp, char **endp, unsigned int base)
115{
116 if (*cp == '-')
117 return -simple_strtoull(cp + 1, endp, base);
118
119 return simple_strtoull(cp, endp, base);
120}
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
145{
146 char *tail;
147 unsigned long val;
148 size_t len;
149
150 *res = 0;
151 len = strlen(cp);
152 if (len == 0)
153 return -EINVAL;
154
155 val = simple_strtoul(cp, &tail, base);
156 if (tail == cp)
157 return -EINVAL;
158
159 if ((*tail == '\0') ||
160 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
161 *res = val;
162 return 0;
163 }
164
165 return -EINVAL;
166}
167EXPORT_SYMBOL(strict_strtoul);
168
169
170
171
172
173
174
175
176
177
178
179
180
181int strict_strtol(const char *cp, unsigned int base, long *res)
182{
183 int ret;
184 if (*cp == '-') {
185 ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
186 if (!ret)
187 *res = -(*res);
188 } else {
189 ret = strict_strtoul(cp, base, (unsigned long *)res);
190 }
191
192 return ret;
193}
194EXPORT_SYMBOL(strict_strtol);
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
219{
220 char *tail;
221 unsigned long long val;
222 size_t len;
223
224 *res = 0;
225 len = strlen(cp);
226 if (len == 0)
227 return -EINVAL;
228
229 val = simple_strtoull(cp, &tail, base);
230 if (tail == cp)
231 return -EINVAL;
232 if ((*tail == '\0') ||
233 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
234 *res = val;
235 return 0;
236 }
237
238 return -EINVAL;
239}
240EXPORT_SYMBOL(strict_strtoull);
241
242
243
244
245
246
247
248
249
250
251
252
253
254int strict_strtoll(const char *cp, unsigned int base, long long *res)
255{
256 int ret;
257 if (*cp == '-') {
258 ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
259 if (!ret)
260 *res = -(*res);
261 } else {
262 ret = strict_strtoull(cp, base, (unsigned long long *)res);
263 }
264
265 return ret;
266}
267EXPORT_SYMBOL(strict_strtoll);
268
269static int skip_atoi(const char **s)
270{
271 int i = 0;
272
273 while (isdigit(**s))
274 i = i*10 + *((*s)++) - '0';
275
276 return i;
277}
278
279
280
281
282
283
284
285
286
287
288
289static char *put_dec_trunc(char *buf, unsigned q)
290{
291 unsigned d3, d2, d1, d0;
292 d1 = (q>>4) & 0xf;
293 d2 = (q>>8) & 0xf;
294 d3 = (q>>12);
295
296 d0 = 6*(d3 + d2 + d1) + (q & 0xf);
297 q = (d0 * 0xcd) >> 11;
298 d0 = d0 - 10*q;
299 *buf++ = d0 + '0';
300 d1 = q + 9*d3 + 5*d2 + d1;
301 if (d1 != 0) {
302 q = (d1 * 0xcd) >> 11;
303 d1 = d1 - 10*q;
304 *buf++ = d1 + '0';
305
306 d2 = q + 2*d2;
307 if ((d2 != 0) || (d3 != 0)) {
308 q = (d2 * 0xd) >> 7;
309 d2 = d2 - 10*q;
310 *buf++ = d2 + '0';
311
312 d3 = q + 4*d3;
313 if (d3 != 0) {
314 q = (d3 * 0xcd) >> 11;
315 d3 = d3 - 10*q;
316 *buf++ = d3 + '0';
317 if (q != 0)
318 *buf++ = q + '0';
319 }
320 }
321 }
322
323 return buf;
324}
325
326static char *put_dec_full(char *buf, unsigned q)
327{
328
329
330 unsigned d3, d2, d1, d0;
331 d1 = (q>>4) & 0xf;
332 d2 = (q>>8) & 0xf;
333 d3 = (q>>12);
334
335
336
337
338
339
340
341
342
343
344 d0 = 6*(d3 + d2 + d1) + (q & 0xf);
345 q = (d0 * 0xcd) >> 11;
346 d0 = d0 - 10*q;
347 *buf++ = d0 + '0';
348 d1 = q + 9*d3 + 5*d2 + d1;
349 q = (d1 * 0xcd) >> 11;
350 d1 = d1 - 10*q;
351 *buf++ = d1 + '0';
352
353 d2 = q + 2*d2;
354 q = (d2 * 0xd) >> 7;
355 d2 = d2 - 10*q;
356 *buf++ = d2 + '0';
357
358 d3 = q + 4*d3;
359 q = (d3 * 0xcd) >> 11;
360
361 d3 = d3 - 10*q;
362 *buf++ = d3 + '0';
363 *buf++ = q + '0';
364
365 return buf;
366}
367
368static noinline char *put_dec(char *buf, unsigned long long num)
369{
370 while (1) {
371 unsigned rem;
372 if (num < 100000)
373 return put_dec_trunc(buf, num);
374 rem = do_div(num, 100000);
375 buf = put_dec_full(buf, rem);
376 }
377}
378
379#define ZEROPAD 1
380#define SIGN 2
381#define PLUS 4
382#define SPACE 8
383#define LEFT 16
384#define SMALL 32
385#define SPECIAL 64
386
387enum format_type {
388 FORMAT_TYPE_NONE,
389 FORMAT_TYPE_WIDTH,
390 FORMAT_TYPE_PRECISION,
391 FORMAT_TYPE_CHAR,
392 FORMAT_TYPE_STR,
393 FORMAT_TYPE_PTR,
394 FORMAT_TYPE_PERCENT_CHAR,
395 FORMAT_TYPE_INVALID,
396 FORMAT_TYPE_LONG_LONG,
397 FORMAT_TYPE_ULONG,
398 FORMAT_TYPE_LONG,
399 FORMAT_TYPE_UBYTE,
400 FORMAT_TYPE_BYTE,
401 FORMAT_TYPE_USHORT,
402 FORMAT_TYPE_SHORT,
403 FORMAT_TYPE_UINT,
404 FORMAT_TYPE_INT,
405 FORMAT_TYPE_NRCHARS,
406 FORMAT_TYPE_SIZE_T,
407 FORMAT_TYPE_PTRDIFF
408};
409
410struct printf_spec {
411 enum format_type type;
412 int flags;
413 int field_width;
414 int base;
415 int precision;
416 int qualifier;
417};
418
419static char *number(char *buf, char *end, unsigned long long num,
420 struct printf_spec spec)
421{
422
423 static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
424
425 char tmp[66];
426 char sign;
427 char locase;
428 int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
429 int i;
430
431
432
433 locase = (spec.flags & SMALL);
434 if (spec.flags & LEFT)
435 spec.flags &= ~ZEROPAD;
436 sign = 0;
437 if (spec.flags & SIGN) {
438 if ((signed long long)num < 0) {
439 sign = '-';
440 num = -(signed long long)num;
441 spec.field_width--;
442 } else if (spec.flags & PLUS) {
443 sign = '+';
444 spec.field_width--;
445 } else if (spec.flags & SPACE) {
446 sign = ' ';
447 spec.field_width--;
448 }
449 }
450 if (need_pfx) {
451 spec.field_width--;
452 if (spec.base == 16)
453 spec.field_width--;
454 }
455
456
457 i = 0;
458 if (num == 0)
459 tmp[i++] = '0';
460
461
462
463
464
465 else if (spec.base != 10) {
466 int mask = spec.base - 1;
467 int shift = 3;
468
469 if (spec.base == 16)
470 shift = 4;
471 do {
472 tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
473 num >>= shift;
474 } while (num);
475 } else {
476 i = put_dec(tmp, num) - tmp;
477 }
478
479
480 if (i > spec.precision)
481 spec.precision = i;
482
483 spec.field_width -= spec.precision;
484 if (!(spec.flags & (ZEROPAD+LEFT))) {
485 while (--spec.field_width >= 0) {
486 if (buf < end)
487 *buf = ' ';
488 ++buf;
489 }
490 }
491
492 if (sign) {
493 if (buf < end)
494 *buf = sign;
495 ++buf;
496 }
497
498 if (need_pfx) {
499 if (buf < end)
500 *buf = '0';
501 ++buf;
502 if (spec.base == 16) {
503 if (buf < end)
504 *buf = ('X' | locase);
505 ++buf;
506 }
507 }
508
509 if (!(spec.flags & LEFT)) {
510 char c = (spec.flags & ZEROPAD) ? '0' : ' ';
511 while (--spec.field_width >= 0) {
512 if (buf < end)
513 *buf = c;
514 ++buf;
515 }
516 }
517
518 while (i <= --spec.precision) {
519 if (buf < end)
520 *buf = '0';
521 ++buf;
522 }
523
524 while (--i >= 0) {
525 if (buf < end)
526 *buf = tmp[i];
527 ++buf;
528 }
529
530 while (--spec.field_width >= 0) {
531 if (buf < end)
532 *buf = ' ';
533 ++buf;
534 }
535
536 return buf;
537}
538
539static char *string(char *buf, char *end, const char *s, struct printf_spec spec)
540{
541 int len, i;
542
543 if ((unsigned long)s < PAGE_SIZE)
544 s = "(null)";
545
546 len = strnlen(s, spec.precision);
547
548 if (!(spec.flags & LEFT)) {
549 while (len < spec.field_width--) {
550 if (buf < end)
551 *buf = ' ';
552 ++buf;
553 }
554 }
555 for (i = 0; i < len; ++i) {
556 if (buf < end)
557 *buf = *s;
558 ++buf; ++s;
559 }
560 while (len < spec.field_width--) {
561 if (buf < end)
562 *buf = ' ';
563 ++buf;
564 }
565
566 return buf;
567}
568
569static char *symbol_string(char *buf, char *end, void *ptr,
570 struct printf_spec spec, char ext)
571{
572 unsigned long value = (unsigned long) ptr;
573#ifdef CONFIG_KALLSYMS
574 char sym[KSYM_SYMBOL_LEN];
575 if (ext != 'f' && ext != 's')
576 sprint_symbol(sym, value);
577 else
578 kallsyms_lookup(value, NULL, NULL, NULL, sym);
579
580 return string(buf, end, sym, spec);
581#else
582 spec.field_width = 2 * sizeof(void *);
583 spec.flags |= SPECIAL | SMALL | ZEROPAD;
584 spec.base = 16;
585
586 return number(buf, end, value, spec);
587#endif
588}
589
590static char *resource_string(char *buf, char *end, struct resource *res,
591 struct printf_spec spec, const char *fmt)
592{
593#ifndef IO_RSRC_PRINTK_SIZE
594#define IO_RSRC_PRINTK_SIZE 6
595#endif
596
597#ifndef MEM_RSRC_PRINTK_SIZE
598#define MEM_RSRC_PRINTK_SIZE 10
599#endif
600 struct printf_spec hex_spec = {
601 .base = 16,
602 .precision = -1,
603 .flags = SPECIAL | SMALL | ZEROPAD,
604 };
605 struct printf_spec dec_spec = {
606 .base = 10,
607 .precision = -1,
608 .flags = 0,
609 };
610 struct printf_spec str_spec = {
611 .field_width = -1,
612 .precision = 10,
613 .flags = LEFT,
614 };
615 struct printf_spec flag_spec = {
616 .base = 16,
617 .precision = -1,
618 .flags = SPECIAL | SMALL,
619 };
620
621
622
623#define RSRC_BUF_SIZE ((2 * sizeof(resource_size_t)) + 4)
624#define FLAG_BUF_SIZE (2 * sizeof(res->flags))
625#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref disabled]")
626#define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
627 char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
628 2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
629
630 char *p = sym, *pend = sym + sizeof(sym);
631 int size = -1, addr = 0;
632 int decode = (fmt[0] == 'R') ? 1 : 0;
633
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
642 *p++ = '[';
643 if (res->flags & IORESOURCE_IO)
644 p = string(p, pend, "io ", str_spec);
645 else if (res->flags & IORESOURCE_MEM)
646 p = string(p, pend, "mem ", str_spec);
647 else if (res->flags & IORESOURCE_IRQ)
648 p = string(p, pend, "irq ", str_spec);
649 else if (res->flags & IORESOURCE_DMA)
650 p = string(p, pend, "dma ", str_spec);
651 else {
652 p = string(p, pend, "??? ", str_spec);
653 decode = 0;
654 }
655 hex_spec.field_width = size;
656 p = number(p, pend, res->start, addr ? hex_spec : dec_spec);
657 if (res->start != res->end) {
658 *p++ = '-';
659 p = number(p, pend, res->end, addr ? hex_spec : dec_spec);
660 }
661 if (decode) {
662 if (res->flags & IORESOURCE_MEM_64)
663 p = string(p, pend, " 64bit", str_spec);
664 if (res->flags & IORESOURCE_PREFETCH)
665 p = string(p, pend, " pref", str_spec);
666 if (res->flags & IORESOURCE_DISABLED)
667 p = string(p, pend, " disabled", str_spec);
668 } else {
669 p = string(p, pend, " flags ", str_spec);
670 p = number(p, pend, res->flags, flag_spec);
671 }
672 *p++ = ']';
673 *p = '\0';
674
675 return string(buf, end, sym, spec);
676}
677
678static char *mac_address_string(char *buf, char *end, u8 *addr,
679 struct printf_spec spec, const char *fmt)
680{
681 char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
682 char *p = mac_addr;
683 int i;
684
685 for (i = 0; i < 6; i++) {
686 p = pack_hex_byte(p, addr[i]);
687 if (fmt[0] == 'M' && i != 5)
688 *p++ = ':';
689 }
690 *p = '\0';
691
692 return string(buf, end, mac_addr, spec);
693}
694
695static char *ip4_string(char *p, const u8 *addr, bool leading_zeros)
696{
697 int i;
698
699 for (i = 0; i < 4; i++) {
700 char temp[3];
701 int digits = put_dec_trunc(temp, addr[i]) - temp;
702 if (leading_zeros) {
703 if (digits < 3)
704 *p++ = '0';
705 if (digits < 2)
706 *p++ = '0';
707 }
708
709 while (digits--)
710 *p++ = temp[digits];
711 if (i < 3)
712 *p++ = '.';
713 }
714 *p = '\0';
715
716 return p;
717}
718
719static char *ip6_compressed_string(char *p, const char *addr)
720{
721 int i, j, range;
722 unsigned char zerolength[8];
723 int longest = 1;
724 int colonpos = -1;
725 u16 word;
726 u8 hi, lo;
727 bool needcolon = false;
728 bool useIPv4;
729 struct in6_addr in6;
730
731 memcpy(&in6, addr, sizeof(struct in6_addr));
732
733 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
734
735 memset(zerolength, 0, sizeof(zerolength));
736
737 if (useIPv4)
738 range = 6;
739 else
740 range = 8;
741
742
743 for (i = 0; i < range; i++) {
744 for (j = i; j < range; j++) {
745 if (in6.s6_addr16[j] != 0)
746 break;
747 zerolength[i]++;
748 }
749 }
750 for (i = 0; i < range; i++) {
751 if (zerolength[i] > longest) {
752 longest = zerolength[i];
753 colonpos = i;
754 }
755 }
756
757
758 for (i = 0; i < range; i++) {
759 if (i == colonpos) {
760 if (needcolon || i == 0)
761 *p++ = ':';
762 *p++ = ':';
763 needcolon = false;
764 i += longest - 1;
765 continue;
766 }
767 if (needcolon) {
768 *p++ = ':';
769 needcolon = false;
770 }
771
772 word = ntohs(in6.s6_addr16[i]);
773 hi = word >> 8;
774 lo = word & 0xff;
775 if (hi) {
776 if (hi > 0x0f)
777 p = pack_hex_byte(p, hi);
778 else
779 *p++ = hex_asc_lo(hi);
780 p = pack_hex_byte(p, lo);
781 }
782 else if (lo > 0x0f)
783 p = pack_hex_byte(p, lo);
784 else
785 *p++ = hex_asc_lo(lo);
786 needcolon = true;
787 }
788
789 if (useIPv4) {
790 if (needcolon)
791 *p++ = ':';
792 p = ip4_string(p, &in6.s6_addr[12], false);
793 }
794 *p = '\0';
795
796 return p;
797}
798
799static char *ip6_string(char *p, const char *addr, const char *fmt)
800{
801 int i;
802
803 for (i = 0; i < 8; i++) {
804 p = pack_hex_byte(p, *addr++);
805 p = pack_hex_byte(p, *addr++);
806 if (fmt[0] == 'I' && i != 7)
807 *p++ = ':';
808 }
809 *p = '\0';
810
811 return p;
812}
813
814static char *ip6_addr_string(char *buf, char *end, const u8 *addr,
815 struct printf_spec spec, const char *fmt)
816{
817 char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
818
819 if (fmt[0] == 'I' && fmt[2] == 'c')
820 ip6_compressed_string(ip6_addr, addr);
821 else
822 ip6_string(ip6_addr, addr, fmt);
823
824 return string(buf, end, ip6_addr, spec);
825}
826
827static char *ip4_addr_string(char *buf, char *end, const u8 *addr,
828 struct printf_spec spec, const char *fmt)
829{
830 char ip4_addr[sizeof("255.255.255.255")];
831
832 ip4_string(ip4_addr, addr, fmt[0] == 'i');
833
834 return string(buf, end, ip4_addr, spec);
835}
836
837static char *uuid_string(char *buf, char *end, const u8 *addr,
838 struct printf_spec spec, const char *fmt)
839{
840 char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
841 char *p = uuid;
842 int i;
843 static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
844 static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
845 const u8 *index = be;
846 bool uc = false;
847
848 switch (*(++fmt)) {
849 case 'L':
850 uc = true;
851 case 'l':
852 index = le;
853 break;
854 case 'B':
855 uc = true;
856 break;
857 }
858
859 for (i = 0; i < 16; i++) {
860 p = pack_hex_byte(p, addr[index[i]]);
861 switch (i) {
862 case 3:
863 case 5:
864 case 7:
865 case 9:
866 *p++ = '-';
867 break;
868 }
869 }
870
871 *p = 0;
872
873 if (uc) {
874 p = uuid;
875 do {
876 *p = toupper(*p);
877 } while (*(++p));
878 }
879
880 return string(buf, end, uuid, spec);
881}
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
924 struct printf_spec spec)
925{
926 if (!ptr)
927 return string(buf, end, "(null)", spec);
928
929 switch (*fmt) {
930 case 'F':
931 case 'f':
932 ptr = dereference_function_descriptor(ptr);
933
934 case 'S':
935 case 's':
936 return symbol_string(buf, end, ptr, spec, *fmt);
937 case 'R':
938 case 'r':
939 return resource_string(buf, end, ptr, spec, fmt);
940 case 'M':
941 case 'm':
942 return mac_address_string(buf, end, ptr, spec, fmt);
943 case 'I':
944
945
946
947
948 case 'i':
949
950
951
952 switch (fmt[1]) {
953 case '6':
954 return ip6_addr_string(buf, end, ptr, spec, fmt);
955 case '4':
956 return ip4_addr_string(buf, end, ptr, spec, fmt);
957 }
958 break;
959 case 'U':
960 return uuid_string(buf, end, ptr, spec, fmt);
961 }
962 spec.flags |= SMALL;
963 if (spec.field_width == -1) {
964 spec.field_width = 2*sizeof(void *);
965 spec.flags |= ZEROPAD;
966 }
967 spec.base = 16;
968
969 return number(buf, end, (unsigned long) ptr, spec);
970}
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992static int format_decode(const char *fmt, struct printf_spec *spec)
993{
994 const char *start = fmt;
995
996
997 if (spec->type == FORMAT_TYPE_WIDTH) {
998 if (spec->field_width < 0) {
999 spec->field_width = -spec->field_width;
1000 spec->flags |= LEFT;
1001 }
1002 spec->type = FORMAT_TYPE_NONE;
1003 goto precision;
1004 }
1005
1006
1007 if (spec->type == FORMAT_TYPE_PRECISION) {
1008 if (spec->precision < 0)
1009 spec->precision = 0;
1010
1011 spec->type = FORMAT_TYPE_NONE;
1012 goto qualifier;
1013 }
1014
1015
1016 spec->type = FORMAT_TYPE_NONE;
1017
1018 for (; *fmt ; ++fmt) {
1019 if (*fmt == '%')
1020 break;
1021 }
1022
1023
1024 if (fmt != start || !*fmt)
1025 return fmt - start;
1026
1027
1028 spec->flags = 0;
1029
1030 while (1) {
1031 bool found = true;
1032
1033 ++fmt;
1034
1035 switch (*fmt) {
1036 case '-': spec->flags |= LEFT; break;
1037 case '+': spec->flags |= PLUS; break;
1038 case ' ': spec->flags |= SPACE; break;
1039 case '#': spec->flags |= SPECIAL; break;
1040 case '0': spec->flags |= ZEROPAD; break;
1041 default: found = false;
1042 }
1043
1044 if (!found)
1045 break;
1046 }
1047
1048
1049 spec->field_width = -1;
1050
1051 if (isdigit(*fmt))
1052 spec->field_width = skip_atoi(&fmt);
1053 else if (*fmt == '*') {
1054
1055 spec->type = FORMAT_TYPE_WIDTH;
1056 return ++fmt - start;
1057 }
1058
1059precision:
1060
1061 spec->precision = -1;
1062 if (*fmt == '.') {
1063 ++fmt;
1064 if (isdigit(*fmt)) {
1065 spec->precision = skip_atoi(&fmt);
1066 if (spec->precision < 0)
1067 spec->precision = 0;
1068 } else if (*fmt == '*') {
1069
1070 spec->type = FORMAT_TYPE_PRECISION;
1071 return ++fmt - start;
1072 }
1073 }
1074
1075qualifier:
1076
1077 spec->qualifier = -1;
1078 if (*fmt == 'h' || TOLOWER(*fmt) == 'l' ||
1079 TOLOWER(*fmt) == 'z' || *fmt == 't') {
1080 spec->qualifier = *fmt++;
1081 if (unlikely(spec->qualifier == *fmt)) {
1082 if (spec->qualifier == 'l') {
1083 spec->qualifier = 'L';
1084 ++fmt;
1085 } else if (spec->qualifier == 'h') {
1086 spec->qualifier = 'H';
1087 ++fmt;
1088 }
1089 }
1090 }
1091
1092
1093 spec->base = 10;
1094 switch (*fmt) {
1095 case 'c':
1096 spec->type = FORMAT_TYPE_CHAR;
1097 return ++fmt - start;
1098
1099 case 's':
1100 spec->type = FORMAT_TYPE_STR;
1101 return ++fmt - start;
1102
1103 case 'p':
1104 spec->type = FORMAT_TYPE_PTR;
1105 return fmt - start;
1106
1107
1108 case 'n':
1109 spec->type = FORMAT_TYPE_NRCHARS;
1110 return ++fmt - start;
1111
1112 case '%':
1113 spec->type = FORMAT_TYPE_PERCENT_CHAR;
1114 return ++fmt - start;
1115
1116
1117 case 'o':
1118 spec->base = 8;
1119 break;
1120
1121 case 'x':
1122 spec->flags |= SMALL;
1123
1124 case 'X':
1125 spec->base = 16;
1126 break;
1127
1128 case 'd':
1129 case 'i':
1130 spec->flags |= SIGN;
1131 case 'u':
1132 break;
1133
1134 default:
1135 spec->type = FORMAT_TYPE_INVALID;
1136 return fmt - start;
1137 }
1138
1139 if (spec->qualifier == 'L')
1140 spec->type = FORMAT_TYPE_LONG_LONG;
1141 else if (spec->qualifier == 'l') {
1142 if (spec->flags & SIGN)
1143 spec->type = FORMAT_TYPE_LONG;
1144 else
1145 spec->type = FORMAT_TYPE_ULONG;
1146 } else if (TOLOWER(spec->qualifier) == 'z') {
1147 spec->type = FORMAT_TYPE_SIZE_T;
1148 } else if (spec->qualifier == 't') {
1149 spec->type = FORMAT_TYPE_PTRDIFF;
1150 } else if (spec->qualifier == 'H') {
1151 if (spec->flags & SIGN)
1152 spec->type = FORMAT_TYPE_BYTE;
1153 else
1154 spec->type = FORMAT_TYPE_UBYTE;
1155 } else if (spec->qualifier == 'h') {
1156 if (spec->flags & SIGN)
1157 spec->type = FORMAT_TYPE_SHORT;
1158 else
1159 spec->type = FORMAT_TYPE_USHORT;
1160 } else {
1161 if (spec->flags & SIGN)
1162 spec->type = FORMAT_TYPE_INT;
1163 else
1164 spec->type = FORMAT_TYPE_UINT;
1165 }
1166
1167 return ++fmt - start;
1168}
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
1208{
1209 unsigned long long num;
1210 char *str, *end;
1211 struct printf_spec spec = {0};
1212
1213
1214
1215 if (WARN_ON_ONCE((int) size < 0))
1216 return 0;
1217
1218 str = buf;
1219 end = buf + size;
1220
1221
1222 if (end < buf) {
1223 end = ((void *)-1);
1224 size = end - buf;
1225 }
1226
1227 while (*fmt) {
1228 const char *old_fmt = fmt;
1229 int read = format_decode(fmt, &spec);
1230
1231 fmt += read;
1232
1233 switch (spec.type) {
1234 case FORMAT_TYPE_NONE: {
1235 int copy = read;
1236 if (str < end) {
1237 if (copy > end - str)
1238 copy = end - str;
1239 memcpy(str, old_fmt, copy);
1240 }
1241 str += read;
1242 break;
1243 }
1244
1245 case FORMAT_TYPE_WIDTH:
1246 spec.field_width = va_arg(args, int);
1247 break;
1248
1249 case FORMAT_TYPE_PRECISION:
1250 spec.precision = va_arg(args, int);
1251 break;
1252
1253 case FORMAT_TYPE_CHAR: {
1254 char c;
1255
1256 if (!(spec.flags & LEFT)) {
1257 while (--spec.field_width > 0) {
1258 if (str < end)
1259 *str = ' ';
1260 ++str;
1261
1262 }
1263 }
1264 c = (unsigned char) va_arg(args, int);
1265 if (str < end)
1266 *str = c;
1267 ++str;
1268 while (--spec.field_width > 0) {
1269 if (str < end)
1270 *str = ' ';
1271 ++str;
1272 }
1273 break;
1274 }
1275
1276 case FORMAT_TYPE_STR:
1277 str = string(str, end, va_arg(args, char *), spec);
1278 break;
1279
1280 case FORMAT_TYPE_PTR:
1281 str = pointer(fmt+1, str, end, va_arg(args, void *),
1282 spec);
1283 while (isalnum(*fmt))
1284 fmt++;
1285 break;
1286
1287 case FORMAT_TYPE_PERCENT_CHAR:
1288 if (str < end)
1289 *str = '%';
1290 ++str;
1291 break;
1292
1293 case FORMAT_TYPE_INVALID:
1294 if (str < end)
1295 *str = '%';
1296 ++str;
1297 break;
1298
1299 case FORMAT_TYPE_NRCHARS: {
1300 int qualifier = spec.qualifier;
1301
1302 if (qualifier == 'l') {
1303 long *ip = va_arg(args, long *);
1304 *ip = (str - buf);
1305 } else if (TOLOWER(qualifier) == 'z') {
1306 size_t *ip = va_arg(args, size_t *);
1307 *ip = (str - buf);
1308 } else {
1309 int *ip = va_arg(args, int *);
1310 *ip = (str - buf);
1311 }
1312 break;
1313 }
1314
1315 default:
1316 switch (spec.type) {
1317 case FORMAT_TYPE_LONG_LONG:
1318 num = va_arg(args, long long);
1319 break;
1320 case FORMAT_TYPE_ULONG:
1321 num = va_arg(args, unsigned long);
1322 break;
1323 case FORMAT_TYPE_LONG:
1324 num = va_arg(args, long);
1325 break;
1326 case FORMAT_TYPE_SIZE_T:
1327 num = va_arg(args, size_t);
1328 break;
1329 case FORMAT_TYPE_PTRDIFF:
1330 num = va_arg(args, ptrdiff_t);
1331 break;
1332 case FORMAT_TYPE_UBYTE:
1333 num = (unsigned char) va_arg(args, int);
1334 break;
1335 case FORMAT_TYPE_BYTE:
1336 num = (signed char) va_arg(args, int);
1337 break;
1338 case FORMAT_TYPE_USHORT:
1339 num = (unsigned short) va_arg(args, int);
1340 break;
1341 case FORMAT_TYPE_SHORT:
1342 num = (short) va_arg(args, int);
1343 break;
1344 case FORMAT_TYPE_INT:
1345 num = (int) va_arg(args, int);
1346 break;
1347 default:
1348 num = va_arg(args, unsigned int);
1349 }
1350
1351 str = number(str, end, num, spec);
1352 }
1353 }
1354
1355 if (size > 0) {
1356 if (str < end)
1357 *str = '\0';
1358 else
1359 end[-1] = '\0';
1360 }
1361
1362
1363 return str-buf;
1364
1365}
1366EXPORT_SYMBOL(vsnprintf);
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
1385{
1386 int i;
1387
1388 i = vsnprintf(buf, size, fmt, args);
1389
1390 return (i >= size) ? (size - 1) : i;
1391}
1392EXPORT_SYMBOL(vscnprintf);
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408int snprintf(char *buf, size_t size, const char *fmt, ...)
1409{
1410 va_list args;
1411 int i;
1412
1413 va_start(args, fmt);
1414 i = vsnprintf(buf, size, fmt, args);
1415 va_end(args);
1416
1417 return i;
1418}
1419EXPORT_SYMBOL(snprintf);
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432int scnprintf(char *buf, size_t size, const char *fmt, ...)
1433{
1434 va_list args;
1435 int i;
1436
1437 va_start(args, fmt);
1438 i = vsnprintf(buf, size, fmt, args);
1439 va_end(args);
1440
1441 return (i >= size) ? (size - 1) : i;
1442}
1443EXPORT_SYMBOL(scnprintf);
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460int vsprintf(char *buf, const char *fmt, va_list args)
1461{
1462 return vsnprintf(buf, INT_MAX, fmt, args);
1463}
1464EXPORT_SYMBOL(vsprintf);
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478int sprintf(char *buf, const char *fmt, ...)
1479{
1480 va_list args;
1481 int i;
1482
1483 va_start(args, fmt);
1484 i = vsnprintf(buf, INT_MAX, fmt, args);
1485 va_end(args);
1486
1487 return i;
1488}
1489EXPORT_SYMBOL(sprintf);
1490
1491#ifdef CONFIG_BINARY_PRINTF
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
1516{
1517 struct printf_spec spec = {0};
1518 char *str, *end;
1519
1520 str = (char *)bin_buf;
1521 end = (char *)(bin_buf + size);
1522
1523#define save_arg(type) \
1524do { \
1525 if (sizeof(type) == 8) { \
1526 unsigned long long value; \
1527 str = PTR_ALIGN(str, sizeof(u32)); \
1528 value = va_arg(args, unsigned long long); \
1529 if (str + sizeof(type) <= end) { \
1530 *(u32 *)str = *(u32 *)&value; \
1531 *(u32 *)(str + 4) = *((u32 *)&value + 1); \
1532 } \
1533 } else { \
1534 unsigned long value; \
1535 str = PTR_ALIGN(str, sizeof(type)); \
1536 value = va_arg(args, int); \
1537 if (str + sizeof(type) <= end) \
1538 *(typeof(type) *)str = (type)value; \
1539 } \
1540 str += sizeof(type); \
1541} while (0)
1542
1543 while (*fmt) {
1544 int read = format_decode(fmt, &spec);
1545
1546 fmt += read;
1547
1548 switch (spec.type) {
1549 case FORMAT_TYPE_NONE:
1550 case FORMAT_TYPE_INVALID:
1551 case FORMAT_TYPE_PERCENT_CHAR:
1552 break;
1553
1554 case FORMAT_TYPE_WIDTH:
1555 case FORMAT_TYPE_PRECISION:
1556 save_arg(int);
1557 break;
1558
1559 case FORMAT_TYPE_CHAR:
1560 save_arg(char);
1561 break;
1562
1563 case FORMAT_TYPE_STR: {
1564 const char *save_str = va_arg(args, char *);
1565 size_t len;
1566
1567 if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE
1568 || (unsigned long)save_str < PAGE_SIZE)
1569 save_str = "(null)";
1570 len = strlen(save_str) + 1;
1571 if (str + len < end)
1572 memcpy(str, save_str, len);
1573 str += len;
1574 break;
1575 }
1576
1577 case FORMAT_TYPE_PTR:
1578 save_arg(void *);
1579
1580 while (isalnum(*fmt))
1581 fmt++;
1582 break;
1583
1584 case FORMAT_TYPE_NRCHARS: {
1585
1586 int qualifier = spec.qualifier;
1587 void *skip_arg;
1588 if (qualifier == 'l')
1589 skip_arg = va_arg(args, long *);
1590 else if (TOLOWER(qualifier) == 'z')
1591 skip_arg = va_arg(args, size_t *);
1592 else
1593 skip_arg = va_arg(args, int *);
1594 break;
1595 }
1596
1597 default:
1598 switch (spec.type) {
1599
1600 case FORMAT_TYPE_LONG_LONG:
1601 save_arg(long long);
1602 break;
1603 case FORMAT_TYPE_ULONG:
1604 case FORMAT_TYPE_LONG:
1605 save_arg(unsigned long);
1606 break;
1607 case FORMAT_TYPE_SIZE_T:
1608 save_arg(size_t);
1609 break;
1610 case FORMAT_TYPE_PTRDIFF:
1611 save_arg(ptrdiff_t);
1612 break;
1613 case FORMAT_TYPE_UBYTE:
1614 case FORMAT_TYPE_BYTE:
1615 save_arg(char);
1616 break;
1617 case FORMAT_TYPE_USHORT:
1618 case FORMAT_TYPE_SHORT:
1619 save_arg(short);
1620 break;
1621 default:
1622 save_arg(int);
1623 }
1624 }
1625 }
1626
1627 return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
1628#undef save_arg
1629}
1630EXPORT_SYMBOL_GPL(vbin_printf);
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
1655{
1656 struct printf_spec spec = {0};
1657 char *str, *end;
1658 const char *args = (const char *)bin_buf;
1659
1660 if (WARN_ON_ONCE((int) size < 0))
1661 return 0;
1662
1663 str = buf;
1664 end = buf + size;
1665
1666#define get_arg(type) \
1667({ \
1668 typeof(type) value; \
1669 if (sizeof(type) == 8) { \
1670 args = PTR_ALIGN(args, sizeof(u32)); \
1671 *(u32 *)&value = *(u32 *)args; \
1672 *((u32 *)&value + 1) = *(u32 *)(args + 4); \
1673 } else { \
1674 args = PTR_ALIGN(args, sizeof(type)); \
1675 value = *(typeof(type) *)args; \
1676 } \
1677 args += sizeof(type); \
1678 value; \
1679})
1680
1681
1682 if (end < buf) {
1683 end = ((void *)-1);
1684 size = end - buf;
1685 }
1686
1687 while (*fmt) {
1688 const char *old_fmt = fmt;
1689 int read = format_decode(fmt, &spec);
1690
1691 fmt += read;
1692
1693 switch (spec.type) {
1694 case FORMAT_TYPE_NONE: {
1695 int copy = read;
1696 if (str < end) {
1697 if (copy > end - str)
1698 copy = end - str;
1699 memcpy(str, old_fmt, copy);
1700 }
1701 str += read;
1702 break;
1703 }
1704
1705 case FORMAT_TYPE_WIDTH:
1706 spec.field_width = get_arg(int);
1707 break;
1708
1709 case FORMAT_TYPE_PRECISION:
1710 spec.precision = get_arg(int);
1711 break;
1712
1713 case FORMAT_TYPE_CHAR: {
1714 char c;
1715
1716 if (!(spec.flags & LEFT)) {
1717 while (--spec.field_width > 0) {
1718 if (str < end)
1719 *str = ' ';
1720 ++str;
1721 }
1722 }
1723 c = (unsigned char) get_arg(char);
1724 if (str < end)
1725 *str = c;
1726 ++str;
1727 while (--spec.field_width > 0) {
1728 if (str < end)
1729 *str = ' ';
1730 ++str;
1731 }
1732 break;
1733 }
1734
1735 case FORMAT_TYPE_STR: {
1736 const char *str_arg = args;
1737 args += strlen(str_arg) + 1;
1738 str = string(str, end, (char *)str_arg, spec);
1739 break;
1740 }
1741
1742 case FORMAT_TYPE_PTR:
1743 str = pointer(fmt+1, str, end, get_arg(void *), spec);
1744 while (isalnum(*fmt))
1745 fmt++;
1746 break;
1747
1748 case FORMAT_TYPE_PERCENT_CHAR:
1749 case FORMAT_TYPE_INVALID:
1750 if (str < end)
1751 *str = '%';
1752 ++str;
1753 break;
1754
1755 case FORMAT_TYPE_NRCHARS:
1756
1757 break;
1758
1759 default: {
1760 unsigned long long num;
1761
1762 switch (spec.type) {
1763
1764 case FORMAT_TYPE_LONG_LONG:
1765 num = get_arg(long long);
1766 break;
1767 case FORMAT_TYPE_ULONG:
1768 case FORMAT_TYPE_LONG:
1769 num = get_arg(unsigned long);
1770 break;
1771 case FORMAT_TYPE_SIZE_T:
1772 num = get_arg(size_t);
1773 break;
1774 case FORMAT_TYPE_PTRDIFF:
1775 num = get_arg(ptrdiff_t);
1776 break;
1777 case FORMAT_TYPE_UBYTE:
1778 num = get_arg(unsigned char);
1779 break;
1780 case FORMAT_TYPE_BYTE:
1781 num = get_arg(signed char);
1782 break;
1783 case FORMAT_TYPE_USHORT:
1784 num = get_arg(unsigned short);
1785 break;
1786 case FORMAT_TYPE_SHORT:
1787 num = get_arg(short);
1788 break;
1789 case FORMAT_TYPE_UINT:
1790 num = get_arg(unsigned int);
1791 break;
1792 default:
1793 num = get_arg(int);
1794 }
1795
1796 str = number(str, end, num, spec);
1797 }
1798 }
1799 }
1800
1801 if (size > 0) {
1802 if (str < end)
1803 *str = '\0';
1804 else
1805 end[-1] = '\0';
1806 }
1807
1808#undef get_arg
1809
1810
1811 return str - buf;
1812}
1813EXPORT_SYMBOL_GPL(bstr_printf);
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
1826{
1827 va_list args;
1828 int ret;
1829
1830 va_start(args, fmt);
1831 ret = vbin_printf(bin_buf, size, fmt, args);
1832 va_end(args);
1833
1834 return ret;
1835}
1836EXPORT_SYMBOL_GPL(bprintf);
1837
1838#endif
1839
1840
1841
1842
1843
1844
1845
1846int vsscanf(const char *buf, const char *fmt, va_list args)
1847{
1848 const char *str = buf;
1849 char *next;
1850 char digit;
1851 int num = 0;
1852 int qualifier, base, field_width;
1853 bool is_sign;
1854
1855 while (*fmt && *str) {
1856
1857
1858
1859
1860 if (isspace(*fmt)) {
1861 fmt = skip_spaces(++fmt);
1862 str = skip_spaces(str);
1863 }
1864
1865
1866 if (*fmt != '%' && *fmt) {
1867 if (*fmt++ != *str++)
1868 break;
1869 continue;
1870 }
1871
1872 if (!*fmt)
1873 break;
1874 ++fmt;
1875
1876
1877
1878
1879 if (*fmt == '*') {
1880 while (!isspace(*fmt) && *fmt != '%' && *fmt)
1881 fmt++;
1882 while (!isspace(*str) && *str)
1883 str++;
1884 continue;
1885 }
1886
1887
1888 field_width = -1;
1889 if (isdigit(*fmt))
1890 field_width = skip_atoi(&fmt);
1891
1892
1893 qualifier = -1;
1894 if (*fmt == 'h' || TOLOWER(*fmt) == 'l' ||
1895 TOLOWER(*fmt) == 'z') {
1896 qualifier = *fmt++;
1897 if (unlikely(qualifier == *fmt)) {
1898 if (qualifier == 'h') {
1899 qualifier = 'H';
1900 fmt++;
1901 } else if (qualifier == 'l') {
1902 qualifier = 'L';
1903 fmt++;
1904 }
1905 }
1906 }
1907
1908 if (!*fmt || !*str)
1909 break;
1910
1911 base = 10;
1912 is_sign = 0;
1913
1914 switch (*fmt++) {
1915 case 'c':
1916 {
1917 char *s = (char *)va_arg(args, char*);
1918 if (field_width == -1)
1919 field_width = 1;
1920 do {
1921 *s++ = *str++;
1922 } while (--field_width > 0 && *str);
1923 num++;
1924 }
1925 continue;
1926 case 's':
1927 {
1928 char *s = (char *)va_arg(args, char *);
1929 if (field_width == -1)
1930 field_width = INT_MAX;
1931
1932 str = skip_spaces(str);
1933
1934
1935 while (*str && !isspace(*str) && field_width--)
1936 *s++ = *str++;
1937 *s = '\0';
1938 num++;
1939 }
1940 continue;
1941 case 'n':
1942
1943 {
1944 int *i = (int *)va_arg(args, int*);
1945 *i = str - buf;
1946 }
1947 continue;
1948 case 'o':
1949 base = 8;
1950 break;
1951 case 'x':
1952 case 'X':
1953 base = 16;
1954 break;
1955 case 'i':
1956 base = 0;
1957 case 'd':
1958 is_sign = 1;
1959 case 'u':
1960 break;
1961 case '%':
1962
1963 if (*str++ != '%')
1964 return num;
1965 continue;
1966 default:
1967
1968 return num;
1969 }
1970
1971
1972
1973
1974 str = skip_spaces(str);
1975
1976 digit = *str;
1977 if (is_sign && digit == '-')
1978 digit = *(str + 1);
1979
1980 if (!digit
1981 || (base == 16 && !isxdigit(digit))
1982 || (base == 10 && !isdigit(digit))
1983 || (base == 8 && (!isdigit(digit) || digit > '7'))
1984 || (base == 0 && !isdigit(digit)))
1985 break;
1986
1987 switch (qualifier) {
1988 case 'H': /* that's 'hh' in format */
1989 if (is_sign) {
1990 signed char *s = (signed char *)va_arg(args, signed char *);
1991 *s = (signed char)simple_strtol(str, &next, base);
1992 } else {
1993 unsigned char *s = (unsigned char *)va_arg(args, unsigned char *);
1994 *s = (unsigned char)simple_strtoul(str, &next, base);
1995 }
1996 break;
1997 case 'h':
1998 if (is_sign) {
1999 short *s = (short *)va_arg(args, short *);
2000 *s = (short)simple_strtol(str, &next, base);
2001 } else {
2002 unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
2003 *s = (unsigned short)simple_strtoul(str, &next, base);
2004 }
2005 break;
2006 case 'l':
2007 if (is_sign) {
2008 long *l = (long *)va_arg(args, long *);
2009 *l = simple_strtol(str, &next, base);
2010 } else {
2011 unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
2012 *l = simple_strtoul(str, &next, base);
2013 }
2014 break;
2015 case 'L':
2016 if (is_sign) {
2017 long long *l = (long long *)va_arg(args, long long *);
2018 *l = simple_strtoll(str, &next, base);
2019 } else {
2020 unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
2021 *l = simple_strtoull(str, &next, base);
2022 }
2023 break;
2024 case 'Z':
2025 case 'z':
2026 {
2027 size_t *s = (size_t *)va_arg(args, size_t *);
2028 *s = (size_t)simple_strtoul(str, &next, base);
2029 }
2030 break;
2031 default:
2032 if (is_sign) {
2033 int *i = (int *)va_arg(args, int *);
2034 *i = (int)simple_strtol(str, &next, base);
2035 } else {
2036 unsigned int *i = (unsigned int *)va_arg(args, unsigned int*);
2037 *i = (unsigned int)simple_strtoul(str, &next, base);
2038 }
2039 break;
2040 }
2041 num++;
2042
2043 if (!next)
2044 break;
2045 str = next;
2046 }
2047
2048
2049
2050
2051
2052
2053 if (*fmt == '%' && *(fmt + 1) == 'n') {
2054 int *p = (int *)va_arg(args, int *);
2055 *p = str - buf;
2056 }
2057
2058 return num;
2059}
2060EXPORT_SYMBOL(vsscanf);
2061
2062
2063
2064
2065
2066
2067
2068int sscanf(const char *buf, const char *fmt, ...)
2069{
2070 va_list args;
2071 int i;
2072
2073 va_start(args, fmt);
2074 i = vsscanf(buf, fmt, args);
2075 va_end(args);
2076
2077 return i;
2078}
2079EXPORT_SYMBOL(sscanf);
2080