Blame view

lib/vsprintf.c 52.6 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
   * 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>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
19
  #include <linux/module.h>	/* for KSYM_SYMBOL_LEN */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
  #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
  /* 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
133fd9f5c   Denys Vlasenko   vsprintf: further...
113
114
115
   * using ideas described at <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
   * (with permission from the author, Douglas W. Jones).
   */
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
116

133fd9f5c   Denys Vlasenko   vsprintf: further...
117
118
  #if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
  /* Formats correctly any integer in [0, 999999999] */
cf3b429b0   Joe Perches   vsprintf.c: use n...
119
  static noinline_for_stack
133fd9f5c   Denys Vlasenko   vsprintf: further...
120
  char *put_dec_full9(char *buf, unsigned q)
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
121
  {
133fd9f5c   Denys Vlasenko   vsprintf: further...
122
  	unsigned r;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
123

133fd9f5c   Denys Vlasenko   vsprintf: further...
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
150
151
152
153
154
155
156
157
158
159
160
  	/*
  	 * Possible ways to approx. divide by 10
  	 * (x * 0x1999999a) >> 32 x < 1073741829 (multiply must be 64-bit)
  	 * (x * 0xcccd) >> 19     x <      81920 (x < 262149 when 64-bit mul)
  	 * (x * 0x6667) >> 18     x <      43699
  	 * (x * 0x3334) >> 17     x <      16389
  	 * (x * 0x199a) >> 16     x <      16389
  	 * (x * 0x0ccd) >> 15     x <      16389
  	 * (x * 0x0667) >> 14     x <       2739
  	 * (x * 0x0334) >> 13     x <       1029
  	 * (x * 0x019a) >> 12     x <       1029
  	 * (x * 0x00cd) >> 11     x <       1029 shorter code than * 0x67 (on i386)
  	 * (x * 0x0067) >> 10     x <        179
  	 * (x * 0x0034) >>  9     x <         69 same
  	 * (x * 0x001a) >>  8     x <         69 same
  	 * (x * 0x000d) >>  7     x <         69 same, shortest code (on i386)
  	 * (x * 0x0007) >>  6     x <         19
  	 * See <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
  	 */
  	r      = (q * (uint64_t)0x1999999a) >> 32;
  	*buf++ = (q - 10 * r) + '0'; /* 1 */
  	q      = (r * (uint64_t)0x1999999a) >> 32;
  	*buf++ = (r - 10 * q) + '0'; /* 2 */
  	r      = (q * (uint64_t)0x1999999a) >> 32;
  	*buf++ = (q - 10 * r) + '0'; /* 3 */
  	q      = (r * (uint64_t)0x1999999a) >> 32;
  	*buf++ = (r - 10 * q) + '0'; /* 4 */
  	r      = (q * (uint64_t)0x1999999a) >> 32;
  	*buf++ = (q - 10 * r) + '0'; /* 5 */
  	/* Now value is under 10000, can avoid 64-bit multiply */
  	q      = (r * 0x199a) >> 16;
  	*buf++ = (r - 10 * q)  + '0'; /* 6 */
  	r      = (q * 0xcd) >> 11;
  	*buf++ = (q - 10 * r)  + '0'; /* 7 */
  	q      = (r * 0xcd) >> 11;
  	*buf++ = (r - 10 * q) + '0'; /* 8 */
  	*buf++ = q + '0'; /* 9 */
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
161
162
  	return buf;
  }
133fd9f5c   Denys Vlasenko   vsprintf: further...
163
164
165
166
167
168
  #endif
  
  /* Similar to above but do not pad with zeros.
   * Code can be easily arranged to print 9 digits too, but our callers
   * always call put_dec_full9() instead when the number has 9 decimal digits.
   */
cf3b429b0   Joe Perches   vsprintf.c: use n...
169
  static noinline_for_stack
133fd9f5c   Denys Vlasenko   vsprintf: further...
170
  char *put_dec_trunc8(char *buf, unsigned r)
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
171
  {
133fd9f5c   Denys Vlasenko   vsprintf: further...
172
173
174
  	unsigned q;
  
  	/* Copy of previous function's body with added early returns */
cb239d0a9   George Spelvin   lib: vsprintf: op...
175
176
177
178
179
  	while (r >= 10000) {
  		q = r + '0';
  		r  = (r * (uint64_t)0x1999999a) >> 32;
  		*buf++ = q - 10*r;
  	}
f40005165   George Spelvin   lib: vsprintf: fi...
180
181
  	q      = (r * 0x199a) >> 16;	/* r <= 9999 */
  	*buf++ = (r - 10 * q)  + '0';
133fd9f5c   Denys Vlasenko   vsprintf: further...
182
183
  	if (q == 0)
  		return buf;
f40005165   George Spelvin   lib: vsprintf: fi...
184
185
  	r      = (q * 0xcd) >> 11;	/* q <= 999 */
  	*buf++ = (q - 10 * r)  + '0';
133fd9f5c   Denys Vlasenko   vsprintf: further...
186
187
  	if (r == 0)
  		return buf;
f40005165   George Spelvin   lib: vsprintf: fi...
188
189
  	q      = (r * 0xcd) >> 11;	/* r <= 99 */
  	*buf++ = (r - 10 * q) + '0';
133fd9f5c   Denys Vlasenko   vsprintf: further...
190
191
  	if (q == 0)
  		return buf;
f40005165   George Spelvin   lib: vsprintf: fi...
192
  	*buf++ = q + '0';		 /* q <= 9 */
133fd9f5c   Denys Vlasenko   vsprintf: further...
193
194
  	return buf;
  }
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
195

133fd9f5c   Denys Vlasenko   vsprintf: further...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
  /* There are two algorithms to print larger numbers.
   * One is generic: divide by 1000000000 and repeatedly print
   * groups of (up to) 9 digits. It's conceptually simple,
   * but requires a (unsigned long long) / 1000000000 division.
   *
   * Second algorithm splits 64-bit unsigned long long into 16-bit chunks,
   * manipulates them cleverly and generates groups of 4 decimal digits.
   * It so happens that it does NOT require long long division.
   *
   * If long is > 32 bits, division of 64-bit values is relatively easy,
   * and we will use the first algorithm.
   * If long long is > 64 bits (strange architecture with VERY large long long),
   * second algorithm can't be used, and we again use the first one.
   *
   * Else (if long is 32 bits and long long is 64 bits) we use second one.
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
212

133fd9f5c   Denys Vlasenko   vsprintf: further...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  #if BITS_PER_LONG != 32 || BITS_PER_LONG_LONG != 64
  
  /* First algorithm: generic */
  
  static
  char *put_dec(char *buf, unsigned long long n)
  {
  	if (n >= 100*1000*1000) {
  		while (n >= 1000*1000*1000)
  			buf = put_dec_full9(buf, do_div(n, 1000*1000*1000));
  		if (n >= 100*1000*1000)
  			return put_dec_full9(buf, n);
  	}
  	return put_dec_trunc8(buf, n);
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
227
  }
133fd9f5c   Denys Vlasenko   vsprintf: further...
228
229
230
231
  
  #else
  
  /* Second algorithm: valid only for 64-bit long longs */
e49317d41   George Spelvin   lib: vsprintf: op...
232
  /* See comment in put_dec_full9 for choice of constants */
cf3b429b0   Joe Perches   vsprintf.c: use n...
233
  static noinline_for_stack
2359172a7   George Spelvin   lib: vsprintf: op...
234
  void put_dec_full4(char *buf, unsigned q)
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
235
  {
133fd9f5c   Denys Vlasenko   vsprintf: further...
236
  	unsigned r;
e49317d41   George Spelvin   lib: vsprintf: op...
237
  	r      = (q * 0xccd) >> 15;
2359172a7   George Spelvin   lib: vsprintf: op...
238
  	buf[0] = (q - 10 * r) + '0';
e49317d41   George Spelvin   lib: vsprintf: op...
239
  	q      = (r * 0xcd) >> 11;
2359172a7   George Spelvin   lib: vsprintf: op...
240
  	buf[1] = (r - 10 * q)  + '0';
133fd9f5c   Denys Vlasenko   vsprintf: further...
241
  	r      = (q * 0xcd) >> 11;
2359172a7   George Spelvin   lib: vsprintf: op...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  	buf[2] = (q - 10 * r)  + '0';
  	buf[3] = r + '0';
  }
  
  /*
   * Call put_dec_full4 on x % 10000, return x / 10000.
   * The approximation x/10000 == (x * 0x346DC5D7) >> 43
   * holds for all x < 1,128,869,999.  The largest value this
   * helper will ever be asked to convert is 1,125,520,955.
   * (d1 in the put_dec code, assuming n is all-ones).
   */
  static
  unsigned put_dec_helper4(char *buf, unsigned x)
  {
          uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;
  
          put_dec_full4(buf, x - q * 10000);
          return q;
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
260
  }
133fd9f5c   Denys Vlasenko   vsprintf: further...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
  /* Based on code by Douglas W. Jones found at
   * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
   * (with permission from the author).
   * Performs no 64-bit division and hence should be fast on 32-bit machines.
   */
  static
  char *put_dec(char *buf, unsigned long long n)
  {
  	uint32_t d3, d2, d1, q, h;
  
  	if (n < 100*1000*1000)
  		return put_dec_trunc8(buf, n);
  
  	d1  = ((uint32_t)n >> 16); /* implicit "& 0xffff" */
  	h   = (n >> 32);
  	d2  = (h      ) & 0xffff;
  	d3  = (h >> 16); /* implicit "& 0xffff" */
  
  	q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
2359172a7   George Spelvin   lib: vsprintf: op...
280
281
282
283
284
285
286
  	q = put_dec_helper4(buf, q);
  
  	q += 7671 * d3 + 9496 * d2 + 6 * d1;
  	q = put_dec_helper4(buf+4, q);
  
  	q += 4749 * d3 + 42 * d2;
  	q = put_dec_helper4(buf+8, q);
133fd9f5c   Denys Vlasenko   vsprintf: further...
287

2359172a7   George Spelvin   lib: vsprintf: op...
288
289
290
291
292
  	q += 281 * d3;
  	buf += 12;
  	if (q)
  		buf = put_dec_trunc8(buf, q);
  	else while (buf[-1] == '0')
133fd9f5c   Denys Vlasenko   vsprintf: further...
293
294
295
296
297
298
  		--buf;
  
  	return buf;
  }
  
  #endif
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
299
300
301
302
303
304
305
306
  /*
   * Convert passed number to decimal string.
   * Returns the length of string.  On buffer overflow, returns 0.
   *
   * If speed is not important, use snprintf(). It's easy to read the code.
   */
  int num_to_str(char *buf, int size, unsigned long long num)
  {
133fd9f5c   Denys Vlasenko   vsprintf: further...
307
  	char tmp[sizeof(num) * 3];
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
308
  	int idx, len;
133fd9f5c   Denys Vlasenko   vsprintf: further...
309
310
311
312
313
314
315
  	/* put_dec() may work incorrectly for num = 0 (generate "", not "0") */
  	if (num <= 9) {
  		tmp[0] = '0' + num;
  		len = 1;
  	} else {
  		len = put_dec(tmp, num) - tmp;
  	}
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
316
317
318
319
320
  
  	if (len > size)
  		return 0;
  	for (idx = 0; idx < len; ++idx)
  		buf[idx] = tmp[len - idx - 1];
133fd9f5c   Denys Vlasenko   vsprintf: further...
321
  	return len;
1ac101a5d   KAMEZAWA Hiroyuki   procfs: add num_t...
322
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
  #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...
328
329
  #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
330

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
331
332
  enum format_type {
  	FORMAT_TYPE_NONE, /* Just a string part */
ed681a91a   Vegard Nossum   vsprintf: unify t...
333
  	FORMAT_TYPE_WIDTH,
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
334
335
336
337
338
339
340
341
342
  	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...
343
344
  	FORMAT_TYPE_UBYTE,
  	FORMAT_TYPE_BYTE,
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
345
346
347
348
349
350
351
352
353
354
  	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 ...
355
  	u8	type;		/* format_type enum */
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
356
  	u8	flags;		/* flags to number() */
4e310fda9   Joe Perches   vsprintf: Change ...
357
358
359
360
  	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...
361
  };
cf3b429b0   Joe Perches   vsprintf.c: use n...
362
363
364
  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
365
  {
9b706aee7   Denys Vlasenko   x86: trivial prin...
366
367
368
369
370
371
  	/* 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...
372
  	int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	int i;
7c2034223   Pierre Carrier   lib/vsprintf.c: "...
374
  	bool is_zero = num == 0LL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375

9b706aee7   Denys Vlasenko   x86: trivial prin...
376
377
  	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
  	 * produces same digits or (maybe lowercased) letters */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
378
379
380
  	locase = (spec.flags & SMALL);
  	if (spec.flags & LEFT)
  		spec.flags &= ~ZEROPAD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  	sign = 0;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
382
  	if (spec.flags & SIGN) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
383
  		if ((signed long long)num < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  			sign = '-';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
385
  			num = -(signed long long)num;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
386
387
  			spec.field_width--;
  		} else if (spec.flags & PLUS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
  			sign = '+';
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
389
390
  			spec.field_width--;
  		} else if (spec.flags & SPACE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  			sign = ' ';
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
392
  			spec.field_width--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
395
  	if (need_pfx) {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
396
  		if (spec.base == 16)
7c2034223   Pierre Carrier   lib/vsprintf.c: "...
397
398
  			spec.field_width -= 2;
  		else if (!is_zero)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
399
  			spec.field_width--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
401
402
  
  	/* generate full string in tmp[], in reverse order */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  	i = 0;
133fd9f5c   Denys Vlasenko   vsprintf: further...
404
405
  	if (num < spec.base)
  		tmp[i++] = digits[num] | locase;
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
406
407
  	/* Generic code, for any base:
  	else do {
9b706aee7   Denys Vlasenko   x86: trivial prin...
408
  		tmp[i++] = (digits[do_div(num,base)] | locase);
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
409
410
  	} while (num != 0);
  	*/
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
411
412
  	else if (spec.base != 10) { /* 8 or 16 */
  		int mask = spec.base - 1;
b39a73409   Denis Vlasenko   vsprintf.c: optim...
413
  		int shift = 3;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
414
415
416
  
  		if (spec.base == 16)
  			shift = 4;
b39a73409   Denis Vlasenko   vsprintf.c: optim...
417
  		do {
9b706aee7   Denys Vlasenko   x86: trivial prin...
418
  			tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
b39a73409   Denis Vlasenko   vsprintf.c: optim...
419
420
  			num >>= shift;
  		} while (num);
4277eedd7   Denis Vlasenko   vsprintf.c: optim...
421
422
423
  	} else { /* base 10 */
  		i = put_dec(tmp, num) - tmp;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
424
425
  
  	/* printing 100 using %2d gives "100", not "00" */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
426
427
  	if (i > spec.precision)
  		spec.precision = i;
b39a73409   Denis Vlasenko   vsprintf.c: optim...
428
  	/* leading space padding */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
429
430
  	spec.field_width -= spec.precision;
  	if (!(spec.flags & (ZEROPAD+LEFT))) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
431
  		while (--spec.field_width >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
432
  			if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
  				*buf = ' ';
  			++buf;
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
437
  	/* sign */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  	if (sign) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
439
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
442
  			*buf = sign;
  		++buf;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
443
444
  	/* "0x" / "0" prefix */
  	if (need_pfx) {
7c2034223   Pierre Carrier   lib/vsprintf.c: "...
445
446
447
448
449
  		if (spec.base == 16 || !is_zero) {
  			if (buf < end)
  				*buf = '0';
  			++buf;
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
450
  		if (spec.base == 16) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
451
  			if (buf < end)
9b706aee7   Denys Vlasenko   x86: trivial prin...
452
  				*buf = ('X' | locase);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
  			++buf;
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
456
  	/* zero or space padding */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
457
458
459
  	if (!(spec.flags & LEFT)) {
  		char c = (spec.flags & ZEROPAD) ? '0' : ' ';
  		while (--spec.field_width >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
460
  			if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
464
  				*buf = c;
  			++buf;
  		}
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
465
  	/* hmm even more zero padding? */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
466
  	while (i <= --spec.precision) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
467
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
  			*buf = '0';
  		++buf;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
471
472
  	/* actual digits of result */
  	while (--i >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
473
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
  			*buf = tmp[i];
  		++buf;
  	}
b39a73409   Denis Vlasenko   vsprintf.c: optim...
477
  	/* trailing space padding */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
478
  	while (--spec.field_width >= 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
479
  		if (buf < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
  			*buf = ' ';
  		++buf;
  	}
7b9186f5e   André Goddard Rosa   vsprintf: give it...
483

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
  	return buf;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
486
487
  static noinline_for_stack
  char *string(char *buf, char *end, const char *s, struct printf_spec spec)
0f9bfa569   Linus Torvalds   vsprintf: split o...
488
489
490
491
  {
  	int len, i;
  
  	if ((unsigned long)s < PAGE_SIZE)
0f4f81dce   André Goddard Rosa   vsprintf: factori...
492
  		s = "(null)";
0f9bfa569   Linus Torvalds   vsprintf: split o...
493

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

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
496
497
  	if (!(spec.flags & LEFT)) {
  		while (len < spec.field_width--) {
0f9bfa569   Linus Torvalds   vsprintf: split o...
498
499
500
501
502
503
504
505
506
507
  			if (buf < end)
  				*buf = ' ';
  			++buf;
  		}
  	}
  	for (i = 0; i < len; ++i) {
  		if (buf < end)
  			*buf = *s;
  		++buf; ++s;
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
508
  	while (len < spec.field_width--) {
0f9bfa569   Linus Torvalds   vsprintf: split o...
509
510
511
512
  		if (buf < end)
  			*buf = ' ';
  		++buf;
  	}
7b9186f5e   André Goddard Rosa   vsprintf: give it...
513

0f9bfa569   Linus Torvalds   vsprintf: split o...
514
515
  	return buf;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
516
517
518
  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...
519
520
521
522
  {
  	unsigned long value = (unsigned long) ptr;
  #ifdef CONFIG_KALLSYMS
  	char sym[KSYM_SYMBOL_LEN];
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
523
524
525
  	if (ext == 'B')
  		sprint_backtrace(sym, value);
  	else if (ext != 'f' && ext != 's')
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
526
527
  		sprint_symbol(sym, value);
  	else
4796dd200   Stephen Boyd   vsprintf: fix %ps...
528
  		sprint_symbol_no_offset(sym, value);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
529

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
530
  	return string(buf, end, sym, spec);
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
531
  #else
7b9186f5e   André Goddard Rosa   vsprintf: give it...
532
  	spec.field_width = 2 * sizeof(void *);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
533
534
  	spec.flags |= SPECIAL | SMALL | ZEROPAD;
  	spec.base = 16;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
535

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
536
  	return number(buf, end, value, spec);
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
537
538
  #endif
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
539
540
541
  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 ...
542
543
  {
  #ifndef IO_RSRC_PRINTK_SIZE
284053722   Bjorn Helgaas   vsprintf: fix io/...
544
  #define IO_RSRC_PRINTK_SIZE	6
332d2e783   Linus Torvalds   Implement %pR to ...
545
546
547
  #endif
  
  #ifndef MEM_RSRC_PRINTK_SIZE
284053722   Bjorn Helgaas   vsprintf: fix io/...
548
  #define MEM_RSRC_PRINTK_SIZE	10
332d2e783   Linus Torvalds   Implement %pR to ...
549
  #endif
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
550
  	static const struct printf_spec io_spec = {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
551
  		.base = 16,
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
552
  		.field_width = IO_RSRC_PRINTK_SIZE,
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
553
554
555
  		.precision = -1,
  		.flags = SPECIAL | SMALL | ZEROPAD,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
556
557
558
559
560
561
  	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...
562
563
564
565
566
567
  	static const struct printf_spec bus_spec = {
  		.base = 16,
  		.field_width = 2,
  		.precision = -1,
  		.flags = SMALL | ZEROPAD,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
568
  	static const struct printf_spec dec_spec = {
c91d3376e   Bjorn Helgaas   vsprintf: add %pR...
569
570
571
572
  		.base = 10,
  		.precision = -1,
  		.flags = 0,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
573
  	static const struct printf_spec str_spec = {
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
574
575
576
577
  		.field_width = -1,
  		.precision = 10,
  		.flags = LEFT,
  	};
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
578
  	static const struct printf_spec flag_spec = {
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
579
580
581
582
  		.base = 16,
  		.precision = -1,
  		.flags = SPECIAL | SMALL,
  	};
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
583
584
585
586
587
  
  	/* 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...
588
  #define DECODED_BUF_SIZE	sizeof("[mem - 64bit pref window disabled]")
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
589
590
591
  #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 ...
592
  	char *p = sym, *pend = sym + sizeof(sym);
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
593
  	int decode = (fmt[0] == 'R') ? 1 : 0;
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
594
  	const struct printf_spec *specp;
332d2e783   Linus Torvalds   Implement %pR to ...
595
596
  
  	*p++ = '[';
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
597
  	if (res->flags & IORESOURCE_IO) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
598
  		p = string(p, pend, "io  ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
599
600
  		specp = &io_spec;
  	} else if (res->flags & IORESOURCE_MEM) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
601
  		p = string(p, pend, "mem ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
602
603
  		specp = &mem_spec;
  	} else if (res->flags & IORESOURCE_IRQ) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
604
  		p = string(p, pend, "irq ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
605
606
  		specp = &dec_spec;
  	} else if (res->flags & IORESOURCE_DMA) {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
607
  		p = string(p, pend, "dma ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
608
  		specp = &dec_spec;
0f4050c7d   Bjorn Helgaas   resource: add bus...
609
610
611
  	} else if (res->flags & IORESOURCE_BUS) {
  		p = string(p, pend, "bus ", str_spec);
  		specp = &bus_spec;
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
612
  	} else {
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
613
  		p = string(p, pend, "??? ", str_spec);
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
614
  		specp = &mem_spec;
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
615
  		decode = 0;
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
616
  	}
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
617
  	p = number(p, pend, res->start, *specp);
c91d3376e   Bjorn Helgaas   vsprintf: add %pR...
618
619
  	if (res->start != res->end) {
  		*p++ = '-';
4da0b66c6   Bjorn Helgaas   vsprintf: move %p...
620
  		p = number(p, pend, res->end, *specp);
c91d3376e   Bjorn Helgaas   vsprintf: add %pR...
621
  	}
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
622
  	if (decode) {
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
623
624
625
626
  		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...
627
628
  		if (res->flags & IORESOURCE_WINDOW)
  			p = string(p, pend, " window", str_spec);
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
629
630
  		if (res->flags & IORESOURCE_DISABLED)
  			p = string(p, pend, " disabled", str_spec);
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
631
632
633
  	} else {
  		p = string(p, pend, " flags ", str_spec);
  		p = number(p, pend, res->flags, flag_spec);
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
634
  	}
332d2e783   Linus Torvalds   Implement %pR to ...
635
  	*p++ = ']';
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
636
  	*p = '\0';
332d2e783   Linus Torvalds   Implement %pR to ...
637

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
638
  	return string(buf, end, sym, spec);
332d2e783   Linus Torvalds   Implement %pR to ...
639
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
640
  static noinline_for_stack
31550a16a   Andy Shevchenko   vsprintf: add sup...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
  char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
  		 const char *fmt)
  {
  	int i, len = 1;		/* if we pass '%ph[CDN]', field witdh remains
  				   negative value, fallback to the default */
  	char separator;
  
  	if (spec.field_width == 0)
  		/* nothing to print */
  		return buf;
  
  	if (ZERO_OR_NULL_PTR(addr))
  		/* NULL pointer */
  		return string(buf, end, NULL, spec);
  
  	switch (fmt[1]) {
  	case 'C':
  		separator = ':';
  		break;
  	case 'D':
  		separator = '-';
  		break;
  	case 'N':
  		separator = 0;
  		break;
  	default:
  		separator = ' ';
  		break;
  	}
  
  	if (spec.field_width > 0)
  		len = min_t(int, spec.field_width, 64);
  
  	for (i = 0; i < len && buf < end - 1; i++) {
  		buf = hex_byte_pack(buf, addr[i]);
  
  		if (buf < end && separator && i != len - 1)
  			*buf++ = separator;
  	}
  
  	return buf;
  }
  
  static noinline_for_stack
cf3b429b0   Joe Perches   vsprintf.c: use n...
685
686
  char *mac_address_string(char *buf, char *end, u8 *addr,
  			 struct printf_spec spec, const char *fmt)
dd45c9cf6   Harvey Harrison   printk: add %pM f...
687
  {
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
688
  	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
dd45c9cf6   Harvey Harrison   printk: add %pM f...
689
690
  	char *p = mac_addr;
  	int i;
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
691
  	char separator;
76597ff98   Andrei Emeltchenko   vsprintf: add %pM...
692
  	bool reversed = false;
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
693

76597ff98   Andrei Emeltchenko   vsprintf: add %pM...
694
695
  	switch (fmt[1]) {
  	case 'F':
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
696
  		separator = '-';
76597ff98   Andrei Emeltchenko   vsprintf: add %pM...
697
698
699
700
701
702
703
  		break;
  
  	case 'R':
  		reversed = true;
  		/* fall through */
  
  	default:
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
704
  		separator = ':';
76597ff98   Andrei Emeltchenko   vsprintf: add %pM...
705
  		break;
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
706
  	}
dd45c9cf6   Harvey Harrison   printk: add %pM f...
707
708
  
  	for (i = 0; i < 6; i++) {
76597ff98   Andrei Emeltchenko   vsprintf: add %pM...
709
710
711
712
  		if (reversed)
  			p = hex_byte_pack(p, addr[5 - i]);
  		else
  			p = hex_byte_pack(p, addr[i]);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
713
  		if (fmt[0] == 'M' && i != 5)
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
714
  			*p++ = separator;
dd45c9cf6   Harvey Harrison   printk: add %pM f...
715
716
  	}
  	*p = '\0';
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
717
  	return string(buf, end, mac_addr, spec);
dd45c9cf6   Harvey Harrison   printk: add %pM f...
718
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
719
720
  static noinline_for_stack
  char *ip4_string(char *p, const u8 *addr, const char *fmt)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
721
722
  {
  	int i;
0159f24ee   Joe Perches   lib/vsprintf.c: A...
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
  	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...
748
749
  	for (i = 0; i < 4; i++) {
  		char temp[3];	/* hold each IP quad in reverse order */
133fd9f5c   Denys Vlasenko   vsprintf: further...
750
  		int digits = put_dec_trunc8(temp, addr[index]) - temp;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
751
752
753
754
755
756
757
758
759
760
761
  		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...
762
  		index += step;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
763
  	}
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
764
  	*p = '\0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
765

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
766
767
  	return p;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
768
769
  static noinline_for_stack
  char *ip6_compressed_string(char *p, const char *addr)
689afa7da   Harvey Harrison   printk: add %p6 f...
770
  {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
771
  	int i, j, range;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
772
773
774
775
  	unsigned char zerolength[8];
  	int longest = 1;
  	int colonpos = -1;
  	u16 word;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
776
  	u8 hi, lo;
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
777
  	bool needcolon = false;
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
778
779
780
781
782
783
  	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...
784
785
786
787
788
789
790
791
792
793
794
  
  	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...
795
  			if (in6.s6_addr16[j] != 0)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
796
797
798
799
800
801
802
803
804
805
  				break;
  			zerolength[i]++;
  		}
  	}
  	for (i = 0; i < range; i++) {
  		if (zerolength[i] > longest) {
  			longest = zerolength[i];
  			colonpos = i;
  		}
  	}
29cf519ee   Joe Perches   vsprintf: Update ...
806
807
  	if (longest == 1)		/* don't compress a single 0 */
  		colonpos = -1;
689afa7da   Harvey Harrison   printk: add %p6 f...
808

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  	/* 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...
824
  		word = ntohs(in6.s6_addr16[i]);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
825
826
827
828
  		hi = word >> 8;
  		lo = word & 0xff;
  		if (hi) {
  			if (hi > 0x0f)
55036ba76   Andy Shevchenko   lib: rename pack_...
829
  				p = hex_byte_pack(p, hi);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
830
831
  			else
  				*p++ = hex_asc_lo(hi);
55036ba76   Andy Shevchenko   lib: rename pack_...
832
  			p = hex_byte_pack(p, lo);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
833
  		}
b5ff992b0   André Goddard Rosa   vsprintf: reduce ...
834
  		else if (lo > 0x0f)
55036ba76   Andy Shevchenko   lib: rename pack_...
835
  			p = hex_byte_pack(p, lo);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
836
837
838
839
840
841
842
843
  		else
  			*p++ = hex_asc_lo(lo);
  		needcolon = true;
  	}
  
  	if (useIPv4) {
  		if (needcolon)
  			*p++ = ':';
0159f24ee   Joe Perches   lib/vsprintf.c: A...
844
  		p = ip4_string(p, &in6.s6_addr[12], "I4");
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
845
  	}
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
846
  	*p = '\0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
847

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
848
849
  	return p;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
850
851
  static noinline_for_stack
  char *ip6_string(char *p, const char *addr, const char *fmt)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
852
853
  {
  	int i;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
854

689afa7da   Harvey Harrison   printk: add %p6 f...
855
  	for (i = 0; i < 8; i++) {
55036ba76   Andy Shevchenko   lib: rename pack_...
856
857
  		p = hex_byte_pack(p, *addr++);
  		p = hex_byte_pack(p, *addr++);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
858
  		if (fmt[0] == 'I' && i != 7)
689afa7da   Harvey Harrison   printk: add %p6 f...
859
860
861
  			*p++ = ':';
  	}
  	*p = '\0';
7b9186f5e   André Goddard Rosa   vsprintf: give it...
862

8a27f7c90   Joe Perches   lib/vsprintf.c: A...
863
864
  	return p;
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
865
866
867
  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...
868
869
870
871
  {
  	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...
872
  		ip6_compressed_string(ip6_addr, addr);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
873
  	else
eb78cd26b   Joe Perches   lib/vsprintf.c: A...
874
  		ip6_string(ip6_addr, addr, fmt);
689afa7da   Harvey Harrison   printk: add %p6 f...
875

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
876
  	return string(buf, end, ip6_addr, spec);
689afa7da   Harvey Harrison   printk: add %p6 f...
877
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
878
879
880
  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, ...
881
  {
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
882
  	char ip4_addr[sizeof("255.255.255.255")];
4aa996066   Harvey Harrison   printk: add %I4, ...
883

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

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
886
  	return string(buf, end, ip4_addr, spec);
4aa996066   Harvey Harrison   printk: add %I4, ...
887
  }
cf3b429b0   Joe Perches   vsprintf.c: use n...
888
889
890
  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...
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  {
  	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_...
912
  		p = hex_byte_pack(p, addr[index[i]]);
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  		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...
934
935
936
937
938
939
940
941
942
943
944
  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...
945
  int kptr_restrict __read_mostly;
455cd5ab3   Dan Rosenberg   kptr_restrict for...
946

4d8a743cd   Linus Torvalds   vsprintf: add inf...
947
948
949
950
951
  /*
   * 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 ...
952
953
   * Right now we handle:
   *
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
954
955
   * - 'F' For symbolic function descriptor pointers with offset
   * - 'f' For simple symbolic function names without offset
0efb4d207   Steven Rostedt   vsnprintf: remove...
956
957
   * - 'S' For symbolic direct pointers with offset
   * - 's' For symbolic direct pointers without offset
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
958
   * - 'B' For backtraced symbolic direct pointers with offset
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
959
960
   * - '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...
961
962
   * - '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...
963
   * - 'm' For a 6-byte MAC address, it prints the hex address without colons
bc7259a2c   Joe Perches   lib/vsprintf.c: A...
964
   * - 'MF' For a 6-byte MAC FDDI address, it prints the address
c8e000604   Joe Perches   lib: Kill bit-rev...
965
   *       with a dash-separated hex notation
7c59154e7   Andy Shevchenko   lib/vsprintf: upd...
966
   * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
967
968
969
970
971
972
   * - '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...
973
   * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
974
   * - 'I6c' for IPv6 addresses printed as specified by
29cf519ee   Joe Perches   vsprintf: Update ...
975
   *       http://tools.ietf.org/html/rfc5952
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
976
977
978
979
980
981
982
983
984
985
986
   * - '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...
987
988
989
990
991
   * - '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...
992
   * - 'K' For a kernel pointer that should be hidden from unprivileged users
c8f44affb   Michał Mirosław   net: introduce an...
993
   * - 'NF' For a netdev_features_t
31550a16a   Andy Shevchenko   vsprintf: add sup...
994
995
996
997
998
999
1000
   * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with
   *            a certain separator (' ' by default):
   *              C colon
   *              D dash
   *              N no separator
   *            The maximum supported length is 64 bytes of the input. Consider
   *            to use print_hex_dump() for the larger input.
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
1001
   *
332d2e783   Linus Torvalds   Implement %pR to ...
1002
1003
1004
   * 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...
1005
   */
cf3b429b0   Joe Perches   vsprintf.c: use n...
1006
1007
1008
  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...
1009
  {
725fe002d   Grant Likely   vsprintf: correct...
1010
  	int default_width = 2 * sizeof(void *) + (spec.flags & SPECIAL ? 2 : 0);
9f36e2c44   Kees Cook   printk: use %pK f...
1011
  	if (!ptr && *fmt != 'K') {
5e0579812   Joe Perches   vsprintf.c: use d...
1012
1013
1014
1015
1016
  		/*
  		 * Print (null) with the same width as a pointer so it makes
  		 * tabular output look nice.
  		 */
  		if (spec.field_width == -1)
725fe002d   Grant Likely   vsprintf: correct...
1017
  			spec.field_width = default_width;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1018
  		return string(buf, end, "(null)", spec);
5e0579812   Joe Perches   vsprintf.c: use d...
1019
  	}
d97106ab5   Linus Torvalds   Make %p print '(n...
1020

0fe1ef24f   Linus Torvalds   vsprintf: add sup...
1021
1022
  	switch (*fmt) {
  	case 'F':
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
1023
  	case 'f':
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
1024
1025
1026
  		ptr = dereference_function_descriptor(ptr);
  		/* Fallthrough */
  	case 'S':
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
1027
  	case 's':
0f77a8d37   Namhyung Kim   vsprintf: Introdu...
1028
  	case 'B':
0c8b946e3   Frederic Weisbecker   vsprintf: introdu...
1029
  		return symbol_string(buf, end, ptr, spec, *fmt);
332d2e783   Linus Torvalds   Implement %pR to ...
1030
  	case 'R':
c7dabef8a   Bjorn Helgaas   vsprintf: use %pR...
1031
  	case 'r':
fd95541e2   Bjorn Helgaas   vsprintf: add %pR...
1032
  		return resource_string(buf, end, ptr, spec, fmt);
31550a16a   Andy Shevchenko   vsprintf: add sup...
1033
1034
  	case 'h':
  		return hex_string(buf, end, ptr, spec, fmt);
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
1035
1036
  	case 'M':			/* Colon separated: 00:01:02:03:04:05 */
  	case 'm':			/* Contiguous: 000102030405 */
76597ff98   Andrei Emeltchenko   vsprintf: add %pM...
1037
1038
  					/* [mM]F (FDDI) */
  					/* [mM]R (Reverse order; Bluetooth) */
8a27f7c90   Joe Perches   lib/vsprintf.c: A...
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
  		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...
1055
  		break;
9ac6e44ee   Joe Perches   lib/vsprintf.c: a...
1056
1057
  	case 'U':
  		return uuid_string(buf, end, ptr, spec, fmt);
7db6f5fb6   Joe Perches   vsprintf: Recursi...
1058
  	case 'V':
5756b76e4   Jan Beulich   vsprintf: make %p...
1059
1060
1061
1062
1063
1064
1065
1066
1067
  		{
  			va_list va;
  
  			va_copy(va, *((struct va_format *)ptr)->va);
  			buf += vsnprintf(buf, end > buf ? end - buf : 0,
  					 ((struct va_format *)ptr)->fmt, va);
  			va_end(va);
  			return buf;
  		}
455cd5ab3   Dan Rosenberg   kptr_restrict for...
1068
1069
1070
1071
1072
  	case 'K':
  		/*
  		 * %pK cannot be used in IRQ context because its test
  		 * for CAP_SYSLOG would be meaningless.
  		 */
3715c5309   Dan Rosenberg   lib/vsprintf.c: k...
1073
1074
  		if (kptr_restrict && (in_irq() || in_serving_softirq() ||
  				      in_nmi())) {
455cd5ab3   Dan Rosenberg   kptr_restrict for...
1075
  			if (spec.field_width == -1)
725fe002d   Grant Likely   vsprintf: correct...
1076
  				spec.field_width = default_width;
455cd5ab3   Dan Rosenberg   kptr_restrict for...
1077
  			return string(buf, end, "pK-error", spec);
455cd5ab3   Dan Rosenberg   kptr_restrict for...
1078
  		}
26297607e   Joe Perches   vsprintf: neaten ...
1079
1080
1081
1082
1083
  		if (!((kptr_restrict == 0) ||
  		      (kptr_restrict == 1 &&
  		       has_capability_noaudit(current, CAP_SYSLOG))))
  			ptr = NULL;
  		break;
c8f44affb   Michał Mirosław   net: introduce an...
1084
1085
1086
1087
1088
1089
  	case 'N':
  		switch (fmt[1]) {
  		case 'F':
  			return netdev_feature_string(buf, end, ptr, spec);
  		}
  		break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1090
1091
1092
  	}
  	spec.flags |= SMALL;
  	if (spec.field_width == -1) {
725fe002d   Grant Likely   vsprintf: correct...
1093
  		spec.field_width = default_width;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
  		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...
1121
1122
  static noinline_for_stack
  int format_decode(const char *fmt, struct printf_spec *spec)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1123
1124
  {
  	const char *start = fmt;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1125
1126
  
  	/* we finished early by reading the field width */
ed681a91a   Vegard Nossum   vsprintf: unify t...
1127
  	if (spec->type == FORMAT_TYPE_WIDTH) {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
  		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...
1185
  		spec->type = FORMAT_TYPE_WIDTH;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
  		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...
1200
  			spec->type = FORMAT_TYPE_PRECISION;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1201
1202
1203
1204
1205
1206
1207
  			return ++fmt - start;
  		}
  	}
  
  qualifier:
  	/* get the conversion qualifier */
  	spec->qualifier = -1;
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1208
1209
  	if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
  	    _tolower(*fmt) == 'z' || *fmt == 't') {
a4e94ef0d   Zhaolei   printk: add suppo...
1210
1211
1212
1213
1214
1215
1216
1217
1218
  		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...
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
  		}
  	}
  
  	/* 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...
1260
  		spec->flags |= SIGN;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1261
  	case 'u':
4aa996066   Harvey Harrison   printk: add %I4, ...
1262
  		break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1263
1264
1265
1266
  
  	default:
  		spec->type = FORMAT_TYPE_INVALID;
  		return fmt - start;
0fe1ef24f   Linus Torvalds   vsprintf: add sup...
1267
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1268
1269
1270
1271
  
  	if (spec->qualifier == 'L')
  		spec->type = FORMAT_TYPE_LONG_LONG;
  	else if (spec->qualifier == 'l') {
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1272
  		if (spec->flags & SIGN)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1273
1274
1275
  			spec->type = FORMAT_TYPE_LONG;
  		else
  			spec->type = FORMAT_TYPE_ULONG;
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1276
  	} else if (_tolower(spec->qualifier) == 'z') {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1277
1278
1279
  		spec->type = FORMAT_TYPE_SIZE_T;
  	} else if (spec->qualifier == 't') {
  		spec->type = FORMAT_TYPE_PTRDIFF;
a4e94ef0d   Zhaolei   printk: add suppo...
1280
1281
1282
1283
1284
  	} 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...
1285
  	} else if (spec->qualifier == 'h') {
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1286
  		if (spec->flags & SIGN)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1287
1288
1289
1290
  			spec->type = FORMAT_TYPE_SHORT;
  		else
  			spec->type = FORMAT_TYPE_USHORT;
  	} else {
39e874f8a   Frederic Weisbecker   vsprintf: fix bug...
1291
  		if (spec->flags & SIGN)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1292
1293
1294
  			spec->type = FORMAT_TYPE_INT;
  		else
  			spec->type = FORMAT_TYPE_UINT;
78a8bf69b   Linus Torvalds   vsprintf: split o...
1295
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1296
1297
  
  	return ++fmt - start;
78a8bf69b   Linus Torvalds   vsprintf: split o...
1298
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
1300
1301
1302
1303
1304
1305
  /**
   * 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...
1306
   * This function follows C99 vsnprintf, but has some extensions:
91adcd2c4   Steven Rostedt   vsprintf: add %ps...
1307
1308
   * %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...
1309
1310
   * %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...
1311
   * %pB output the name of a backtrace symbol with its offset
8a79503aa   Uwe Kleine-König   lib/vsprintf.c: d...
1312
1313
1314
   * %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
7c59154e7   Andy Shevchenko   lib/vsprintf: upd...
1315
1316
   * %pMR output a 6-byte MAC address with colons in reversed order
   * %pMF output a 6-byte MAC address with dashes
8a79503aa   Uwe Kleine-König   lib/vsprintf.c: d...
1317
   * %pm output a 6-byte MAC address without colons
7c59154e7   Andy Shevchenko   lib/vsprintf: upd...
1318
   * %pmR output a 6-byte MAC address without colons in reversed order
8a79503aa   Uwe Kleine-König   lib/vsprintf.c: d...
1319
1320
1321
1322
   * %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...
1323
   * %pI6c print an IPv6 address as specified by RFC 5952
8a79503aa   Uwe Kleine-König   lib/vsprintf.c: d...
1324
1325
   * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
   *   case.
31550a16a   Andy Shevchenko   vsprintf: add sup...
1326
1327
   * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
   *           bytes of the input)
0efb4d207   Steven Rostedt   vsnprintf: remove...
1328
   * %n is ignored
20036fdca   Andi Kleen   Add kerneldoc doc...
1329
   *
80f548e04   Andrew Morton   lib/vsprintf.c: r...
1330
1331
   * ** Please update Documentation/printk-formats.txt when making changes **
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1332
1333
1334
1335
   * 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 ...
1336
   * (not including the trailing '\0'), use vscnprintf(). If the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
1338
1339
   * return is greater than or equal to @size, the resulting
   * string is truncated.
   *
ba1835eb3   Uwe Kleine-König   vsprintf: make co...
1340
   * If you're not already dealing with a va_list consider using snprintf().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
1343
   */
  int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
  	unsigned long long num;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1345
  	char *str, *end;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1346
  	struct printf_spec spec = {0};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1348
1349
  	/* Reject out-of-range values early.  Large positive sizes are
  	   used for unknown buffer sizes. */
2f30b1f9e   Marcin Slusarz   vsprintf: use WAR...
1350
  	if (WARN_ON_ONCE((int) size < 0))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
  
  	str = buf;
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1354
  	end = buf + size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1356
1357
1358
1359
  	/* Make sure end is always >= buf */
  	if (end < buf) {
  		end = ((void *)-1);
  		size = end - buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1361
1362
  	while (*fmt) {
  		const char *old_fmt = fmt;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1363
  		int read = format_decode(fmt, &spec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364

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

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1367
1368
1369
1370
1371
1372
1373
  		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
1374
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1375
1376
  			str += read;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
  		}
ed681a91a   Vegard Nossum   vsprintf: unify t...
1378
  		case FORMAT_TYPE_WIDTH:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1379
1380
  			spec.field_width = va_arg(args, int);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1382
1383
1384
  		case FORMAT_TYPE_PRECISION:
  			spec.precision = va_arg(args, int);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385

d4be151b2   André Goddard Rosa   vsprintf: move lo...
1386
1387
  		case FORMAT_TYPE_CHAR: {
  			char c;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1388
1389
  			if (!(spec.flags & LEFT)) {
  				while (--spec.field_width > 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1390
  					if (str < end)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391
1392
  						*str = ' ';
  					++str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1393

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1394
1395
1396
1397
1398
1399
1400
  				}
  			}
  			c = (unsigned char) va_arg(args, int);
  			if (str < end)
  				*str = c;
  			++str;
  			while (--spec.field_width > 0) {
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1401
  				if (str < end)
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1402
  					*str = ' ';
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1403
  				++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1404
1405
  			}
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1406
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407

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

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1412
1413
1414
1415
1416
1417
  		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
1418

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1419
1420
1421
1422
1423
  		case FORMAT_TYPE_PERCENT_CHAR:
  			if (str < end)
  				*str = '%';
  			++str;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1425
1426
1427
1428
  		case FORMAT_TYPE_INVALID:
  			if (str < end)
  				*str = '%';
  			++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1429
1430
1431
  			break;
  
  		case FORMAT_TYPE_NRCHARS: {
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
1432
  			u8 qualifier = spec.qualifier;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1433
1434
1435
1436
  
  			if (qualifier == 'l') {
  				long *ip = va_arg(args, long *);
  				*ip = (str - buf);
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1437
  			} else if (_tolower(qualifier) == 'z') {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1438
1439
1440
1441
1442
1443
1444
  				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
1445
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
  
  		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...
1464
1465
1466
1467
1468
1469
  			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...
1470
1471
1472
1473
1474
1475
  			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...
1476
1477
  			case FORMAT_TYPE_INT:
  				num = (int) va_arg(args, int);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1478
1479
1480
1481
1482
1483
  				break;
  			default:
  				num = va_arg(args, unsigned int);
  			}
  
  			str = number(str, end, num, spec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1484
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1485
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1486

f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1487
1488
1489
1490
  	if (size > 0) {
  		if (str < end)
  			*str = '\0';
  		else
0a6047eef   Linus Torvalds   Fix vsnprintf off...
1491
  			end[-1] = '\0';
f796937a0   Jeremy Fitzhardinge   [PATCH] Fix bound...
1492
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1493

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1497
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  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...
1508
   * the @buf not including the trailing '\0'. If @size is == 0 the function
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509
1510
   * returns 0.
   *
ba1835eb3   Uwe Kleine-König   vsprintf: make co...
1511
   * If you're not already dealing with a va_list consider using scnprintf().
20036fdca   Andi Kleen   Add kerneldoc doc...
1512
1513
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1514
1515
1516
1517
   */
  int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
  {
  	int i;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1518
  	i = vsnprintf(buf, size, fmt, args);
b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1519
1520
1521
1522
1523
  	if (likely(i < size))
  		return i;
  	if (size != 0)
  		return size - 1;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1524
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
  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...
1538
1539
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1540
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1541
  int snprintf(char *buf, size_t size, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1542
1543
1544
1545
1546
  {
  	va_list args;
  	int i;
  
  	va_start(args, fmt);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1547
  	i = vsnprintf(buf, size, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1549

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1550
1551
  	return i;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
  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...
1562
   * the trailing '\0'. If @size is == 0 the function returns 0.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1563
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1564
  int scnprintf(char *buf, size_t size, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1565
1566
1567
1568
1569
  {
  	va_list args;
  	int i;
  
  	va_start(args, fmt);
b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1570
  	i = vscnprintf(buf, size, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1571
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1572

b921c69fb   Anton Arapov   lib/vsprintf.c: f...
1573
  	return i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  }
  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 ...
1584
   * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585
1586
   * buffer overflows.
   *
ba1835eb3   Uwe Kleine-König   vsprintf: make co...
1587
   * If you're not already dealing with a va_list consider using sprintf().
20036fdca   Andi Kleen   Add kerneldoc doc...
1588
1589
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1590
1591
1592
1593
1594
   */
  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
1595
1596
1597
1598
1599
1600
1601
1602
1603
  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 ...
1604
   * into @buf. Use snprintf() or scnprintf() in order to avoid
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1605
   * buffer overflows.
20036fdca   Andi Kleen   Add kerneldoc doc...
1606
1607
   *
   * See the vsnprintf() documentation for format string extensions over C99.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
   */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1609
  int sprintf(char *buf, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1610
1611
1612
1613
1614
  {
  	va_list args;
  	int i;
  
  	va_start(args, fmt);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1615
  	i = vsnprintf(buf, INT_MAX, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
1617

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
1619
  	return i;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1620
  EXPORT_SYMBOL(sprintf);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
  #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...
1647
  	struct printf_spec spec = {0};
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1648
  	char *str, *end;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
  
  	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...
1672
  	while (*fmt) {
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1673
  		int read = format_decode(fmt, &spec);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1674

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

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1677
1678
  		switch (spec.type) {
  		case FORMAT_TYPE_NONE:
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1679
1680
  		case FORMAT_TYPE_INVALID:
  		case FORMAT_TYPE_PERCENT_CHAR:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1681
  			break;
ed681a91a   Vegard Nossum   vsprintf: unify t...
1682
  		case FORMAT_TYPE_WIDTH:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1683
1684
1685
1686
1687
  		case FORMAT_TYPE_PRECISION:
  			save_arg(int);
  			break;
  
  		case FORMAT_TYPE_CHAR:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1688
  			save_arg(char);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1689
1690
1691
  			break;
  
  		case FORMAT_TYPE_STR: {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1692
1693
  			const char *save_str = va_arg(args, char *);
  			size_t len;
6c3566341   André Goddard Rosa   vsprintf: pre-cal...
1694

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1695
1696
  			if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE
  					|| (unsigned long)save_str < PAGE_SIZE)
0f4f81dce   André Goddard Rosa   vsprintf: factori...
1697
  				save_str = "(null)";
6c3566341   André Goddard Rosa   vsprintf: pre-cal...
1698
1699
1700
1701
  			len = strlen(save_str) + 1;
  			if (str + len < end)
  				memcpy(str, save_str, len);
  			str += len;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1702
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1703
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1704
1705
  
  		case FORMAT_TYPE_PTR:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1706
1707
  			save_arg(void *);
  			/* skip all alphanumeric pointer suffixes */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1708
  			while (isalnum(*fmt))
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1709
  				fmt++;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1710
  			break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1711
  		case FORMAT_TYPE_NRCHARS: {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1712
  			/* skip %n 's argument */
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
1713
  			u8 qualifier = spec.qualifier;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1714
1715
1716
  			void *skip_arg;
  			if (qualifier == 'l')
  				skip_arg = va_arg(args, long *);
75fb8f269   Andy Shevchenko   lib: make _tolowe...
1717
  			else if (_tolower(qualifier) == 'z')
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1718
1719
1720
  				skip_arg = va_arg(args, size_t *);
  			else
  				skip_arg = va_arg(args, int *);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1721
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1722
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1723
1724
1725
1726
1727
  
  		default:
  			switch (spec.type) {
  
  			case FORMAT_TYPE_LONG_LONG:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1728
  				save_arg(long long);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1729
1730
1731
  				break;
  			case FORMAT_TYPE_ULONG:
  			case FORMAT_TYPE_LONG:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1732
  				save_arg(unsigned long);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1733
1734
  				break;
  			case FORMAT_TYPE_SIZE_T:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1735
  				save_arg(size_t);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1736
1737
  				break;
  			case FORMAT_TYPE_PTRDIFF:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1738
  				save_arg(ptrdiff_t);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1739
  				break;
a4e94ef0d   Zhaolei   printk: add suppo...
1740
1741
1742
1743
  			case FORMAT_TYPE_UBYTE:
  			case FORMAT_TYPE_BYTE:
  				save_arg(char);
  				break;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1744
1745
  			case FORMAT_TYPE_USHORT:
  			case FORMAT_TYPE_SHORT:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1746
  				save_arg(short);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1747
1748
  				break;
  			default:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1749
  				save_arg(int);
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1750
  			}
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1751
1752
  		}
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1753

7b9186f5e   André Goddard Rosa   vsprintf: give it...
1754
  	return (u32 *)(PTR_ALIGN(str, sizeof(u32))) - bin_buf;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1755
  #undef save_arg
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
  }
  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...
1771
   *  see vsnprintf comment for details.
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
   *
   * 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...
1783
  	struct printf_spec spec = {0};
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1784
1785
  	char *str, *end;
  	const char *args = (const char *)bin_buf;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1786

2f30b1f9e   Marcin Slusarz   vsprintf: use WAR...
1787
  	if (WARN_ON_ONCE((int) size < 0))
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1788
  		return 0;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
  
  	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...
1813
  	while (*fmt) {
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1814
  		const char *old_fmt = fmt;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1815
  		int read = format_decode(fmt, &spec);
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1816

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

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1819
1820
1821
1822
1823
1824
1825
  		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...
1826
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1827
1828
  			str += read;
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1829
  		}
ed681a91a   Vegard Nossum   vsprintf: unify t...
1830
  		case FORMAT_TYPE_WIDTH:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1831
1832
  			spec.field_width = get_arg(int);
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1833

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1834
1835
1836
  		case FORMAT_TYPE_PRECISION:
  			spec.precision = get_arg(int);
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1837

d4be151b2   André Goddard Rosa   vsprintf: move lo...
1838
1839
  		case FORMAT_TYPE_CHAR: {
  			char c;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1840
1841
  			if (!(spec.flags & LEFT)) {
  				while (--spec.field_width > 0) {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1842
1843
1844
1845
1846
1847
1848
1849
1850
  					if (str < end)
  						*str = ' ';
  					++str;
  				}
  			}
  			c = (unsigned char) get_arg(char);
  			if (str < end)
  				*str = c;
  			++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1851
  			while (--spec.field_width > 0) {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1852
1853
1854
1855
  				if (str < end)
  					*str = ' ';
  				++str;
  			}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1856
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1857
  		}
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1858

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1859
  		case FORMAT_TYPE_STR: {
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1860
  			const char *str_arg = args;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1861
  			args += strlen(str_arg) + 1;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1862
1863
  			str = string(str, end, (char *)str_arg, spec);
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1864
  		}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1865
1866
1867
  		case FORMAT_TYPE_PTR:
  			str = pointer(fmt+1, str, end, get_arg(void *), spec);
  			while (isalnum(*fmt))
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1868
  				fmt++;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1869
  			break;
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1870

fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1871
  		case FORMAT_TYPE_PERCENT_CHAR:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1872
  		case FORMAT_TYPE_INVALID:
4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1873
1874
1875
  			if (str < end)
  				*str = '%';
  			++str;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1876
1877
1878
1879
1880
  			break;
  
  		case FORMAT_TYPE_NRCHARS:
  			/* skip */
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1881
1882
  		default: {
  			unsigned long long num;
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1883
1884
1885
1886
1887
1888
  			switch (spec.type) {
  
  			case FORMAT_TYPE_LONG_LONG:
  				num = get_arg(long long);
  				break;
  			case FORMAT_TYPE_ULONG:
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1889
1890
1891
1892
1893
1894
1895
1896
1897
  			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...
1898
1899
1900
1901
1902
1903
  			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...
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
  			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...
1918
1919
1920
  		} /* default: */
  		} /* switch(spec.type) */
  	} /* while(*fmt) */
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1921

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1922
1923
1924
1925
1926
1927
  	if (size > 0) {
  		if (str < end)
  			*str = '\0';
  		else
  			end[-1] = '\0';
  	}
fef20d9c1   Frederic Weisbecker   vsprintf: unify t...
1928

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
  #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...
1954

4370aa4aa   Lai Jiangshan   vsprintf: add bin...
1955
1956
1957
1958
1959
  	return ret;
  }
  EXPORT_SYMBOL_GPL(bprintf);
  
  #endif /* CONFIG_BINARY_PRINTF */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1960
1961
1962
1963
1964
1965
  /**
   * 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...
1966
  int vsscanf(const char *buf, const char *fmt, va_list args)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1967
1968
1969
1970
1971
  {
  	const char *str = buf;
  	char *next;
  	char digit;
  	int num = 0;
ef0658f3d   Joe Perches   vsprintf.c: Reduc...
1972
1973
1974
  	u8 qualifier;
  	u8 base;
  	s16 field_width;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
1975
  	bool is_sign;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1976

da99075c1   Jan Beulich   lib/vsprintf.c: i...
1977
  	while (*fmt) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1978
1979
1980
1981
1982
  		/* 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...
1983
1984
  			fmt = skip_spaces(++fmt);
  			str = skip_spaces(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
  		}
  
  		/* 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...
1997

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1998
1999
2000
2001
  		/* skip this conversion.
  		 * advance both strings to next white space
  		 */
  		if (*fmt == '*') {
da99075c1   Jan Beulich   lib/vsprintf.c: i...
2002
2003
  			if (!*str)
  				break;
8fccae2c9   Andy Spencer   sscanf(): fix %*s%n
2004
  			while (!isspace(*fmt) && *fmt != '%' && *fmt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
  				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...
2018
2019
  		if (*fmt == 'h' || _tolower(*fmt) == 'l' ||
  		    _tolower(*fmt) == 'z') {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
  			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
2031

da99075c1   Jan Beulich   lib/vsprintf.c: i...
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
  		if (!*fmt)
  			break;
  
  		if (*fmt == 'n') {
  			/* return number of characters read so far */
  			*va_arg(args, int *) = str - buf;
  			++fmt;
  			continue;
  		}
  
  		if (!*str)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2043
  			break;
d4be151b2   André Goddard Rosa   vsprintf: move lo...
2044
2045
  		base = 10;
  		is_sign = 0;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2046
  		switch (*fmt++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2047
2048
  		case 'c':
  		{
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2049
  			char *s = (char *)va_arg(args, char*);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
  			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...
2060
2061
  			char *s = (char *)va_arg(args, char *);
  			if (field_width == -1)
4be929be3   Alexey Dobriyan   kernel-wide: repl...
2062
  				field_width = SHRT_MAX;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2063
  			/* first, skip leading white space in buffer */
e7d2860b6   André Goddard Rosa   tree-wide: conver...
2064
  			str = skip_spaces(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2065
2066
  
  			/* now copy until next white space */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2067
  			while (*str && !isspace(*str) && field_width--)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068
  				*s++ = *str++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2069
2070
2071
2072
  			*s = '\0';
  			num++;
  		}
  		continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2073
2074
2075
2076
2077
2078
2079
2080
  		case 'o':
  			base = 8;
  			break;
  		case 'x':
  		case 'X':
  			base = 16;
  			break;
  		case 'i':
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2081
  			base = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2082
2083
2084
2085
2086
2087
  		case 'd':
  			is_sign = 1;
  		case 'u':
  			break;
  		case '%':
  			/* looking for '%' in str */
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2088
  			if (*str++ != '%')
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
  				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...
2099
  		str = skip_spaces(str);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2100
2101
2102
2103
2104
2105
  
  		digit = *str;
  		if (is_sign && digit == '-')
  			digit = *(str + 1);
  
  		if (!digit
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2106
2107
2108
2109
2110
  		    || (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
2111

7b9186f5e   André Goddard Rosa   vsprintf: give it...
2112
  		switch (qualifier) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2113
2114
  		case 'H':	/* that's 'hh' in format */
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2115
2116
  				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
2117
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2118
2119
  				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
2120
2121
2122
2123
  			}
  			break;
  		case 'h':
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2124
2125
  				short *s = (short *)va_arg(args, short *);
  				*s = (short)simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2126
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2127
2128
  				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
2129
2130
2131
2132
  			}
  			break;
  		case 'l':
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2133
2134
  				long *l = (long *)va_arg(args, long *);
  				*l = simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2136
2137
  				unsigned long *l = (unsigned long *)va_arg(args, unsigned long *);
  				*l = simple_strtoul(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2138
2139
2140
2141
  			}
  			break;
  		case 'L':
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2142
2143
  				long long *l = (long long *)va_arg(args, long long *);
  				*l = simple_strtoll(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2145
2146
  				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
2147
2148
2149
2150
2151
  			}
  			break;
  		case 'Z':
  		case 'z':
  		{
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2152
2153
  			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
2154
2155
2156
2157
  		}
  		break;
  		default:
  			if (is_sign) {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2158
2159
  				int *i = (int *)va_arg(args, int *);
  				*i = (int)simple_strtol(str, &next, base);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2160
  			} else {
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2161
2162
  				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
2163
2164
2165
2166
2167
2168
2169
2170
2171
  			}
  			break;
  		}
  		num++;
  
  		if (!next)
  			break;
  		str = next;
  	}
c6b40d16d   Johannes Berg   fix sscanf %n mat...
2172

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2173
2174
  	return num;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2175
2176
2177
2178
2179
2180
2181
2182
  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...
2183
  int sscanf(const char *buf, const char *fmt, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2184
2185
2186
  {
  	va_list args;
  	int i;
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2187
2188
  	va_start(args, fmt);
  	i = vsscanf(buf, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2189
  	va_end(args);
7b9186f5e   André Goddard Rosa   vsprintf: give it...
2190

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
2192
  	return i;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2193
  EXPORT_SYMBOL(sscanf);