Blame view

lib/vsprintf.c 47.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   *  linux/lib/vsprintf.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
  
  /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
  /*
   * Wirzenius wrote this portably, Torvalds fucked it up :-)
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
11
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
20
21
22
23
   * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
   * - changed to provide snprintf and vsnprintf functions
   * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
   * - scnprintf and vscnprintf
   */
  
  #include <stdarg.h>
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/ctype.h>
  #include <linux/kernel.h>
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
24
25
  #include <linux/kallsyms.h>
  #include <linux/uaccess.h>
332d2e783   Linus Torvalds   Implement %pR to ...
26
  #include <linux/ioport.h>
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
27
  #include <net/addrconf.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

4e57b6817   Tim Schmielau   [PATCH] fix missi...
29
  #include <asm/page.h>		/* for PAGE_SIZE */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  #include <asm/div64.h>
deac93df2   James Bottomley   lib: Correct prin...
31
  #include <asm/sections.h>	/* for dereference_function_descriptor() */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32

1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
33
  #include "kstrtox.h"
aa46a63ef   Harvey Harrison   lib: pull base-gu...
34

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  /**
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
36
   * simple_strtoull - convert a string to an unsigned long long
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
41
  unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  {
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
43
44
  	unsigned long long result;
  	unsigned int rv;
aa46a63ef   Harvey Harrison   lib: pull base-gu...
45

1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
46
47
48
49
  	cp = _parse_integer_fixup_radix(cp, &base);
  	rv = _parse_integer(cp, base, &result);
  	/* FIXME */
  	cp += (rv & ~KSTRTOX_OVERFLOW);
aa46a63ef   Harvey Harrison   lib: pull base-gu...
50

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  	if (endp)
  		*endp = (char *)cp;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
53

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  	return result;
  }
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
56
  EXPORT_SYMBOL(simple_strtoull);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
  
  /**
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
59
   * simple_strtoul - convert a string to an unsigned long
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
64
  unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  {
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
66
  	return simple_strtoull(cp, endp, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  }
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
68
  EXPORT_SYMBOL(simple_strtoul);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  
  /**
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
71
   * simple_strtol - convert a string to a signed long
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
76
  long simple_strtol(const char *cp, char **endp, unsigned int base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  {
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
78
79
  	if (*cp == '-')
  		return -simple_strtoul(cp + 1, endp, base);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
80

922ac25c9   André Goddard Rosa   vsprintf: reuse a...
81
  	return simple_strtoul(cp, endp, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  }
922ac25c9   André Goddard Rosa   vsprintf: reuse a...
83
  EXPORT_SYMBOL(simple_strtol);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
89
90
  
  /**
   * simple_strtoll - convert a string to a signed long long
   * @cp: The start of the string
   * @endp: A pointer to the end of the parsed string will be placed here
   * @base: The number base to use
   */
22d27051b   Harvey Harrison   lib: trivial whit...
91
  long long simple_strtoll(const char *cp, char **endp, unsigned int base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
93
  	if (*cp == '-')
22d27051b   Harvey Harrison   lib: trivial whit...
94
  		return -simple_strtoull(cp + 1, endp, base);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
95

22d27051b   Harvey Harrison   lib: trivial whit...
96
  	return simple_strtoull(cp, endp, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  }
98d5ce0d0   Hans Verkuil   lib/vsprintf.c: a...
98
  EXPORT_SYMBOL(simple_strtoll);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

cf3b429b0   Joe Perches   vsprintf.c: use n...
100
101
  static noinline_for_stack
  int skip_atoi(const char **s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
103
  	int i = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
  
  	while (isdigit(**s))
  		i = i*10 + *((*s)++) - '0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
107

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
109
  	return i;
  }
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
110
111
112
113
114
115
116
117
118
119
  /* Decimal conversion is by far the most typical, and is used
   * for /proc and /sys data. This directly impacts e.g. top performance
   * with many processes running. We optimize it for speed
   * using code from
   * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
   * (with permission from the author, Douglas W. Jones). */
  
  /* Formats correctly any integer in [0,99999].
   * Outputs from one to five digits depending on input.
   * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
cf3b429b0   Joe Perches   vsprintf.c: use n...
120
121
  static noinline_for_stack
  char *put_dec_trunc(char *buf, unsigned q)
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  {
  	unsigned d3, d2, d1, d0;
  	d1 = (q>>4) & 0xf;
  	d2 = (q>>8) & 0xf;
  	d3 = (q>>12);
  
  	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
  	q = (d0 * 0xcd) >> 11;
  	d0 = d0 - 10*q;
  	*buf++ = d0 + '0'; /* least significant digit */
  	d1 = q + 9*d3 + 5*d2 + d1;
  	if (d1 != 0) {
  		q = (d1 * 0xcd) >> 11;
  		d1 = d1 - 10*q;
  		*buf++ = d1 + '0'; /* next digit */
  
  		d2 = q + 2*d2;
  		if ((d2 != 0) || (d3 != 0)) {
  			q = (d2 * 0xd) >> 7;
  			d2 = d2 - 10*q;
  			*buf++ = d2 + '0'; /* next digit */
  
  			d3 = q + 4*d3;
  			if (d3 != 0) {
  				q = (d3 * 0xcd) >> 11;
  				d3 = d3 - 10*q;
  				*buf++ = d3 + '0';  /* next digit */
  				if (q != 0)
7b9186f5e   André Goddard Rosa   vsprintf: give it...
150
  					*buf++ = q + '0'; /* most sign. digit */
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
151
152
153
  			}
  		}
  	}
7b9186f5e   André Goddard Rosa   vsprintf: give it...
154

4277eedd7   Denis Vlasenko   vsprintf.c: optim...
155
156
157
  	return buf;
  }
  /* Same with if's removed. Always emits five digits */
cf3b429b0   Joe Perches   vsprintf.c: use n...
158
159
  static noinline_for_stack
  char *put_dec_full(char *buf, unsigned q)
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
160
161
162
163
164
165
166
  {
  	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
  	/* but anyway, gcc produces better code with full-sized ints */
  	unsigned d3, d2, d1, d0;
  	d1 = (q>>4) & 0xf;
  	d2 = (q>>8) & 0xf;
  	d3 = (q>>12);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
167
168
169
170
171
172
173
174
175
  	/*
  	 * Possible ways to approx. divide by 10
  	 * gcc -O2 replaces multiply with shifts and adds
  	 * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
  	 * (x * 0x67) >> 10:  1100111
  	 * (x * 0x34) >> 9:    110100 - same
  	 * (x * 0x1a) >> 8:     11010 - same
  	 * (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
  	 */
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
  	q = (d0 * 0xcd) >> 11;
  	d0 = d0 - 10*q;
  	*buf++ = d0 + '0';
  	d1 = q + 9*d3 + 5*d2 + d1;
  		q = (d1 * 0xcd) >> 11;
  		d1 = d1 - 10*q;
  		*buf++ = d1 + '0';
  
  		d2 = q + 2*d2;
  			q = (d2 * 0xd) >> 7;
  			d2 = d2 - 10*q;
  			*buf++ = d2 + '0';
  
  			d3 = q + 4*d3;
  				q = (d3 * 0xcd) >> 11; /* - shorter code */
  				/* q = (d3 * 0x67) >> 10; - would also work */
  				d3 = d3 - 10*q;
  				*buf++ = d3 + '0';
  					*buf++ = q + '0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
196

4277eedd7   Denis Vlasenko   vsprintf.c: optim...
197
198
199
  	return buf;
  }
  /* No inlining helps gcc to use registers better */
cf3b429b0   Joe Perches   vsprintf.c: use n...
200
201
  static noinline_for_stack
  char *put_dec(char *buf, unsigned long long num)
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
202
203
204
205
206
207
208
209
210
  {
  	while (1) {
  		unsigned rem;
  		if (num < 100000)
  			return put_dec_trunc(buf, num);
  		rem = do_div(num, 100000);
  		buf = put_dec_full(buf, rem);
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
  #define ZEROPAD	1		/* pad with zero */
  #define SIGN	2		/* unsigned/signed long */
  #define PLUS	4		/* show plus */
  #define SPACE	8		/* space if plus */
  #define LEFT	16		/* left justified */
b89dc5d6b   Bjorn Helgaas   vsprintf: clarify...
216
217
  #define SMALL	32		/* use lowercase in hex (must be 32 == 0x20) */
  #define SPECIAL	64		/* prefix hex with "0x", octal with "0" */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
219
220
  enum format_type {
  	FORMAT_TYPE_NONE, /* Just a string part */
ed681a91a   Vegard Nossum   vsprintf: unify t...
221
  	FORMAT_TYPE_WIDTH,
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
222
223
224
225
226
227
228
229
230
  	FORMAT_TYPE_PRECISION,
  	FORMAT_TYPE_CHAR,
  	FORMAT_TYPE_STR,
  	FORMAT_TYPE_PTR,
  	FORMAT_TYPE_PERCENT_CHAR,
  	FORMAT_TYPE_INVALID,
  	FORMAT_TYPE_LONG_LONG,
  	FORMAT_TYPE_ULONG,
  	FORMAT_TYPE_LONG,
a4e94ef0d   Zhaolei   printk: add suppo...
231
232
  	FORMAT_TYPE_UBYTE,
  	FORMAT_TYPE_BYTE,
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
233
234
235
236
237
238
239
240
241
242
  	FORMAT_TYPE_USHORT,
  	FORMAT_TYPE_SHORT,
  	FORMAT_TYPE_UINT,
  	FORMAT_TYPE_INT,
  	FORMAT_TYPE_NRCHARS,
  	FORMAT_TYPE_SIZE_T,
  	FORMAT_TYPE_PTRDIFF
  };
  
  struct printf_spec {
4e310fda9   Joe Perches   vsprintf: Change ...
243
  	u8	type;		/* format_type enum */
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
244
  	u8	flags;		/* flags to number() */
4e310fda9   Joe Perches   vsprintf: Change ...
245
246
247
248
  	u8	base;		/* number base, 8, 10 or 16 only */
  	u8	qualifier;	/* number qualifier, one of 'hHlLtzZ' */
  	s16	field_width;	/* width of output field */
  	s16	precision;	/* # of digits/chars */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
249
  };
cf3b429b0   Joe Perches   vsprintf.c: use n...
250
251
252
  static noinline_for_stack
  char *number(char *buf, char *end, unsigned long long num,
  	     struct printf_spec spec)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  {
9b706aee7   Denys Vlasenko   x86: trivial prin...
254
255
256
257
258
259
  	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
  	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
  
  	char tmp[66];
  	char sign;
  	char locase;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
260
  	int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
  	int i;
9b706aee7   Denys Vlasenko   x86: trivial prin...
262
263
  	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
  	 * produces same digits or (maybe lowercased) letters */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
264
265
266
  	locase = (spec.flags & SMALL);
  	if (spec.flags & LEFT)
  		spec.flags &= ~ZEROPAD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  	sign = 0;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
268
  	if (spec.flags & SIGN) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
269
  		if ((signed long long)num < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  			sign = '-';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
271
  			num = -(signed long long)num;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
272
273
  			spec.field_width--;
  		} else if (spec.flags & PLUS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
  			sign = '+';
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
275
276
  			spec.field_width--;
  		} else if (spec.flags & SPACE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  			sign = ' ';
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
278
  			spec.field_width--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
281
  	if (need_pfx) {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
282
283
284
  		spec.field_width--;
  		if (spec.base == 16)
  			spec.field_width--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
286
287
  
  	/* generate full string in tmp[], in reverse order */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
289
  	i = 0;
  	if (num == 0)
b39a73409   Denis Vlasenko   vsprintf.c: optim...
290
  		tmp[i++] = '0';
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
291
292
  	/* Generic code, for any base:
  	else do {
9b706aee7   Denys Vlasenko   x86: trivial prin...
293
  		tmp[i++] = (digits[do_div(num,base)] | locase);
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
294
295
  	} while (num != 0);
  	*/
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
296
297
  	else if (spec.base != 10) { /* 8 or 16 */
  		int mask = spec.base - 1;
b39a73409   Denis Vlasenko   vsprintf.c: optim...
298
  		int shift = 3;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
299
300
301
  
  		if (spec.base == 16)
  			shift = 4;
b39a73409   Denis Vlasenko   vsprintf.c: optim...
302
  		do {
9b706aee7   Denys Vlasenko   x86: trivial prin...
303
  			tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
b39a73409   Denis Vlasenko   vsprintf.c: optim...
304
305
  			num >>= shift;
  		} while (num);
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
306
307
308
  	} else { /* base 10 */
  		i = put_dec(tmp, num) - tmp;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
309
310
  
  	/* printing 100 using %2d gives "100", not "00" */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
311
312
  	if (i > spec.precision)
  		spec.precision = i;
b39a73409   Denis Vlasenko   vsprintf.c: optim...
313
  	/* leading space padding */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
314
315
  	spec.field_width -= spec.precision;
  	if (!(spec.flags & (ZEROPAD+LEFT))) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
316
  		while (--spec.field_width >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
317
  			if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
  				*buf = ' ';
  			++buf;
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
322
  	/* sign */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	if (sign) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
324
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
  			*buf = sign;
  		++buf;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
328
329
330
331
332
  	/* "0x" / "0" prefix */
  	if (need_pfx) {
  		if (buf < end)
  			*buf = '0';
  		++buf;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
333
  		if (spec.base == 16) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
334
  			if (buf < end)
9b706aee7   Denys Vlasenko   x86: trivial prin...
335
  				*buf = ('X' | locase);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
  			++buf;
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
339
  	/* zero or space padding */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
340
341
342
  	if (!(spec.flags & LEFT)) {
  		char c = (spec.flags & ZEROPAD) ? '0' : ' ';
  		while (--spec.field_width >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
343
  			if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
346
347
  				*buf = c;
  			++buf;
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
348
  	/* hmm even more zero padding? */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
349
  	while (i <= --spec.precision) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
350
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
  			*buf = '0';
  		++buf;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
354
355
  	/* actual digits of result */
  	while (--i >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
356
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
359
  			*buf = tmp[i];
  		++buf;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
360
  	/* trailing space padding */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
361
  	while (--spec.field_width >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
362
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
  			*buf = ' ';
  		++buf;
  	}
7b9186f5e   André Goddard Rosa   vsprintf: give it...
366

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
  	return buf;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
369
370
  static noinline_for_stack
  char *string(char *buf, char *end, const char *s, struct printf_spec spec)
0f9bfa569   Linus Torvalds   vsprintf: split o...
371
372
373
374
  {
  	int len, i;
  
  	if ((unsigned long)s < PAGE_SIZE)
0f4f81dce   André Goddard Rosa   vsprintf: factori...
375
  		s = "(null)";
0f9bfa569   Linus Torvalds   vsprintf: split o...
376

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
377
  	len = strnlen(s, spec.precision);
0f9bfa569   Linus Torvalds   vsprintf: split o...
378

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
379
380
  	if (!(spec.flags & LEFT)) {
  		while (len < spec.field_width--) {
0f9bfa569   Linus Torvalds   vsprintf: split o...
381
382
383
384
385
386
387
388
389
390
  			if (buf < end)
  				*buf = ' ';
  			++buf;
  		}
  	}
  	for (i = 0; i < len; ++i) {
  		if (buf < end)
  			*buf = *s;
  		++buf; ++s;
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
391
  	while (len < spec.field_width--) {
0f9bfa569   Linus Torvalds   vsprintf: split o...
392
393
394
395
  		if (buf < end)
  			*buf = ' ';
  		++buf;
  	}
7b9186f5e   André Goddard Rosa   vsprintf: give it...
396

0f9bfa569   Linus Torvalds   vsprintf: split o...
397
398
  	return buf;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
399
400
401
  static noinline_for_stack
  char *symbol_string(char *buf, char *end, void *ptr,
  		    struct printf_spec spec, char ext)
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
402
403
404
405
  {
  	unsigned long value = (unsigned long) ptr;
  #ifdef CONFIG_KALLSYMS
  	char sym[KSYM_SYMBOL_LEN];
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
406
407
408
  	if (ext == 'B')
  		sprint_backtrace(sym, value);
  	else if (ext != 'f' && ext != 's')
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
409
410
411
  		sprint_symbol(sym, value);
  	else
  		kallsyms_lookup(value, NULL, NULL, NULL, sym);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
412

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
413
  	return string(buf, end, sym, spec);
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
414
  #else
7b9186f5e   André Goddard Rosa   vsprintf: give it...
415
  	spec.field_width = 2 * sizeof(void *);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
416
417
  	spec.flags |= SPECIAL | SMALL | ZEROPAD;
  	spec.base = 16;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
418

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
419
  	return number(buf, end, value, spec);
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
420
421
  #endif
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
422
423
424
  static noinline_for_stack
  char *resource_string(char *buf, char *end, struct resource *res,
  		      struct printf_spec spec, const char *fmt)
332d2e783   Linus Torvalds   Implement %pR to ...
425
426
  {
  #ifndef IO_RSRC_PRINTK_SIZE
284053722   Bjorn Helgaas   vsprintf: fix io/...
427
  #define IO_RSRC_PRINTK_SIZE	6
332d2e783   Linus Torvalds   Implement %pR to ...
428
429
430
  #endif
  
  #ifndef MEM_RSRC_PRINTK_SIZE
284053722   Bjorn Helgaas   vsprintf: fix io/...
431
  #define MEM_RSRC_PRINTK_SIZE	10
332d2e783   Linus Torvalds   Implement %pR to ...
432
  #endif
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
433
  	static const struct printf_spec io_spec = {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
434
  		.base = 16,
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
435
  		.field_width = IO_RSRC_PRINTK_SIZE,
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
436
437
438
  		.precision = -1,
  		.flags = SPECIAL | SMALL | ZEROPAD,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
439
440
441
442
443
444
  	static const struct printf_spec mem_spec = {
  		.base = 16,
  		.field_width = MEM_RSRC_PRINTK_SIZE,
  		.precision = -1,
  		.flags = SPECIAL | SMALL | ZEROPAD,
  	};
0f4050c7d   Bjorn Helgaas   resource: add bus...
445
446
447
448
449
450
  	static const struct printf_spec bus_spec = {
  		.base = 16,
  		.field_width = 2,
  		.precision = -1,
  		.flags = SMALL | ZEROPAD,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
451
  	static const struct printf_spec dec_spec = {
c91d3376e   Bjorn Helgaas   vsprintf: add %pR...
452
453
454
455
  		.base = 10,
  		.precision = -1,
  		.flags = 0,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
456
  	static const struct printf_spec str_spec = {
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
457
458
459
460
  		.field_width = -1,
  		.precision = 10,
  		.flags = LEFT,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
461
  	static const struct printf_spec flag_spec = {
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
462
463
464
465
  		.base = 16,
  		.precision = -1,
  		.flags = SPECIAL | SMALL,
  	};
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
466
467
468
469
470
  
  	/* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8)
  	 * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */
  #define RSRC_BUF_SIZE		((2 * sizeof(resource_size_t)) + 4)
  #define FLAG_BUF_SIZE		(2 * sizeof(res->flags))
9d7cca042   Bjorn Helgaas   resource: add win...
471
  #define DECODED_BUF_SIZE	sizeof("[mem - 64bit pref window disabled]")
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
472
473
474
  #define RAW_BUF_SIZE		sizeof("[mem - flags 0x]")
  	char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
  		     2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
332d2e783   Linus Torvalds   Implement %pR to ...
475
  	char *p = sym, *pend = sym + sizeof(sym);
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
476
  	int decode = (fmt[0] == 'R') ? 1 : 0;
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
477
  	const struct printf_spec *specp;
332d2e783   Linus Torvalds   Implement %pR to ...
478
479
  
  	*p++ = '[';
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
480
  	if (res->flags & IORESOURCE_IO) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
481
  		p = string(p, pend, "io  ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
482
483
  		specp = &io_spec;
  	} else if (res->flags & IORESOURCE_MEM) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
484
  		p = string(p, pend, "mem ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
485
486
  		specp = &mem_spec;
  	} else if (res->flags & IORESOURCE_IRQ) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
487
  		p = string(p, pend, "irq ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
488
489
  		specp = &dec_spec;
  	} else if (res->flags & IORESOURCE_DMA) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
490
  		p = string(p, pend, "dma ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
491
  		specp = &dec_spec;
0f4050c7d   Bjorn Helgaas   resource: add bus...
492
493
494
  	} else if (res->flags & IORESOURCE_BUS) {
  		p = string(p, pend, "bus ", str_spec);
  		specp = &bus_spec;
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
495
  	} else {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
496
  		p = string(p, pend, "??? ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
497
  		specp = &mem_spec;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
498
  		decode = 0;
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
499
  	}
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
500
  	p = number(p, pend, res->start, *specp);
c91d3376e   Bjorn Helgaas   vsprintf: add %pR...
501
502
  	if (res->start != res->end) {
  		*p++ = '-';
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
503
  		p = number(p, pend, res->end, *specp);
c91d3376e   Bjorn Helgaas   vsprintf: add %pR...
504
  	}
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
505
  	if (decode) {
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
506
507
508
509
  		if (res->flags & IORESOURCE_MEM_64)
  			p = string(p, pend, " 64bit", str_spec);
  		if (res->flags & IORESOURCE_PREFETCH)
  			p = string(p, pend, " pref", str_spec);
9d7cca042   Bjorn Helgaas   resource: add win...
510
511
  		if (res->flags & IORESOURCE_WINDOW)
  			p = string(p, pend, " window", str_spec);
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
512
513
  		if (res->flags & IORESOURCE_DISABLED)
  			p = string(p, pend, " disabled", str_spec);
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
514
515
516
  	} else {
  		p = string(p, pend, " flags ", str_spec);
  		p = number(p, pend, res->flags, flag_spec);
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
517
  	}
332d2e783   Linus Torvalds   Implement %pR to ...
518
  	*p++ = ']';
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
519
  	*p = '\0';
332d2e783   Linus Torvalds   Implement %pR to ...
520

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
521
  	return string(buf, end, sym, spec);
332d2e783   Linus Torvalds   Implement %pR to ...
522
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
523
524
525
  static noinline_for_stack
  char *mac_address_string(char *buf, char *end, u8 *addr,
  			 struct printf_spec spec, const char *fmt)
dd45c9cf6   Harvey Harrison   printk: add %pM f...
526
  {
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
527
  	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
dd45c9cf6   Harvey Harrison   printk: add %pM f...
528
529
  	char *p = mac_addr;
  	int i;
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
530
531
532
  	char separator;
  
  	if (fmt[1] == 'F') {		/* FDDI canonical format */
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
533
534
  		separator = '-';
  	} else {
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
535
536
  		separator = ':';
  	}
dd45c9cf6   Harvey Harrison   printk: add %pM f...
537
538
  
  	for (i = 0; i < 6; i++) {
55036ba76   Andy Shevchenko   lib: rename pack_...
539
  		p = hex_byte_pack(p, addr[i]);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
540
  		if (fmt[0] == 'M' && i != 5)
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
541
  			*p++ = separator;
dd45c9cf6   Harvey Harrison   printk: add %pM f...
542
543
  	}
  	*p = '\0';
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
544
  	return string(buf, end, mac_addr, spec);
dd45c9cf6   Harvey Harrison   printk: add %pM f...
545
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
546
547
  static noinline_for_stack
  char *ip4_string(char *p, const u8 *addr, const char *fmt)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
548
549
  {
  	int i;
0159f24ee   Joe Perches   lib/vsprintf.c: A...
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  	bool leading_zeros = (fmt[0] == 'i');
  	int index;
  	int step;
  
  	switch (fmt[2]) {
  	case 'h':
  #ifdef __BIG_ENDIAN
  		index = 0;
  		step = 1;
  #else
  		index = 3;
  		step = -1;
  #endif
  		break;
  	case 'l':
  		index = 3;
  		step = -1;
  		break;
  	case 'n':
  	case 'b':
  	default:
  		index = 0;
  		step = 1;
  		break;
  	}
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
575
576
  	for (i = 0; i < 4; i++) {
  		char temp[3];	/* hold each IP quad in reverse order */
0159f24ee   Joe Perches   lib/vsprintf.c: A...
577
  		int digits = put_dec_trunc(temp, addr[index]) - temp;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
578
579
580
581
582
583
584
585
586
587
588
  		if (leading_zeros) {
  			if (digits < 3)
  				*p++ = '0';
  			if (digits < 2)
  				*p++ = '0';
  		}
  		/* reverse the digits in the quad */
  		while (digits--)
  			*p++ = temp[digits];
  		if (i < 3)
  			*p++ = '.';
0159f24ee   Joe Perches   lib/vsprintf.c: A...
589
  		index += step;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
590
  	}
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
591
  	*p = '\0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
592

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
593
594
  	return p;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
595
596
  static noinline_for_stack
  char *ip6_compressed_string(char *p, const char *addr)
689afa7da   Harvey Harrison   printk: add %p6 f...
597
  {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
598
  	int i, j, range;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
599
600
601
602
  	unsigned char zerolength[8];
  	int longest = 1;
  	int colonpos = -1;
  	u16 word;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
603
  	u8 hi, lo;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
604
  	bool needcolon = false;
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
605
606
607
608
609
610
  	bool useIPv4;
  	struct in6_addr in6;
  
  	memcpy(&in6, addr, sizeof(struct in6_addr));
  
  	useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
611
612
613
614
615
616
617
618
619
620
621
  
  	memset(zerolength, 0, sizeof(zerolength));
  
  	if (useIPv4)
  		range = 6;
  	else
  		range = 8;
  
  	/* find position of longest 0 run */
  	for (i = 0; i < range; i++) {
  		for (j = i; j < range; j++) {
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
622
  			if (in6.s6_addr16[j] != 0)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
623
624
625
626
627
628
629
630
631
632
  				break;
  			zerolength[i]++;
  		}
  	}
  	for (i = 0; i < range; i++) {
  		if (zerolength[i] > longest) {
  			longest = zerolength[i];
  			colonpos = i;
  		}
  	}
29cf519ee   Joe Perches   vsprintf: Update ...
633
634
  	if (longest == 1)		/* don't compress a single 0 */
  		colonpos = -1;
689afa7da   Harvey Harrison   printk: add %p6 f...
635

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  	/* emit address */
  	for (i = 0; i < range; i++) {
  		if (i == colonpos) {
  			if (needcolon || i == 0)
  				*p++ = ':';
  			*p++ = ':';
  			needcolon = false;
  			i += longest - 1;
  			continue;
  		}
  		if (needcolon) {
  			*p++ = ':';
  			needcolon = false;
  		}
  		/* hex u16 without leading 0s */
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
651
  		word = ntohs(in6.s6_addr16[i]);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
652
653
654
655
  		hi = word >> 8;
  		lo = word & 0xff;
  		if (hi) {
  			if (hi > 0x0f)
55036ba76   Andy Shevchenko   lib: rename pack_...
656
  				p = hex_byte_pack(p, hi);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
657
658
  			else
  				*p++ = hex_asc_lo(hi);
55036ba76   Andy Shevchenko   lib: rename pack_...
659
  			p = hex_byte_pack(p, lo);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
660
  		}
b5ff992b0   André Goddard Rosa   vsprintf: reduce ...
661
  		else if (lo > 0x0f)
55036ba76   Andy Shevchenko   lib: rename pack_...
662
  			p = hex_byte_pack(p, lo);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
663
664
665
666
667
668
669
670
  		else
  			*p++ = hex_asc_lo(lo);
  		needcolon = true;
  	}
  
  	if (useIPv4) {
  		if (needcolon)
  			*p++ = ':';
0159f24ee   Joe Perches   lib/vsprintf.c: A...
671
  		p = ip4_string(p, &in6.s6_addr[12], "I4");
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
672
  	}
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
673
  	*p = '\0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
674

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
675
676
  	return p;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
677
678
  static noinline_for_stack
  char *ip6_string(char *p, const char *addr, const char *fmt)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
679
680
  {
  	int i;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
681

689afa7da   Harvey Harrison   printk: add %p6 f...
682
  	for (i = 0; i < 8; i++) {
55036ba76   Andy Shevchenko   lib: rename pack_...
683
684
  		p = hex_byte_pack(p, *addr++);
  		p = hex_byte_pack(p, *addr++);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
685
  		if (fmt[0] == 'I' && i != 7)
689afa7da   Harvey Harrison   printk: add %p6 f...
686
687
688
  			*p++ = ':';
  	}
  	*p = '\0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
689

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
690
691
  	return p;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
692
693
694
  static noinline_for_stack
  char *ip6_addr_string(char *buf, char *end, const u8 *addr,
  		      struct printf_spec spec, const char *fmt)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
695
696
697
698
  {
  	char ip6_addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
  
  	if (fmt[0] == 'I' && fmt[2] == 'c')
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
699
  		ip6_compressed_string(ip6_addr, addr);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
700
  	else
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
701
  		ip6_string(ip6_addr, addr, fmt);
689afa7da   Harvey Harrison   printk: add %p6 f...
702

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
703
  	return string(buf, end, ip6_addr, spec);
689afa7da   Harvey Harrison   printk: add %p6 f...
704
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
705
706
707
  static noinline_for_stack
  char *ip4_addr_string(char *buf, char *end, const u8 *addr,
  		      struct printf_spec spec, const char *fmt)
4aa996066   Harvey Harrison   printk: add %I4, ...
708
  {
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
709
  	char ip4_addr[sizeof("255.255.255.255")];
4aa996066   Harvey Harrison   printk: add %I4, ...
710

0159f24ee   Joe Perches   lib/vsprintf.c: A...
711
  	ip4_string(ip4_addr, addr, fmt);
4aa996066   Harvey Harrison   printk: add %I4, ...
712

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
713
  	return string(buf, end, ip4_addr, spec);
4aa996066   Harvey Harrison   printk: add %I4, ...
714
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
715
716
717
  static noinline_for_stack
  char *uuid_string(char *buf, char *end, const u8 *addr,
  		  struct printf_spec spec, const char *fmt)
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
  {
  	char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
  	char *p = uuid;
  	int i;
  	static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  	static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
  	const u8 *index = be;
  	bool uc = false;
  
  	switch (*(++fmt)) {
  	case 'L':
  		uc = true;		/* fall-through */
  	case 'l':
  		index = le;
  		break;
  	case 'B':
  		uc = true;
  		break;
  	}
  
  	for (i = 0; i < 16; i++) {
55036ba76   Andy Shevchenko   lib: rename pack_...
739
  		p = hex_byte_pack(p, addr[index[i]]);
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
  		switch (i) {
  		case 3:
  		case 5:
  		case 7:
  		case 9:
  			*p++ = '-';
  			break;
  		}
  	}
  
  	*p = 0;
  
  	if (uc) {
  		p = uuid;
  		do {
  			*p = toupper(*p);
  		} while (*(++p));
  	}
  
  	return string(buf, end, uuid, spec);
  }
c8f44affb   Michał Mirosław   net: introduce an...
761
762
763
764
765
766
767
768
769
770
771
  static
  char *netdev_feature_string(char *buf, char *end, const u8 *addr,
  		      struct printf_spec spec)
  {
  	spec.flags |= SPECIAL | SMALL | ZEROPAD;
  	if (spec.field_width == -1)
  		spec.field_width = 2 + 2 * sizeof(netdev_features_t);
  	spec.base = 16;
  
  	return number(buf, end, *(const netdev_features_t *)addr, spec);
  }
411f05f12   Ingo Molnar   vsprintf: Turn kp...
772
  int kptr_restrict __read_mostly;
455cd5ab3   Dan Rosenberg   kptr_restrict for...
773

4d8a743cd   Linus Torvalds   vsprintf: add inf...
774
775
776
777
778
  /*
   * Show a '%p' thing.  A kernel extension is that the '%p' is followed
   * by an extra set of alphanumeric characters that are extended format
   * specifiers.
   *
332d2e783   Linus Torvalds   Implement %pR to ...
779
780
   * Right now we handle:
   *
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
781
782
   * - 'F' For symbolic function descriptor pointers with offset
   * - 'f' For simple symbolic function names without offset
0efb4d207   Steven Rostedt   vsnprintf: remove...
783
784
   * - 'S' For symbolic direct pointers with offset
   * - 's' For symbolic direct pointers without offset
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
785
   * - 'B' For backtraced symbolic direct pointers with offset
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
786
787
   * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
   * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
dd45c9cf6   Harvey Harrison   printk: add %pM f...
788
789
   * - 'M' For a 6-byte MAC address, it prints the address in the
   *       usual colon-separated hex notation
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
790
   * - 'm' For a 6-byte MAC address, it prints the hex address without colons
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
791
   * - 'MF' For a 6-byte MAC FDDI address, it prints the address
c8e000604   Joe Perches   lib: Kill bit-rev...
792
   *       with a dash-separated hex notation
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
793
794
795
796
797
798
   * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
   *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
   *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
   * - 'i' [46] for 'raw' IPv4/IPv6 addresses
   *       IPv6 omits the colons (01020304...0f)
   *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
0159f24ee   Joe Perches   lib/vsprintf.c: A...
799
   * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
800
   * - 'I6c' for IPv6 addresses printed as specified by
29cf519ee   Joe Perches   vsprintf: Update ...
801
   *       http://tools.ietf.org/html/rfc5952
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
802
803
804
805
806
807
808
809
810
811
812
   * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
   *       "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
   *       Options for %pU are:
   *         b big endian lower case hex (default)
   *         B big endian UPPER case hex
   *         l little endian lower case hex
   *         L little endian UPPER case hex
   *           big endian output byte order is:
   *             [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
   *           little endian output byte order is:
   *             [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
7db6f5fb6   Joe Perches   vsprintf: Recursi...
813
814
815
816
817
   * - 'V' For a struct va_format which contains a format string * and va_list *,
   *       call vsnprintf(->format, *->va_list).
   *       Implements a "recursive vsnprintf".
   *       Do not use this feature without some mechanism to verify the
   *       correctness of the format string and va_list arguments.
455cd5ab3   Dan Rosenberg   kptr_restrict for...
818
   * - 'K' For a kernel pointer that should be hidden from unprivileged users
c8f44affb   Michał Mirosław   net: introduce an...
819
   * - 'NF' For a netdev_features_t
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
820
   *
332d2e783   Linus Torvalds   Implement %pR to ...
821
822
823
   * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
   * function pointers are really function descriptors, which contain a
   * pointer to the real address.
4d8a743cd   Linus Torvalds   vsprintf: add inf...
824
   */
cf3b429b0   Joe Perches   vsprintf.c: use n...
825
826
827
  static noinline_for_stack
  char *pointer(const char *fmt, char *buf, char *end, void *ptr,
  	      struct printf_spec spec)
78a8bf69b   Linus Torvalds   vsprintf: split o...
828
  {
9f36e2c44   Kees Cook   printk: use %pK f...
829
  	if (!ptr && *fmt != 'K') {
5e0579812   Joe Perches   vsprintf.c: use d...
830
831
832
833
834
835
  		/*
  		 * Print (null) with the same width as a pointer so it makes
  		 * tabular output look nice.
  		 */
  		if (spec.field_width == -1)
  			spec.field_width = 2 * sizeof(void *);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
836
  		return string(buf, end, "(null)", spec);
5e0579812   Joe Perches   vsprintf.c: use d...
837
  	}
d97106ab5   Linus Torvalds   Make %p print '(n...
838

0fe1ef24f   Linus Torvalds   vsprintf: add sup...
839
840
  	switch (*fmt) {
  	case 'F':
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
841
  	case 'f':
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
842
843
844
  		ptr = dereference_function_descriptor(ptr);
  		/* Fallthrough */
  	case 'S':
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
845
  	case 's':
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
846
  	case 'B':
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
847
  		return symbol_string(buf, end, ptr, spec, *fmt);
332d2e783   Linus Torvalds   Implement %pR to ...
848
  	case 'R':
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
849
  	case 'r':
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
850
  		return resource_string(buf, end, ptr, spec, fmt);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
851
852
  	case 'M':			/* Colon separated: 00:01:02:03:04:05 */
  	case 'm':			/* Contiguous: 000102030405 */
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
853
  					/* [mM]F (FDDI, bit reversed) */
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
  		return mac_address_string(buf, end, ptr, spec, fmt);
  	case 'I':			/* Formatted IP supported
  					 * 4:	1.2.3.4
  					 * 6:	0001:0203:...:0708
  					 * 6c:	1::708 or 1::1.2.3.4
  					 */
  	case 'i':			/* Contiguous:
  					 * 4:	001.002.003.004
  					 * 6:   000102...0f
  					 */
  		switch (fmt[1]) {
  		case '6':
  			return ip6_addr_string(buf, end, ptr, spec, fmt);
  		case '4':
  			return ip4_addr_string(buf, end, ptr, spec, fmt);
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
870
  		break;
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
871
872
  	case 'U':
  		return uuid_string(buf, end, ptr, spec, fmt);
7db6f5fb6   Joe Perches   vsprintf: Recursi...
873
  	case 'V':
d9be9b90d   Jan Beulich   lib/vsprintf.c: f...
874
  		return buf + vsnprintf(buf, end > buf ? end - buf : 0,
7db6f5fb6   Joe Perches   vsprintf: Recursi...
875
876
  				       ((struct va_format *)ptr)->fmt,
  				       *(((struct va_format *)ptr)->va));
455cd5ab3   Dan Rosenberg   kptr_restrict for...
877
878
879
880
881
882
883
884
885
  	case 'K':
  		/*
  		 * %pK cannot be used in IRQ context because its test
  		 * for CAP_SYSLOG would be meaningless.
  		 */
  		if (in_irq() || in_serving_softirq() || in_nmi()) {
  			if (spec.field_width == -1)
  				spec.field_width = 2 * sizeof(void *);
  			return string(buf, end, "pK-error", spec);
455cd5ab3   Dan Rosenberg   kptr_restrict for...
886
  		}
26297607e   Joe Perches   vsprintf: neaten ...
887
888
889
890
891
  		if (!((kptr_restrict == 0) ||
  		      (kptr_restrict == 1 &&
  		       has_capability_noaudit(current, CAP_SYSLOG))))
  			ptr = NULL;
  		break;
c8f44affb   Michał Mirosław   net: introduce an...
892
893
894
895
896
897
  	case 'N':
  		switch (fmt[1]) {
  		case 'F':
  			return netdev_feature_string(buf, end, ptr, spec);
  		}
  		break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
898
899
900
  	}
  	spec.flags |= SMALL;
  	if (spec.field_width == -1) {
5e0579812   Joe Perches   vsprintf.c: use d...
901
  		spec.field_width = 2 * sizeof(void *);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
  		spec.flags |= ZEROPAD;
  	}
  	spec.base = 16;
  
  	return number(buf, end, (unsigned long) ptr, spec);
  }
  
  /*
   * Helper function to decode printf style format.
   * Each call decode a token from the format and return the
   * number of characters read (or likely the delta where it wants
   * to go on the next call).
   * The decoded token is returned through the parameters
   *
   * 'h', 'l', or 'L' for integer fields
   * 'z' support added 23/7/1999 S.H.
   * 'z' changed to 'Z' --davidm 1/25/99
   * 't' added for ptrdiff_t
   *
   * @fmt: the format string
   * @type of the token returned
   * @flags: various flags such as +, -, # tokens..
   * @field_width: overwritten width
   * @base: base of the number (octal, hex, ...)
   * @precision: precision of a number
   * @qualifier: qualifier of a number (long, size_t, ...)
   */
cf3b429b0   Joe Perches   vsprintf.c: use n...
929
930
  static noinline_for_stack
  int format_decode(const char *fmt, struct printf_spec *spec)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
931
932
  {
  	const char *start = fmt;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
933
934
  
  	/* we finished early by reading the field width */
ed681a91a   Vegard Nossum   vsprintf: unify t...
935
  	if (spec->type == FORMAT_TYPE_WIDTH) {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
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
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
  		if (spec->field_width < 0) {
  			spec->field_width = -spec->field_width;
  			spec->flags |= LEFT;
  		}
  		spec->type = FORMAT_TYPE_NONE;
  		goto precision;
  	}
  
  	/* we finished early by reading the precision */
  	if (spec->type == FORMAT_TYPE_PRECISION) {
  		if (spec->precision < 0)
  			spec->precision = 0;
  
  		spec->type = FORMAT_TYPE_NONE;
  		goto qualifier;
  	}
  
  	/* By default */
  	spec->type = FORMAT_TYPE_NONE;
  
  	for (; *fmt ; ++fmt) {
  		if (*fmt == '%')
  			break;
  	}
  
  	/* Return the current non-format string */
  	if (fmt != start || !*fmt)
  		return fmt - start;
  
  	/* Process flags */
  	spec->flags = 0;
  
  	while (1) { /* this also skips first '%' */
  		bool found = true;
  
  		++fmt;
  
  		switch (*fmt) {
  		case '-': spec->flags |= LEFT;    break;
  		case '+': spec->flags |= PLUS;    break;
  		case ' ': spec->flags |= SPACE;   break;
  		case '#': spec->flags |= SPECIAL; break;
  		case '0': spec->flags |= ZEROPAD; break;
  		default:  found = false;
  		}
  
  		if (!found)
  			break;
  	}
  
  	/* get field width */
  	spec->field_width = -1;
  
  	if (isdigit(*fmt))
  		spec->field_width = skip_atoi(&fmt);
  	else if (*fmt == '*') {
  		/* it's the next argument */
ed681a91a   Vegard Nossum   vsprintf: unify t...
993
  		spec->type = FORMAT_TYPE_WIDTH;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
  		return ++fmt - start;
  	}
  
  precision:
  	/* get the precision */
  	spec->precision = -1;
  	if (*fmt == '.') {
  		++fmt;
  		if (isdigit(*fmt)) {
  			spec->precision = skip_atoi(&fmt);
  			if (spec->precision < 0)
  				spec->precision = 0;
  		} else if (*fmt == '*') {
  			/* it's the next argument */
adf26f84a   Vegard Nossum   fix regression fr...
1008
  			spec->type = FORMAT_TYPE_PRECISION;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1009
1010
1011
1012
1013
1014
1015
  			return ++fmt - start;
  		}
  	}
  
  qualifier:
  	/* get the conversion qualifier */
  	spec->qualifier = -1;
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1016
1017
  	if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
  	    _tolower(*fmt) == 'z' || *fmt == 't') {
a4e94ef0d   Zhaolei   printk: add suppo...
1018
1019
1020
1021
1022
1023
1024
1025
1026
  		spec->qualifier = *fmt++;
  		if (unlikely(spec->qualifier == *fmt)) {
  			if (spec->qualifier == 'l') {
  				spec->qualifier = 'L';
  				++fmt;
  			} else if (spec->qualifier == 'h') {
  				spec->qualifier = 'H';
  				++fmt;
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  		}
  	}
  
  	/* default base */
  	spec->base = 10;
  	switch (*fmt) {
  	case 'c':
  		spec->type = FORMAT_TYPE_CHAR;
  		return ++fmt - start;
  
  	case 's':
  		spec->type = FORMAT_TYPE_STR;
  		return ++fmt - start;
  
  	case 'p':
  		spec->type = FORMAT_TYPE_PTR;
  		return fmt - start;
  		/* skip alnum */
  
  	case 'n':
  		spec->type = FORMAT_TYPE_NRCHARS;
  		return ++fmt - start;
  
  	case '%':
  		spec->type = FORMAT_TYPE_PERCENT_CHAR;
  		return ++fmt - start;
  
  	/* integer number formats - set up the flags and "break" */
  	case 'o':
  		spec->base = 8;
  		break;
  
  	case 'x':
  		spec->flags |= SMALL;
  
  	case 'X':
  		spec->base = 16;
  		break;
  
  	case 'd':
  	case 'i':
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1068
  		spec->flags |= SIGN;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1069
  	case 'u':
4aa996066   Harvey Harrison   printk: add %I4, ...
1070
  		break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1071
1072
1073
1074
  
  	default:
  		spec->type = FORMAT_TYPE_INVALID;
  		return fmt - start;
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
1075
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1076
1077
1078
1079
  
  	if (spec->qualifier == 'L')
  		spec->type = FORMAT_TYPE_LONG_LONG;
  	else if (spec->qualifier == 'l') {
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1080
  		if (spec->flags & SIGN)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1081
1082
1083
  			spec->type = FORMAT_TYPE_LONG;
  		else
  			spec->type = FORMAT_TYPE_ULONG;
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1084
  	} else if (_tolower(spec->qualifier) == 'z') {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1085
1086
1087
  		spec->type = FORMAT_TYPE_SIZE_T;
  	} else if (spec->qualifier == 't') {
  		spec->type = FORMAT_TYPE_PTRDIFF;
a4e94ef0d   Zhaolei   printk: add suppo...
1088
1089
1090
1091
1092
  	} else if (spec->qualifier == 'H') {
  		if (spec->flags & SIGN)
  			spec->type = FORMAT_TYPE_BYTE;
  		else
  			spec->type = FORMAT_TYPE_UBYTE;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1093
  	} else if (spec->qualifier == 'h') {
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1094
  		if (spec->flags & SIGN)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1095
1096
1097
1098
  			spec->type = FORMAT_TYPE_SHORT;
  		else
  			spec->type = FORMAT_TYPE_USHORT;
  	} else {
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1099
  		if (spec->flags & SIGN)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1100
1101
1102
  			spec->type = FORMAT_TYPE_INT;
  		else
  			spec->type = FORMAT_TYPE_UINT;
78a8bf69b   Linus Torvalds   vsprintf: split o...
1103
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1104
1105
  
  	return ++fmt - start;
78a8bf69b   Linus Torvalds   vsprintf: split o...
1106
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
1108
1109
1110
1111
1112
1113
  /**
   * vsnprintf - Format a string and place it in a buffer
   * @buf: The buffer to place the result into
   * @size: The size of the buffer, including the trailing null space
   * @fmt: The format string to use
   * @args: Arguments for the format string
   *
20036fdca   Andi Kleen   Add kerneldoc doc...
1114
   * This function follows C99 vsnprintf, but has some extensions:
91adcd2c4   Steven Rostedt   vsprintf: add %ps...
1115
1116
   * %pS output the name of a text symbol with offset
   * %ps output the name of a text symbol without offset
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
1117
1118
   * %pF output the name of a function pointer with its offset
   * %pf output the name of a function pointer without its offset
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
1119
   * %pB output the name of a backtrace symbol with its offset
8a79503aa   Uwe Kleine-König   lib/vsprintf.c: d...
1120
1121
1122
1123
1124
1125
1126
1127
   * %pR output the address range in a struct resource with decoded flags
   * %pr output the address range in a struct resource with raw flags
   * %pM output a 6-byte MAC address with colons
   * %pm output a 6-byte MAC address without colons
   * %pI4 print an IPv4 address without leading zeros
   * %pi4 print an IPv4 address with leading zeros
   * %pI6 print an IPv6 address with colons
   * %pi6 print an IPv6 address without colons
f996f2081   Jan Engelhardt   lib/vsprintf: rep...
1128
   * %pI6c print an IPv6 address as specified by RFC 5952
8a79503aa   Uwe Kleine-König   lib/vsprintf.c: d...
1129
1130
   * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
   *   case.
0efb4d207   Steven Rostedt   vsnprintf: remove...
1131
   * %n is ignored
20036fdca   Andi Kleen   Add kerneldoc doc...
1132
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1133
1134
1135
1136
   * The return value is the number of characters which would
   * be generated for the given input, excluding the trailing
   * '\0', as per ISO C99. If you want to have the exact
   * number of characters written into @buf as return value
72fd4a35a   Robert P. J. Day   [PATCH] Numerous ...
1137
   * (not including the trailing '\0'), use vscnprintf(). If the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1138
1139
1140
   * return is greater than or equal to @size, the resulting
   * string is truncated.
   *
ba1835eb3   Uwe Kleine-König   vsprintf: make co...
1141
   * If you're not already dealing with a va_list consider using snprintf().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1142
1143
1144
   */
  int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1145
  	unsigned long long num;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1146
  	char *str, *end;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1147
  	struct printf_spec spec = {0};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1148

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1149
1150
  	/* Reject out-of-range values early.  Large positive sizes are
  	   used for unknown buffer sizes. */
2f30b1f9e   Marcin Slusarz   vsprintf: use WAR...
1151
  	if (WARN_ON_ONCE((int) size < 0))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1153
1154
  
  	str = buf;
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1155
  	end = buf + size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1156

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1157
1158
1159
1160
  	/* Make sure end is always >= buf */
  	if (end < buf) {
  		end = ((void *)-1);
  		size = end - buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1161
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1162
1163
  	while (*fmt) {
  		const char *old_fmt = fmt;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1164
  		int read = format_decode(fmt, &spec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1165

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1166
  		fmt += read;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1168
1169
1170
1171
1172
1173
1174
  		switch (spec.type) {
  		case FORMAT_TYPE_NONE: {
  			int copy = read;
  			if (str < end) {
  				if (copy > end - str)
  					copy = end - str;
  				memcpy(str, old_fmt, copy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1175
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1176
1177
  			str += read;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  		}
ed681a91a   Vegard Nossum   vsprintf: unify t...
1179
  		case FORMAT_TYPE_WIDTH:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1180
1181
  			spec.field_width = va_arg(args, int);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1183
1184
1185
  		case FORMAT_TYPE_PRECISION:
  			spec.precision = va_arg(args, int);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186

d4be151b2   André Goddard Rosa   vsprintf: move lo...
1187
1188
  		case FORMAT_TYPE_CHAR: {
  			char c;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1189
1190
  			if (!(spec.flags & LEFT)) {
  				while (--spec.field_width > 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1191
  					if (str < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
1193
  						*str = ' ';
  					++str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1194

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1195
1196
1197
1198
1199
1200
1201
  				}
  			}
  			c = (unsigned char) va_arg(args, int);
  			if (str < end)
  				*str = c;
  			++str;
  			while (--spec.field_width > 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1202
  				if (str < end)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1203
  					*str = ' ';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
  				++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1205
1206
  			}
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1207
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1208

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1209
1210
1211
  		case FORMAT_TYPE_STR:
  			str = string(str, end, va_arg(args, char *), spec);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1212

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1213
1214
1215
1216
1217
1218
  		case FORMAT_TYPE_PTR:
  			str = pointer(fmt+1, str, end, va_arg(args, void *),
  				      spec);
  			while (isalnum(*fmt))
  				fmt++;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1220
1221
1222
1223
1224
  		case FORMAT_TYPE_PERCENT_CHAR:
  			if (str < end)
  				*str = '%';
  			++str;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1226
1227
1228
1229
  		case FORMAT_TYPE_INVALID:
  			if (str < end)
  				*str = '%';
  			++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1230
1231
1232
  			break;
  
  		case FORMAT_TYPE_NRCHARS: {
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
1233
  			u8 qualifier = spec.qualifier;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1234
1235
1236
1237
  
  			if (qualifier == 'l') {
  				long *ip = va_arg(args, long *);
  				*ip = (str - buf);
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1238
  			} else if (_tolower(qualifier) == 'z') {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1239
1240
1241
1242
1243
1244
1245
  				size_t *ip = va_arg(args, size_t *);
  				*ip = (str - buf);
  			} else {
  				int *ip = va_arg(args, int *);
  				*ip = (str - buf);
  			}
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1246
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
  
  		default:
  			switch (spec.type) {
  			case FORMAT_TYPE_LONG_LONG:
  				num = va_arg(args, long long);
  				break;
  			case FORMAT_TYPE_ULONG:
  				num = va_arg(args, unsigned long);
  				break;
  			case FORMAT_TYPE_LONG:
  				num = va_arg(args, long);
  				break;
  			case FORMAT_TYPE_SIZE_T:
  				num = va_arg(args, size_t);
  				break;
  			case FORMAT_TYPE_PTRDIFF:
  				num = va_arg(args, ptrdiff_t);
  				break;
a4e94ef0d   Zhaolei   printk: add suppo...
1265
1266
1267
1268
1269
1270
  			case FORMAT_TYPE_UBYTE:
  				num = (unsigned char) va_arg(args, int);
  				break;
  			case FORMAT_TYPE_BYTE:
  				num = (signed char) va_arg(args, int);
  				break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1271
1272
1273
1274
1275
1276
  			case FORMAT_TYPE_USHORT:
  				num = (unsigned short) va_arg(args, int);
  				break;
  			case FORMAT_TYPE_SHORT:
  				num = (short) va_arg(args, int);
  				break;
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1277
1278
  			case FORMAT_TYPE_INT:
  				num = (int) va_arg(args, int);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1279
1280
1281
1282
1283
1284
  				break;
  			default:
  				num = va_arg(args, unsigned int);
  			}
  
  			str = number(str, end, num, spec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1287

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1288
1289
1290
1291
  	if (size > 0) {
  		if (str < end)
  			*str = '\0';
  		else
0a6047eef   Linus Torvalds   Fix vsnprintf off...
1292
  			end[-1] = '\0';
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1293
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1294

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1295
  	/* the trailing null byte doesn't count towards the total */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296
  	return str-buf;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1297

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
  EXPORT_SYMBOL(vsnprintf);
  
  /**
   * vscnprintf - Format a string and place it in a buffer
   * @buf: The buffer to place the result into
   * @size: The size of the buffer, including the trailing null space
   * @fmt: The format string to use
   * @args: Arguments for the format string
   *
   * The return value is the number of characters which have been written into
b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1309
   * the @buf not including the trailing '\0'. If @size is == 0 the function
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
   * returns 0.
   *
ba1835eb3   Uwe Kleine-König   vsprintf: make co...
1312
   * If you're not already dealing with a va_list consider using scnprintf().
20036fdca   Andi Kleen   Add kerneldoc doc...
1313
1314
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
1316
1317
1318
   */
  int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
  {
  	int i;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1319
  	i = vsnprintf(buf, size, fmt, args);
b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1320
1321
1322
1323
1324
  	if (likely(i < size))
  		return i;
  	if (size != 0)
  		return size - 1;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
  EXPORT_SYMBOL(vscnprintf);
  
  /**
   * snprintf - Format a string and place it in a buffer
   * @buf: The buffer to place the result into
   * @size: The size of the buffer, including the trailing null space
   * @fmt: The format string to use
   * @...: Arguments for the format string
   *
   * The return value is the number of characters which would be
   * generated for the given input, excluding the trailing null,
   * as per ISO C99.  If the return is greater than or equal to
   * @size, the resulting string is truncated.
20036fdca   Andi Kleen   Add kerneldoc doc...
1339
1340
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1342
  int snprintf(char *buf, size_t size, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
1345
1346
1347
  {
  	va_list args;
  	int i;
  
  	va_start(args, fmt);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1348
  	i = vsnprintf(buf, size, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1350

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
1352
  	return i;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
  EXPORT_SYMBOL(snprintf);
  
  /**
   * scnprintf - Format a string and place it in a buffer
   * @buf: The buffer to place the result into
   * @size: The size of the buffer, including the trailing null space
   * @fmt: The format string to use
   * @...: Arguments for the format string
   *
   * The return value is the number of characters written into @buf not including
b903c0b88   Changli Gao   lib: fix scnprint...
1363
   * the trailing '\0'. If @size is == 0 the function returns 0.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1365
  int scnprintf(char *buf, size_t size, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366
1367
1368
1369
1370
  {
  	va_list args;
  	int i;
  
  	va_start(args, fmt);
b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1371
  	i = vscnprintf(buf, size, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1372
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1373

b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1374
  	return i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
  }
  EXPORT_SYMBOL(scnprintf);
  
  /**
   * vsprintf - Format a string and place it in a buffer
   * @buf: The buffer to place the result into
   * @fmt: The format string to use
   * @args: Arguments for the format string
   *
   * The function returns the number of characters written
72fd4a35a   Robert P. J. Day   [PATCH] Numerous ...
1385
   * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1386
1387
   * buffer overflows.
   *
ba1835eb3   Uwe Kleine-König   vsprintf: make co...
1388
   * If you're not already dealing with a va_list consider using sprintf().
20036fdca   Andi Kleen   Add kerneldoc doc...
1389
1390
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
1393
1394
1395
   */
  int vsprintf(char *buf, const char *fmt, va_list args)
  {
  	return vsnprintf(buf, INT_MAX, fmt, args);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
1397
1398
1399
1400
1401
1402
1403
1404
  EXPORT_SYMBOL(vsprintf);
  
  /**
   * sprintf - Format a string and place it in a buffer
   * @buf: The buffer to place the result into
   * @fmt: The format string to use
   * @...: Arguments for the format string
   *
   * The function returns the number of characters written
72fd4a35a   Robert P. J. Day   [PATCH] Numerous ...
1405
   * into @buf. Use snprintf() or scnprintf() in order to avoid
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
   * buffer overflows.
20036fdca   Andi Kleen   Add kerneldoc doc...
1407
1408
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1410
  int sprintf(char *buf, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1411
1412
1413
1414
1415
  {
  	va_list args;
  	int i;
  
  	va_start(args, fmt);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1416
  	i = vsnprintf(buf, INT_MAX, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1418

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1419
1420
  	return i;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
  EXPORT_SYMBOL(sprintf);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
  #ifdef CONFIG_BINARY_PRINTF
  /*
   * bprintf service:
   * vbin_printf() - VA arguments to binary data
   * bstr_printf() - Binary data to text string
   */
  
  /**
   * vbin_printf - Parse a format string and place args' binary value in a buffer
   * @bin_buf: The buffer to place args' binary value
   * @size: The size of the buffer(by words(32bits), not characters)
   * @fmt: The format string to use
   * @args: Arguments for the format string
   *
   * The format follows C99 vsnprintf, except %n is ignored, and its argument
   * is skiped.
   *
   * The return value is the number of words(32bits) which would be generated for
   * the given input.
   *
   * NOTE:
   * If the return value is greater than @size, the resulting bin_buf is NOT
   * valid for bstr_printf().
   */
  int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
  {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1448
  	struct printf_spec spec = {0};
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1449
  	char *str, *end;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  
  	str = (char *)bin_buf;
  	end = (char *)(bin_buf + size);
  
  #define save_arg(type)							\
  do {									\
  	if (sizeof(type) == 8) {					\
  		unsigned long long value;				\
  		str = PTR_ALIGN(str, sizeof(u32));			\
  		value = va_arg(args, unsigned long long);		\
  		if (str + sizeof(type) <= end) {			\
  			*(u32 *)str = *(u32 *)&value;			\
  			*(u32 *)(str + 4) = *((u32 *)&value + 1);	\
  		}							\
  	} else {							\
  		unsigned long value;					\
  		str = PTR_ALIGN(str, sizeof(type));			\
  		value = va_arg(args, int);				\
  		if (str + sizeof(type) <= end)				\
  			*(typeof(type) *)str = (type)value;		\
  	}								\
  	str += sizeof(type);						\
  } while (0)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1473
  	while (*fmt) {
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1474
  		int read = format_decode(fmt, &spec);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1475

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1476
  		fmt += read;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1477

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1478
1479
  		switch (spec.type) {
  		case FORMAT_TYPE_NONE:
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1480
1481
  		case FORMAT_TYPE_INVALID:
  		case FORMAT_TYPE_PERCENT_CHAR:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1482
  			break;
ed681a91a   Vegard Nossum   vsprintf: unify t...
1483
  		case FORMAT_TYPE_WIDTH:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1484
1485
1486
1487
1488
  		case FORMAT_TYPE_PRECISION:
  			save_arg(int);
  			break;
  
  		case FORMAT_TYPE_CHAR:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1489
  			save_arg(char);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1490
1491
1492
  			break;
  
  		case FORMAT_TYPE_STR: {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1493
1494
  			const char *save_str = va_arg(args, char *);
  			size_t len;
6c3566341   André Goddard Rosa   vsprintf: pre-cal...
1495

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1496
1497
  			if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE
  					|| (unsigned long)save_str < PAGE_SIZE)
0f4f81dce   André Goddard Rosa   vsprintf: factori...
1498
  				save_str = "(null)";
6c3566341   André Goddard Rosa   vsprintf: pre-cal...
1499
1500
1501
1502
  			len = strlen(save_str) + 1;
  			if (str + len < end)
  				memcpy(str, save_str, len);
  			str += len;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1503
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1504
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1505
1506
  
  		case FORMAT_TYPE_PTR:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1507
1508
  			save_arg(void *);
  			/* skip all alphanumeric pointer suffixes */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1509
  			while (isalnum(*fmt))
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1510
  				fmt++;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1511
  			break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1512
  		case FORMAT_TYPE_NRCHARS: {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1513
  			/* skip %n 's argument */
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
1514
  			u8 qualifier = spec.qualifier;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1515
1516
1517
  			void *skip_arg;
  			if (qualifier == 'l')
  				skip_arg = va_arg(args, long *);
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1518
  			else if (_tolower(qualifier) == 'z')
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1519
1520
1521
  				skip_arg = va_arg(args, size_t *);
  			else
  				skip_arg = va_arg(args, int *);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1522
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1523
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1524
1525
1526
1527
1528
  
  		default:
  			switch (spec.type) {
  
  			case FORMAT_TYPE_LONG_LONG:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1529
  				save_arg(long long);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1530
1531
1532
  				break;
  			case FORMAT_TYPE_ULONG:
  			case FORMAT_TYPE_LONG:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1533
  				save_arg(unsigned long);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1534
1535
  				break;
  			case FORMAT_TYPE_SIZE_T:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1536
  				save_arg(size_t);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1537
1538
  				break;
  			case FORMAT_TYPE_PTRDIFF:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1539
  				save_arg(ptrdiff_t);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1540
  				break;
a4e94ef0d   Zhaolei   printk: add suppo...
1541
1542
1543
1544
  			case FORMAT_TYPE_UBYTE:
  			case FORMAT_TYPE_BYTE:
  				save_arg(char);
  				break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1545
1546
  			case FORMAT_TYPE_USHORT:
  			case FORMAT_TYPE_SHORT:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1547
  				save_arg(short);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1548
1549
  				break;
  			default:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1550
  				save_arg(int);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1551
  			}
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1552
1553
  		}
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1554

7b9186f5e   André Goddard Rosa   vsprintf: give it...
1555
  	return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1556
  #undef save_arg
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
  }
  EXPORT_SYMBOL_GPL(vbin_printf);
  
  /**
   * bstr_printf - Format a string from binary arguments and place it in a buffer
   * @buf: The buffer to place the result into
   * @size: The size of the buffer, including the trailing null space
   * @fmt: The format string to use
   * @bin_buf: Binary arguments for the format string
   *
   * This function like C99 vsnprintf, but the difference is that vsnprintf gets
   * arguments from stack, and bstr_printf gets arguments from @bin_buf which is
   * a binary buffer that generated by vbin_printf.
   *
   * The format follows C99 vsnprintf, but has some extensions:
0efb4d207   Steven Rostedt   vsnprintf: remove...
1572
   *  see vsnprintf comment for details.
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
   *
   * The return value is the number of characters which would
   * be generated for the given input, excluding the trailing
   * '\0', as per ISO C99. If you want to have the exact
   * number of characters written into @buf as return value
   * (not including the trailing '\0'), use vscnprintf(). If the
   * return is greater than or equal to @size, the resulting
   * string is truncated.
   */
  int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
  {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1584
  	struct printf_spec spec = {0};
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1585
1586
  	char *str, *end;
  	const char *args = (const char *)bin_buf;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1587

2f30b1f9e   Marcin Slusarz   vsprintf: use WAR...
1588
  	if (WARN_ON_ONCE((int) size < 0))
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1589
  		return 0;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
  
  	str = buf;
  	end = buf + size;
  
  #define get_arg(type)							\
  ({									\
  	typeof(type) value;						\
  	if (sizeof(type) == 8) {					\
  		args = PTR_ALIGN(args, sizeof(u32));			\
  		*(u32 *)&value = *(u32 *)args;				\
  		*((u32 *)&value + 1) = *(u32 *)(args + 4);		\
  	} else {							\
  		args = PTR_ALIGN(args, sizeof(type));			\
  		value = *(typeof(type) *)args;				\
  	}								\
  	args += sizeof(type);						\
  	value;								\
  })
  
  	/* Make sure end is always >= buf */
  	if (end < buf) {
  		end = ((void *)-1);
  		size = end - buf;
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1614
  	while (*fmt) {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1615
  		const char *old_fmt = fmt;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1616
  		int read = format_decode(fmt, &spec);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1617

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1618
  		fmt += read;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1619

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1620
1621
1622
1623
1624
1625
1626
  		switch (spec.type) {
  		case FORMAT_TYPE_NONE: {
  			int copy = read;
  			if (str < end) {
  				if (copy > end - str)
  					copy = end - str;
  				memcpy(str, old_fmt, copy);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1627
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1628
1629
  			str += read;
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1630
  		}
ed681a91a   Vegard Nossum   vsprintf: unify t...
1631
  		case FORMAT_TYPE_WIDTH:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1632
1633
  			spec.field_width = get_arg(int);
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1634

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1635
1636
1637
  		case FORMAT_TYPE_PRECISION:
  			spec.precision = get_arg(int);
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1638

d4be151b2   André Goddard Rosa   vsprintf: move lo...
1639
1640
  		case FORMAT_TYPE_CHAR: {
  			char c;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1641
1642
  			if (!(spec.flags & LEFT)) {
  				while (--spec.field_width > 0) {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1643
1644
1645
1646
1647
1648
1649
1650
1651
  					if (str < end)
  						*str = ' ';
  					++str;
  				}
  			}
  			c = (unsigned char) get_arg(char);
  			if (str < end)
  				*str = c;
  			++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1652
  			while (--spec.field_width > 0) {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1653
1654
1655
1656
  				if (str < end)
  					*str = ' ';
  				++str;
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1657
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1658
  		}
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1659

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1660
  		case FORMAT_TYPE_STR: {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1661
  			const char *str_arg = args;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1662
  			args += strlen(str_arg) + 1;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1663
1664
  			str = string(str, end, (char *)str_arg, spec);
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1665
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1666
1667
1668
  		case FORMAT_TYPE_PTR:
  			str = pointer(fmt+1, str, end, get_arg(void *), spec);
  			while (isalnum(*fmt))
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1669
  				fmt++;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1670
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1671

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1672
  		case FORMAT_TYPE_PERCENT_CHAR:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1673
  		case FORMAT_TYPE_INVALID:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1674
1675
1676
  			if (str < end)
  				*str = '%';
  			++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1677
1678
1679
1680
1681
  			break;
  
  		case FORMAT_TYPE_NRCHARS:
  			/* skip */
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1682
1683
  		default: {
  			unsigned long long num;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1684
1685
1686
1687
1688
1689
  			switch (spec.type) {
  
  			case FORMAT_TYPE_LONG_LONG:
  				num = get_arg(long long);
  				break;
  			case FORMAT_TYPE_ULONG:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1690
1691
1692
1693
1694
1695
1696
1697
1698
  			case FORMAT_TYPE_LONG:
  				num = get_arg(unsigned long);
  				break;
  			case FORMAT_TYPE_SIZE_T:
  				num = get_arg(size_t);
  				break;
  			case FORMAT_TYPE_PTRDIFF:
  				num = get_arg(ptrdiff_t);
  				break;
a4e94ef0d   Zhaolei   printk: add suppo...
1699
1700
1701
1702
1703
1704
  			case FORMAT_TYPE_UBYTE:
  				num = get_arg(unsigned char);
  				break;
  			case FORMAT_TYPE_BYTE:
  				num = get_arg(signed char);
  				break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
  			case FORMAT_TYPE_USHORT:
  				num = get_arg(unsigned short);
  				break;
  			case FORMAT_TYPE_SHORT:
  				num = get_arg(short);
  				break;
  			case FORMAT_TYPE_UINT:
  				num = get_arg(unsigned int);
  				break;
  			default:
  				num = get_arg(int);
  			}
  
  			str = number(str, end, num, spec);
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1719
1720
1721
  		} /* default: */
  		} /* switch(spec.type) */
  	} /* while(*fmt) */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1722

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1723
1724
1725
1726
1727
1728
  	if (size > 0) {
  		if (str < end)
  			*str = '\0';
  		else
  			end[-1] = '\0';
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1729

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
  #undef get_arg
  
  	/* the trailing null byte doesn't count towards the total */
  	return str - buf;
  }
  EXPORT_SYMBOL_GPL(bstr_printf);
  
  /**
   * bprintf - Parse a format string and place args' binary value in a buffer
   * @bin_buf: The buffer to place args' binary value
   * @size: The size of the buffer(by words(32bits), not characters)
   * @fmt: The format string to use
   * @...: Arguments for the format string
   *
   * The function returns the number of words(u32) written
   * into @bin_buf.
   */
  int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
  {
  	va_list args;
  	int ret;
  
  	va_start(args, fmt);
  	ret = vbin_printf(bin_buf, size, fmt, args);
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1755

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1756
1757
1758
1759
1760
  	return ret;
  }
  EXPORT_SYMBOL_GPL(bprintf);
  
  #endif /* CONFIG_BINARY_PRINTF */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1761
1762
1763
1764
1765
1766
  /**
   * vsscanf - Unformat a buffer into a list of arguments
   * @buf:	input buffer
   * @fmt:	format of buffer
   * @args:	arguments
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1767
  int vsscanf(const char *buf, const char *fmt, va_list args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
1770
1771
1772
  {
  	const char *str = buf;
  	char *next;
  	char digit;
  	int num = 0;
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
1773
1774
1775
  	u8 qualifier;
  	u8 base;
  	s16 field_width;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1776
  	bool is_sign;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1777

7b9186f5e   André Goddard Rosa   vsprintf: give it...
1778
  	while (*fmt && *str) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1779
1780
1781
1782
1783
  		/* skip any white space in format */
  		/* white space in format matchs any amount of
  		 * white space, including none, in the input.
  		 */
  		if (isspace(*fmt)) {
e7d2860b6   André Goddard Rosa   tree-wide: conver...
1784
1785
  			fmt = skip_spaces(++fmt);
  			str = skip_spaces(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
  		}
  
  		/* anything that is not a conversion must match exactly */
  		if (*fmt != '%' && *fmt) {
  			if (*fmt++ != *str++)
  				break;
  			continue;
  		}
  
  		if (!*fmt)
  			break;
  		++fmt;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1798

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1799
1800
1801
1802
  		/* skip this conversion.
  		 * advance both strings to next white space
  		 */
  		if (*fmt == '*') {
8fccae2c9   Andy Spencer   sscanf(): fix %*s%n
1803
  			while (!isspace(*fmt) && *fmt != '%' && *fmt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
  				fmt++;
  			while (!isspace(*str) && *str)
  				str++;
  			continue;
  		}
  
  		/* get field width */
  		field_width = -1;
  		if (isdigit(*fmt))
  			field_width = skip_atoi(&fmt);
  
  		/* get conversion qualifier */
  		qualifier = -1;
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1817
1818
  		if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
  		    _tolower(*fmt) == 'z') {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
  			qualifier = *fmt++;
  			if (unlikely(qualifier == *fmt)) {
  				if (qualifier == 'h') {
  					qualifier = 'H';
  					fmt++;
  				} else if (qualifier == 'l') {
  					qualifier = 'L';
  					fmt++;
  				}
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1830
1831
1832
  
  		if (!*fmt || !*str)
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1833
1834
  		base = 10;
  		is_sign = 0;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1835
  		switch (*fmt++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1836
1837
  		case 'c':
  		{
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1838
  			char *s = (char *)va_arg(args, char*);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
  			if (field_width == -1)
  				field_width = 1;
  			do {
  				*s++ = *str++;
  			} while (--field_width > 0 && *str);
  			num++;
  		}
  		continue;
  		case 's':
  		{
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1849
1850
  			char *s = (char *)va_arg(args, char *);
  			if (field_width == -1)
4be929be3   Alexey Dobriyan   kernel-wide: repl...
1851
  				field_width = SHRT_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
  			/* first, skip leading white space in buffer */
e7d2860b6   André Goddard Rosa   tree-wide: conver...
1853
  			str = skip_spaces(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1854
1855
  
  			/* now copy until next white space */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1856
  			while (*str && !isspace(*str) && field_width--)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1857
  				*s++ = *str++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1858
1859
1860
1861
1862
1863
1864
  			*s = '\0';
  			num++;
  		}
  		continue;
  		case 'n':
  			/* return number of characters read so far */
  		{
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1865
  			int *i = (int *)va_arg(args, int*);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
  			*i = str - buf;
  		}
  		continue;
  		case 'o':
  			base = 8;
  			break;
  		case 'x':
  		case 'X':
  			base = 16;
  			break;
  		case 'i':
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1877
  			base = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1878
1879
1880
1881
1882
1883
  		case 'd':
  			is_sign = 1;
  		case 'u':
  			break;
  		case '%':
  			/* looking for '%' in str */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1884
  			if (*str++ != '%')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
  				return num;
  			continue;
  		default:
  			/* invalid format; stop here */
  			return num;
  		}
  
  		/* have some sort of integer conversion.
  		 * first, skip white space in buffer.
  		 */
e7d2860b6   André Goddard Rosa   tree-wide: conver...
1895
  		str = skip_spaces(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1896
1897
1898
1899
1900
1901
  
  		digit = *str;
  		if (is_sign && digit == '-')
  			digit = *(str + 1);
  
  		if (!digit
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1902
1903
1904
1905
1906
  		    || (base == 16 && !isxdigit(digit))
  		    || (base == 10 && !isdigit(digit))
  		    || (base == 8 && (!isdigit(digit) || digit > '7'))
  		    || (base == 0 && !isdigit(digit)))
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907

7b9186f5e   André Goddard Rosa   vsprintf: give it...
1908
  		switch (qualifier) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1909
1910
  		case 'H':	/* that's 'hh' in format */
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1911
1912
  				signed char *s = (signed char *)va_arg(args, signed char *);
  				*s = (signed char)simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1914
1915
  				unsigned char *s = (unsigned char *)va_arg(args, unsigned char *);
  				*s = (unsigned char)simple_strtoul(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1916
1917
1918
1919
  			}
  			break;
  		case 'h':
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1920
1921
  				short *s = (short *)va_arg(args, short *);
  				*s = (short)simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1922
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1923
1924
  				unsigned short *s = (unsigned short *)va_arg(args, unsigned short *);
  				*s = (unsigned short)simple_strtoul(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
1926
1927
1928
  			}
  			break;
  		case 'l':
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1929
1930
  				long *l = (long *)va_arg(args, long *);
  				*l = simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1931
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1932
1933
  				unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
  				*l = simple_strtoul(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
1935
1936
1937
  			}
  			break;
  		case 'L':
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1938
1939
  				long long *l = (long long *)va_arg(args, long long *);
  				*l = simple_strtoll(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1940
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1941
1942
  				unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *);
  				*l = simple_strtoull(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1943
1944
1945
1946
1947
  			}
  			break;
  		case 'Z':
  		case 'z':
  		{
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1948
1949
  			size_t *s = (size_t *)va_arg(args, size_t *);
  			*s = (size_t)simple_strtoul(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1950
1951
1952
1953
  		}
  		break;
  		default:
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1954
1955
  				int *i = (int *)va_arg(args, int *);
  				*i = (int)simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1957
1958
  				unsigned int *i = (unsigned int *)va_arg(args, unsigned int*);
  				*i = (unsigned int)simple_strtoul(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1959
1960
1961
1962
1963
1964
1965
1966
1967
  			}
  			break;
  		}
  		num++;
  
  		if (!next)
  			break;
  		str = next;
  	}
c6b40d16d   Johannes Berg   fix sscanf %n mat...
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
  
  	/*
  	 * Now we've come all the way through so either the input string or the
  	 * format ended. In the former case, there can be a %n at the current
  	 * position in the format that needs to be filled.
  	 */
  	if (*fmt == '%' && *(fmt + 1) == 'n') {
  		int *p = (int *)va_arg(args, int *);
  		*p = str - buf;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1978
1979
  	return num;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1980
1981
1982
1983
1984
1985
1986
1987
  EXPORT_SYMBOL(vsscanf);
  
  /**
   * sscanf - Unformat a buffer into a list of arguments
   * @buf:	input buffer
   * @fmt:	formatting of buffer
   * @...:	resulting arguments
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1988
  int sscanf(const char *buf, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1989
1990
1991
  {
  	va_list args;
  	int i;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1992
1993
  	va_start(args, fmt);
  	i = vsscanf(buf, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1994
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1995

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1996
1997
  	return i;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1998
  EXPORT_SYMBOL(sscanf);