3 @@ -170,6 +170,8 @@ int strict_strtoul(const char *cp, unsig
6 val = simple_strtoul(cp, &tail, base);
10 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
12 @@ -241,6 +243,8 @@ int strict_strtoull(const char *cp, unsi
15 val = simple_strtoull(cp, &tail, base);
18 if ((*tail == '\0') ||
19 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
21 @@ -392,7 +396,38 @@ static noinline char* put_dec(char *buf,
22 #define SMALL 32 /* Must be 32 == 0x20 */
23 #define SPECIAL 64 /* 0x */
25 -static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
27 + FORMAT_TYPE_NONE, /* Just a string part */
29 + FORMAT_TYPE_PRECISION,
33 + FORMAT_TYPE_PERCENT_CHAR,
34 + FORMAT_TYPE_INVALID,
35 + FORMAT_TYPE_LONG_LONG,
42 + FORMAT_TYPE_NRCHARS,
48 + enum format_type type;
49 + int flags; /* flags to number() */
50 + int field_width; /* width of output field */
52 + int precision; /* # of digits/chars */
56 +static char *number(char *buf, char *end, unsigned long long num,
57 + struct printf_spec spec)
59 /* we are called with base 8, 10 or 16, only, thus don't need "G..." */
60 static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
61 @@ -400,32 +435,32 @@ static char *number(char *buf, char *end
65 - int need_pfx = ((type & SPECIAL) && base != 10);
66 + int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
69 /* locase = 0 or 0x20. ORing digits or letters with 'locase'
70 * produces same digits or (maybe lowercased) letters */
71 - locase = (type & SMALL);
74 + locase = (spec.flags & SMALL);
75 + if (spec.flags & LEFT)
76 + spec.flags &= ~ZEROPAD;
79 + if (spec.flags & SIGN) {
80 if ((signed long long) num < 0) {
82 num = - (signed long long) num;
84 - } else if (type & PLUS) {
86 + } else if (spec.flags & PLUS) {
89 - } else if (type & SPACE) {
91 + } else if (spec.flags & SPACE) {
101 + spec.field_width--;
102 + if (spec.base == 16)
103 + spec.field_width--;
106 /* generate full string in tmp[], in reverse order */
107 @@ -437,10 +472,10 @@ static char *number(char *buf, char *end
108 tmp[i++] = (digits[do_div(num,base)] | locase);
111 - else if (base != 10) { /* 8 or 16 */
112 - int mask = base - 1;
113 + else if (spec.base != 10) { /* 8 or 16 */
114 + int mask = spec.base - 1;
116 - if (base == 16) shift = 4;
117 + if (spec.base == 16) shift = 4;
119 tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
121 @@ -450,12 +485,12 @@ static char *number(char *buf, char *end
124 /* printing 100 using %2d gives "100", not "00" */
127 + if (i > spec.precision)
128 + spec.precision = i;
129 /* leading space padding */
131 - if (!(type & (ZEROPAD+LEFT))) {
132 - while(--size >= 0) {
133 + spec.field_width -= spec.precision;
134 + if (!(spec.flags & (ZEROPAD+LEFT))) {
135 + while(--spec.field_width >= 0) {
139 @@ -472,23 +507,23 @@ static char *number(char *buf, char *end
144 + if (spec.base == 16) {
146 *buf = ('X' | locase);
150 /* zero or space padding */
151 - if (!(type & LEFT)) {
152 - char c = (type & ZEROPAD) ? '0' : ' ';
153 - while (--size >= 0) {
154 + if (!(spec.flags & LEFT)) {
155 + char c = (spec.flags & ZEROPAD) ? '0' : ' ';
156 + while (--spec.field_width >= 0) {
162 /* hmm even more zero padding? */
163 - while (i <= --precision) {
164 + while (i <= --spec.precision) {
168 @@ -500,7 +535,7 @@ static char *number(char *buf, char *end
171 /* trailing space padding */
172 - while (--size >= 0) {
173 + while (--spec.field_width >= 0) {
177 @@ -508,17 +543,17 @@ static char *number(char *buf, char *end
181 -static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags)
182 +static char *string(char *buf, char *end, char *s, struct printf_spec spec)
186 if ((unsigned long)s < PAGE_SIZE)
189 - len = strnlen(s, precision);
190 + len = strnlen(s, spec.precision);
192 - if (!(flags & LEFT)) {
193 - while (len < field_width--) {
194 + if (!(spec.flags & LEFT)) {
195 + while (len < spec.field_width--) {
199 @@ -529,7 +564,7 @@ static char *string(char *buf, char *end
203 - while (len < field_width--) {
204 + while (len < spec.field_width--) {
208 @@ -537,21 +572,24 @@ static char *string(char *buf, char *end
212 -static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags)
213 +static char *symbol_string(char *buf, char *end, void *ptr,
214 + struct printf_spec spec)
216 unsigned long value = (unsigned long) ptr;
217 #ifdef CONFIG_KALLSYMS
218 char sym[KSYM_SYMBOL_LEN];
219 sprint_symbol(sym, value);
220 - return string(buf, end, sym, field_width, precision, flags);
221 + return string(buf, end, sym, spec);
223 - field_width = 2*sizeof(void *);
224 - flags |= SPECIAL | SMALL | ZEROPAD;
225 - return number(buf, end, value, 16, field_width, precision, flags);
226 + spec.field_width = 2*sizeof(void *);
227 + spec.flags |= SPECIAL | SMALL | ZEROPAD;
229 + return number(buf, end, value, spec);
233 -static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags)
234 +static char *resource_string(char *buf, char *end, struct resource *res,
235 + struct printf_spec spec)
237 #ifndef IO_RSRC_PRINTK_SIZE
238 #define IO_RSRC_PRINTK_SIZE 4
239 @@ -560,7 +598,11 @@ static char *resource_string(char *buf,
240 #ifndef MEM_RSRC_PRINTK_SIZE
241 #define MEM_RSRC_PRINTK_SIZE 8
244 + struct printf_spec num_spec = {
247 + .flags = SPECIAL | SMALL | ZEROPAD,
249 /* room for the actual numbers, the two "0x", -, [, ] and the final zero */
250 char sym[4*sizeof(resource_size_t) + 8];
251 char *p = sym, *pend = sym + sizeof(sym);
252 @@ -572,13 +614,73 @@ static char *resource_string(char *buf,
253 size = MEM_RSRC_PRINTK_SIZE;
256 - p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
257 + num_spec.field_width = size;
258 + p = number(p, pend, res->start, num_spec);
260 - p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
261 + p = number(p, pend, res->end, num_spec);
265 - return string(buf, end, sym, field_width, precision, flags);
266 + return string(buf, end, sym, spec);
269 +static char *mac_address_string(char *buf, char *end, u8 *addr,
270 + struct printf_spec spec)
272 + char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
273 + char *p = mac_addr;
276 + for (i = 0; i < 6; i++) {
277 + p = pack_hex_byte(p, addr[i]);
278 + if (!(spec.flags & SPECIAL) && i != 5)
282 + spec.flags &= ~SPECIAL;
284 + return string(buf, end, mac_addr, spec);
287 +static char *ip6_addr_string(char *buf, char *end, u8 *addr,
288 + struct printf_spec spec)
290 + char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
291 + char *p = ip6_addr;
294 + for (i = 0; i < 8; i++) {
295 + p = pack_hex_byte(p, addr[2 * i]);
296 + p = pack_hex_byte(p, addr[2 * i + 1]);
297 + if (!(spec.flags & SPECIAL) && i != 7)
301 + spec.flags &= ~SPECIAL;
303 + return string(buf, end, ip6_addr, spec);
306 +static char *ip4_addr_string(char *buf, char *end, u8 *addr,
307 + struct printf_spec spec)
309 + char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
310 + char temp[3]; /* hold each IP quad in reverse order */
311 + char *p = ip4_addr;
314 + for (i = 0; i < 4; i++) {
315 + digits = put_dec_trunc(temp, addr[i]) - temp;
316 + /* reverse the digits in the quad */
318 + *p++ = temp[digits];
323 + spec.flags &= ~SPECIAL;
325 + return string(buf, end, ip4_addr, spec);
329 @@ -592,28 +694,244 @@ static char *resource_string(char *buf,
330 * - 'S' For symbolic direct pointers
331 * - 'R' For a struct resource pointer, it prints the range of
332 * addresses (not the name nor the flags)
333 + * - 'M' For a 6-byte MAC address, it prints the address in the
334 + * usual colon-separated hex notation
335 + * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
336 + * decimal for v4 and colon separated network-order 16 bit hex for v6)
337 + * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
338 + * currently the same
340 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
341 * function pointers are really function descriptors, which contain a
342 * pointer to the real address.
344 -static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
345 +static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
346 + struct printf_spec spec)
349 + return string(buf, end, "(null)", spec);
353 ptr = dereference_function_descriptor(ptr);
356 - return symbol_string(buf, end, ptr, field_width, precision, flags);
357 + return symbol_string(buf, end, ptr, spec);
359 - return resource_string(buf, end, ptr, field_width, precision, flags);
360 + return resource_string(buf, end, ptr, spec);
362 + spec.flags |= SPECIAL;
365 + return mac_address_string(buf, end, ptr, spec);
367 + spec.flags |= SPECIAL;
371 + return ip6_addr_string(buf, end, ptr, spec);
373 + return ip4_addr_string(buf, end, ptr, spec);
374 + spec.flags &= ~SPECIAL;
378 - if (field_width == -1) {
379 - field_width = 2*sizeof(void *);
381 + spec.flags |= SMALL;
382 + if (spec.field_width == -1) {
383 + spec.field_width = 2*sizeof(void *);
384 + spec.flags |= ZEROPAD;
386 - return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags);
389 + return number(buf, end, (unsigned long) ptr, spec);
393 + * Helper function to decode printf style format.
394 + * Each call decode a token from the format and return the
395 + * number of characters read (or likely the delta where it wants
396 + * to go on the next call).
397 + * The decoded token is returned through the parameters
399 + * 'h', 'l', or 'L' for integer fields
400 + * 'z' support added 23/7/1999 S.H.
401 + * 'z' changed to 'Z' --davidm 1/25/99
402 + * 't' added for ptrdiff_t
404 + * @fmt: the format string
405 + * @type of the token returned
406 + * @flags: various flags such as +, -, # tokens..
407 + * @field_width: overwritten width
408 + * @base: base of the number (octal, hex, ...)
409 + * @precision: precision of a number
410 + * @qualifier: qualifier of a number (long, size_t, ...)
412 +static int format_decode(const char *fmt, struct printf_spec *spec)
414 + const char *start = fmt;
416 + /* we finished early by reading the field width */
417 + if (spec->type == FORMAT_TYPE_WIDTH) {
418 + if (spec->field_width < 0) {
419 + spec->field_width = -spec->field_width;
420 + spec->flags |= LEFT;
422 + spec->type = FORMAT_TYPE_NONE;
426 + /* we finished early by reading the precision */
427 + if (spec->type == FORMAT_TYPE_PRECISION) {
428 + if (spec->precision < 0)
429 + spec->precision = 0;
431 + spec->type = FORMAT_TYPE_NONE;
436 + spec->type = FORMAT_TYPE_NONE;
438 + for (; *fmt ; ++fmt) {
443 + /* Return the current non-format string */
444 + if (fmt != start || !*fmt)
445 + return fmt - start;
447 + /* Process flags */
450 + while (1) { /* this also skips first '%' */
456 + case '-': spec->flags |= LEFT; break;
457 + case '+': spec->flags |= PLUS; break;
458 + case ' ': spec->flags |= SPACE; break;
459 + case '#': spec->flags |= SPECIAL; break;
460 + case '0': spec->flags |= ZEROPAD; break;
461 + default: found = false;
468 + /* get field width */
469 + spec->field_width = -1;
472 + spec->field_width = skip_atoi(&fmt);
473 + else if (*fmt == '*') {
474 + /* it's the next argument */
475 + spec->type = FORMAT_TYPE_WIDTH;
476 + return ++fmt - start;
480 + /* get the precision */
481 + spec->precision = -1;
484 + if (isdigit(*fmt)) {
485 + spec->precision = skip_atoi(&fmt);
486 + if (spec->precision < 0)
487 + spec->precision = 0;
488 + } else if (*fmt == '*') {
489 + /* it's the next argument */
490 + spec->type = FORMAT_TYPE_PRECISION;
491 + return ++fmt - start;
496 + /* get the conversion qualifier */
497 + spec->qualifier = -1;
498 + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
499 + *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
500 + spec->qualifier = *fmt;
502 + if (spec->qualifier == 'l' && *fmt == 'l') {
503 + spec->qualifier = 'L';
512 + spec->type = FORMAT_TYPE_CHAR;
513 + return ++fmt - start;
516 + spec->type = FORMAT_TYPE_STR;
517 + return ++fmt - start;
520 + spec->type = FORMAT_TYPE_PTR;
521 + return fmt - start;
525 + spec->type = FORMAT_TYPE_NRCHARS;
526 + return ++fmt - start;
529 + spec->type = FORMAT_TYPE_PERCENT_CHAR;
530 + return ++fmt - start;
532 + /* integer number formats - set up the flags and "break" */
538 + spec->flags |= SMALL;
546 + spec->flags |= SIGN;
551 + spec->type = FORMAT_TYPE_INVALID;
552 + return fmt - start;
555 + if (spec->qualifier == 'L')
556 + spec->type = FORMAT_TYPE_LONG_LONG;
557 + else if (spec->qualifier == 'l') {
558 + if (spec->flags & SIGN)
559 + spec->type = FORMAT_TYPE_LONG;
561 + spec->type = FORMAT_TYPE_ULONG;
562 + } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') {
563 + spec->type = FORMAT_TYPE_SIZE_T;
564 + } else if (spec->qualifier == 't') {
565 + spec->type = FORMAT_TYPE_PTRDIFF;
566 + } else if (spec->qualifier == 'h') {
567 + if (spec->flags & SIGN)
568 + spec->type = FORMAT_TYPE_SHORT;
570 + spec->type = FORMAT_TYPE_USHORT;
572 + if (spec->flags & SIGN)
573 + spec->type = FORMAT_TYPE_INT;
575 + spec->type = FORMAT_TYPE_UINT;
578 + return ++fmt - start;
582 @@ -642,18 +960,9 @@ static char *pointer(const char *fmt, ch
583 int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
585 unsigned long long num;
589 - int flags; /* flags to number() */
591 - int field_width; /* width of output field */
592 - int precision; /* min. # of digits for integers; max
593 - number of chars for from string */
594 - int qualifier; /* 'h', 'l', or 'L' for integer fields */
595 - /* 'z' support added 23/7/1999 S.H. */
596 - /* 'z' changed to 'Z' --davidm 1/25/99 */
597 - /* 't' added for ptrdiff_t */
599 + struct printf_spec spec = {0};
601 /* Reject out-of-range values early. Large positive sizes are
602 used for unknown buffer sizes. */
603 @@ -674,184 +983,137 @@ int vsnprintf(char *buf, size_t size, co
607 - for (; *fmt ; ++fmt) {
615 + const char *old_fmt = fmt;
617 - /* process flags */
620 - ++fmt; /* this also skips first '%' */
622 - case '-': flags |= LEFT; goto repeat;
623 - case '+': flags |= PLUS; goto repeat;
624 - case ' ': flags |= SPACE; goto repeat;
625 - case '#': flags |= SPECIAL; goto repeat;
626 - case '0': flags |= ZEROPAD; goto repeat;
628 + read = format_decode(fmt, &spec);
630 - /* get field width */
633 - field_width = skip_atoi(&fmt);
634 - else if (*fmt == '*') {
636 - /* it's the next argument */
637 - field_width = va_arg(args, int);
638 - if (field_width < 0) {
639 - field_width = -field_width;
645 - /* get the precision */
650 - precision = skip_atoi(&fmt);
651 - else if (*fmt == '*') {
653 - /* it's the next argument */
654 - precision = va_arg(args, int);
655 + switch (spec.type) {
656 + case FORMAT_TYPE_NONE: {
659 + if (copy > end - str)
661 + memcpy(str, old_fmt, copy);
669 - /* get the conversion qualifier */
671 - if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
672 - *fmt =='Z' || *fmt == 'z' || *fmt == 't') {
675 - if (qualifier == 'l' && *fmt == 'l') {
680 + case FORMAT_TYPE_WIDTH:
681 + spec.field_width = va_arg(args, int);
686 + case FORMAT_TYPE_PRECISION:
687 + spec.precision = va_arg(args, int);
692 - if (!(flags & LEFT)) {
693 - while (--field_width > 0) {
699 - c = (unsigned char) va_arg(args, int);
703 - while (--field_width > 0) {
704 + case FORMAT_TYPE_CHAR:
705 + if (!(spec.flags & LEFT)) {
706 + while (--spec.field_width > 0) {
714 - str = string(str, end, va_arg(args, char *), field_width, precision, flags);
718 - str = pointer(fmt+1, str, end,
719 - va_arg(args, void *),
720 - field_width, precision, flags);
721 - /* Skip all alphanumeric pointer suffixes */
722 - while (isalnum(fmt[1]))
728 - * What does C99 say about the overflow case here? */
729 - if (qualifier == 'l') {
730 - long * ip = va_arg(args, long *);
732 - } else if (qualifier == 'Z' || qualifier == 'z') {
733 - size_t * ip = va_arg(args, size_t *);
736 - int * ip = va_arg(args, int *);
743 + c = (unsigned char) va_arg(args, int);
747 + while (--spec.field_width > 0) {
756 - /* integer number formats - set up the flags and "break" */
760 + case FORMAT_TYPE_STR:
761 + str = string(str, end, va_arg(args, char *), spec);
769 + case FORMAT_TYPE_PTR:
770 + str = pointer(fmt+1, str, end, va_arg(args, void *),
772 + while (isalnum(*fmt))
781 + case FORMAT_TYPE_PERCENT_CHAR:
799 + case FORMAT_TYPE_INVALID:
805 + case FORMAT_TYPE_NRCHARS: {
806 + int qualifier = spec.qualifier;
808 + if (qualifier == 'l') {
809 + long *ip = va_arg(args, long *);
811 + } else if (qualifier == 'Z' ||
812 + qualifier == 'z') {
813 + size_t *ip = va_arg(args, size_t *);
816 + int *ip = va_arg(args, int *);
821 - if (qualifier == 'L')
822 - num = va_arg(args, long long);
823 - else if (qualifier == 'l') {
824 - num = va_arg(args, unsigned long);
826 - num = (signed long) num;
827 - } else if (qualifier == 'Z' || qualifier == 'z') {
828 - num = va_arg(args, size_t);
829 - } else if (qualifier == 't') {
830 - num = va_arg(args, ptrdiff_t);
831 - } else if (qualifier == 'h') {
832 - num = (unsigned short) va_arg(args, int);
834 - num = (signed short) num;
836 - num = va_arg(args, unsigned int);
838 - num = (signed int) num;
841 + switch (spec.type) {
842 + case FORMAT_TYPE_LONG_LONG:
843 + num = va_arg(args, long long);
845 + case FORMAT_TYPE_ULONG:
846 + num = va_arg(args, unsigned long);
848 + case FORMAT_TYPE_LONG:
849 + num = va_arg(args, long);
851 + case FORMAT_TYPE_SIZE_T:
852 + num = va_arg(args, size_t);
854 + case FORMAT_TYPE_PTRDIFF:
855 + num = va_arg(args, ptrdiff_t);
857 + case FORMAT_TYPE_USHORT:
858 + num = (unsigned short) va_arg(args, int);
860 + case FORMAT_TYPE_SHORT:
861 + num = (short) va_arg(args, int);
863 + case FORMAT_TYPE_INT:
864 + num = (int) va_arg(args, int);
867 + num = va_arg(args, unsigned int);
870 + str = number(str, end, num, spec);
872 - str = number(str, end, num, base,
873 - field_width, precision, flags);
883 /* the trailing null byte doesn't count towards the total */
887 EXPORT_SYMBOL(vsnprintf);