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