xref: /openbmc/linux/lib/vsprintf.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  *  linux/lib/vsprintf.c
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992  Linus Torvalds
5*1da177e4SLinus Torvalds  */
6*1da177e4SLinus Torvalds 
7*1da177e4SLinus Torvalds /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8*1da177e4SLinus Torvalds /*
9*1da177e4SLinus Torvalds  * Wirzenius wrote this portably, Torvalds fucked it up :-)
10*1da177e4SLinus Torvalds  */
11*1da177e4SLinus Torvalds 
12*1da177e4SLinus Torvalds /*
13*1da177e4SLinus Torvalds  * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
14*1da177e4SLinus Torvalds  * - changed to provide snprintf and vsnprintf functions
15*1da177e4SLinus Torvalds  * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
16*1da177e4SLinus Torvalds  * - scnprintf and vscnprintf
17*1da177e4SLinus Torvalds  */
18*1da177e4SLinus Torvalds 
19*1da177e4SLinus Torvalds #include <stdarg.h>
20*1da177e4SLinus Torvalds #include <linux/module.h>
21*1da177e4SLinus Torvalds #include <linux/types.h>
22*1da177e4SLinus Torvalds #include <linux/string.h>
23*1da177e4SLinus Torvalds #include <linux/ctype.h>
24*1da177e4SLinus Torvalds #include <linux/kernel.h>
25*1da177e4SLinus Torvalds 
26*1da177e4SLinus Torvalds #include <asm/div64.h>
27*1da177e4SLinus Torvalds 
28*1da177e4SLinus Torvalds /**
29*1da177e4SLinus Torvalds  * simple_strtoul - convert a string to an unsigned long
30*1da177e4SLinus Torvalds  * @cp: The start of the string
31*1da177e4SLinus Torvalds  * @endp: A pointer to the end of the parsed string will be placed here
32*1da177e4SLinus Torvalds  * @base: The number base to use
33*1da177e4SLinus Torvalds  */
34*1da177e4SLinus Torvalds unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
35*1da177e4SLinus Torvalds {
36*1da177e4SLinus Torvalds 	unsigned long result = 0,value;
37*1da177e4SLinus Torvalds 
38*1da177e4SLinus Torvalds 	if (!base) {
39*1da177e4SLinus Torvalds 		base = 10;
40*1da177e4SLinus Torvalds 		if (*cp == '0') {
41*1da177e4SLinus Torvalds 			base = 8;
42*1da177e4SLinus Torvalds 			cp++;
43*1da177e4SLinus Torvalds 			if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
44*1da177e4SLinus Torvalds 				cp++;
45*1da177e4SLinus Torvalds 				base = 16;
46*1da177e4SLinus Torvalds 			}
47*1da177e4SLinus Torvalds 		}
48*1da177e4SLinus Torvalds 	} else if (base == 16) {
49*1da177e4SLinus Torvalds 		if (cp[0] == '0' && toupper(cp[1]) == 'X')
50*1da177e4SLinus Torvalds 			cp += 2;
51*1da177e4SLinus Torvalds 	}
52*1da177e4SLinus Torvalds 	while (isxdigit(*cp) &&
53*1da177e4SLinus Torvalds 	       (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
54*1da177e4SLinus Torvalds 		result = result*base + value;
55*1da177e4SLinus Torvalds 		cp++;
56*1da177e4SLinus Torvalds 	}
57*1da177e4SLinus Torvalds 	if (endp)
58*1da177e4SLinus Torvalds 		*endp = (char *)cp;
59*1da177e4SLinus Torvalds 	return result;
60*1da177e4SLinus Torvalds }
61*1da177e4SLinus Torvalds 
62*1da177e4SLinus Torvalds EXPORT_SYMBOL(simple_strtoul);
63*1da177e4SLinus Torvalds 
64*1da177e4SLinus Torvalds /**
65*1da177e4SLinus Torvalds  * simple_strtol - convert a string to a signed long
66*1da177e4SLinus Torvalds  * @cp: The start of the string
67*1da177e4SLinus Torvalds  * @endp: A pointer to the end of the parsed string will be placed here
68*1da177e4SLinus Torvalds  * @base: The number base to use
69*1da177e4SLinus Torvalds  */
70*1da177e4SLinus Torvalds long simple_strtol(const char *cp,char **endp,unsigned int base)
71*1da177e4SLinus Torvalds {
72*1da177e4SLinus Torvalds 	if(*cp=='-')
73*1da177e4SLinus Torvalds 		return -simple_strtoul(cp+1,endp,base);
74*1da177e4SLinus Torvalds 	return simple_strtoul(cp,endp,base);
75*1da177e4SLinus Torvalds }
76*1da177e4SLinus Torvalds 
77*1da177e4SLinus Torvalds EXPORT_SYMBOL(simple_strtol);
78*1da177e4SLinus Torvalds 
79*1da177e4SLinus Torvalds /**
80*1da177e4SLinus Torvalds  * simple_strtoull - convert a string to an unsigned long long
81*1da177e4SLinus Torvalds  * @cp: The start of the string
82*1da177e4SLinus Torvalds  * @endp: A pointer to the end of the parsed string will be placed here
83*1da177e4SLinus Torvalds  * @base: The number base to use
84*1da177e4SLinus Torvalds  */
85*1da177e4SLinus Torvalds unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
86*1da177e4SLinus Torvalds {
87*1da177e4SLinus Torvalds 	unsigned long long result = 0,value;
88*1da177e4SLinus Torvalds 
89*1da177e4SLinus Torvalds 	if (!base) {
90*1da177e4SLinus Torvalds 		base = 10;
91*1da177e4SLinus Torvalds 		if (*cp == '0') {
92*1da177e4SLinus Torvalds 			base = 8;
93*1da177e4SLinus Torvalds 			cp++;
94*1da177e4SLinus Torvalds 			if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
95*1da177e4SLinus Torvalds 				cp++;
96*1da177e4SLinus Torvalds 				base = 16;
97*1da177e4SLinus Torvalds 			}
98*1da177e4SLinus Torvalds 		}
99*1da177e4SLinus Torvalds 	} else if (base == 16) {
100*1da177e4SLinus Torvalds 		if (cp[0] == '0' && toupper(cp[1]) == 'X')
101*1da177e4SLinus Torvalds 			cp += 2;
102*1da177e4SLinus Torvalds 	}
103*1da177e4SLinus Torvalds 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
104*1da177e4SLinus Torvalds 	    ? toupper(*cp) : *cp)-'A'+10) < base) {
105*1da177e4SLinus Torvalds 		result = result*base + value;
106*1da177e4SLinus Torvalds 		cp++;
107*1da177e4SLinus Torvalds 	}
108*1da177e4SLinus Torvalds 	if (endp)
109*1da177e4SLinus Torvalds 		*endp = (char *)cp;
110*1da177e4SLinus Torvalds 	return result;
111*1da177e4SLinus Torvalds }
112*1da177e4SLinus Torvalds 
113*1da177e4SLinus Torvalds EXPORT_SYMBOL(simple_strtoull);
114*1da177e4SLinus Torvalds 
115*1da177e4SLinus Torvalds /**
116*1da177e4SLinus Torvalds  * simple_strtoll - convert a string to a signed long long
117*1da177e4SLinus Torvalds  * @cp: The start of the string
118*1da177e4SLinus Torvalds  * @endp: A pointer to the end of the parsed string will be placed here
119*1da177e4SLinus Torvalds  * @base: The number base to use
120*1da177e4SLinus Torvalds  */
121*1da177e4SLinus Torvalds long long simple_strtoll(const char *cp,char **endp,unsigned int base)
122*1da177e4SLinus Torvalds {
123*1da177e4SLinus Torvalds 	if(*cp=='-')
124*1da177e4SLinus Torvalds 		return -simple_strtoull(cp+1,endp,base);
125*1da177e4SLinus Torvalds 	return simple_strtoull(cp,endp,base);
126*1da177e4SLinus Torvalds }
127*1da177e4SLinus Torvalds 
128*1da177e4SLinus Torvalds static int skip_atoi(const char **s)
129*1da177e4SLinus Torvalds {
130*1da177e4SLinus Torvalds 	int i=0;
131*1da177e4SLinus Torvalds 
132*1da177e4SLinus Torvalds 	while (isdigit(**s))
133*1da177e4SLinus Torvalds 		i = i*10 + *((*s)++) - '0';
134*1da177e4SLinus Torvalds 	return i;
135*1da177e4SLinus Torvalds }
136*1da177e4SLinus Torvalds 
137*1da177e4SLinus Torvalds #define ZEROPAD	1		/* pad with zero */
138*1da177e4SLinus Torvalds #define SIGN	2		/* unsigned/signed long */
139*1da177e4SLinus Torvalds #define PLUS	4		/* show plus */
140*1da177e4SLinus Torvalds #define SPACE	8		/* space if plus */
141*1da177e4SLinus Torvalds #define LEFT	16		/* left justified */
142*1da177e4SLinus Torvalds #define SPECIAL	32		/* 0x */
143*1da177e4SLinus Torvalds #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
144*1da177e4SLinus Torvalds 
145*1da177e4SLinus Torvalds static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type)
146*1da177e4SLinus Torvalds {
147*1da177e4SLinus Torvalds 	char c,sign,tmp[66];
148*1da177e4SLinus Torvalds 	const char *digits;
149*1da177e4SLinus Torvalds 	static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
150*1da177e4SLinus Torvalds 	static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
151*1da177e4SLinus Torvalds 	int i;
152*1da177e4SLinus Torvalds 
153*1da177e4SLinus Torvalds 	digits = (type & LARGE) ? large_digits : small_digits;
154*1da177e4SLinus Torvalds 	if (type & LEFT)
155*1da177e4SLinus Torvalds 		type &= ~ZEROPAD;
156*1da177e4SLinus Torvalds 	if (base < 2 || base > 36)
157*1da177e4SLinus Torvalds 		return NULL;
158*1da177e4SLinus Torvalds 	c = (type & ZEROPAD) ? '0' : ' ';
159*1da177e4SLinus Torvalds 	sign = 0;
160*1da177e4SLinus Torvalds 	if (type & SIGN) {
161*1da177e4SLinus Torvalds 		if ((signed long long) num < 0) {
162*1da177e4SLinus Torvalds 			sign = '-';
163*1da177e4SLinus Torvalds 			num = - (signed long long) num;
164*1da177e4SLinus Torvalds 			size--;
165*1da177e4SLinus Torvalds 		} else if (type & PLUS) {
166*1da177e4SLinus Torvalds 			sign = '+';
167*1da177e4SLinus Torvalds 			size--;
168*1da177e4SLinus Torvalds 		} else if (type & SPACE) {
169*1da177e4SLinus Torvalds 			sign = ' ';
170*1da177e4SLinus Torvalds 			size--;
171*1da177e4SLinus Torvalds 		}
172*1da177e4SLinus Torvalds 	}
173*1da177e4SLinus Torvalds 	if (type & SPECIAL) {
174*1da177e4SLinus Torvalds 		if (base == 16)
175*1da177e4SLinus Torvalds 			size -= 2;
176*1da177e4SLinus Torvalds 		else if (base == 8)
177*1da177e4SLinus Torvalds 			size--;
178*1da177e4SLinus Torvalds 	}
179*1da177e4SLinus Torvalds 	i = 0;
180*1da177e4SLinus Torvalds 	if (num == 0)
181*1da177e4SLinus Torvalds 		tmp[i++]='0';
182*1da177e4SLinus Torvalds 	else while (num != 0)
183*1da177e4SLinus Torvalds 		tmp[i++] = digits[do_div(num,base)];
184*1da177e4SLinus Torvalds 	if (i > precision)
185*1da177e4SLinus Torvalds 		precision = i;
186*1da177e4SLinus Torvalds 	size -= precision;
187*1da177e4SLinus Torvalds 	if (!(type&(ZEROPAD+LEFT))) {
188*1da177e4SLinus Torvalds 		while(size-->0) {
189*1da177e4SLinus Torvalds 			if (buf <= end)
190*1da177e4SLinus Torvalds 				*buf = ' ';
191*1da177e4SLinus Torvalds 			++buf;
192*1da177e4SLinus Torvalds 		}
193*1da177e4SLinus Torvalds 	}
194*1da177e4SLinus Torvalds 	if (sign) {
195*1da177e4SLinus Torvalds 		if (buf <= end)
196*1da177e4SLinus Torvalds 			*buf = sign;
197*1da177e4SLinus Torvalds 		++buf;
198*1da177e4SLinus Torvalds 	}
199*1da177e4SLinus Torvalds 	if (type & SPECIAL) {
200*1da177e4SLinus Torvalds 		if (base==8) {
201*1da177e4SLinus Torvalds 			if (buf <= end)
202*1da177e4SLinus Torvalds 				*buf = '0';
203*1da177e4SLinus Torvalds 			++buf;
204*1da177e4SLinus Torvalds 		} else if (base==16) {
205*1da177e4SLinus Torvalds 			if (buf <= end)
206*1da177e4SLinus Torvalds 				*buf = '0';
207*1da177e4SLinus Torvalds 			++buf;
208*1da177e4SLinus Torvalds 			if (buf <= end)
209*1da177e4SLinus Torvalds 				*buf = digits[33];
210*1da177e4SLinus Torvalds 			++buf;
211*1da177e4SLinus Torvalds 		}
212*1da177e4SLinus Torvalds 	}
213*1da177e4SLinus Torvalds 	if (!(type & LEFT)) {
214*1da177e4SLinus Torvalds 		while (size-- > 0) {
215*1da177e4SLinus Torvalds 			if (buf <= end)
216*1da177e4SLinus Torvalds 				*buf = c;
217*1da177e4SLinus Torvalds 			++buf;
218*1da177e4SLinus Torvalds 		}
219*1da177e4SLinus Torvalds 	}
220*1da177e4SLinus Torvalds 	while (i < precision--) {
221*1da177e4SLinus Torvalds 		if (buf <= end)
222*1da177e4SLinus Torvalds 			*buf = '0';
223*1da177e4SLinus Torvalds 		++buf;
224*1da177e4SLinus Torvalds 	}
225*1da177e4SLinus Torvalds 	while (i-- > 0) {
226*1da177e4SLinus Torvalds 		if (buf <= end)
227*1da177e4SLinus Torvalds 			*buf = tmp[i];
228*1da177e4SLinus Torvalds 		++buf;
229*1da177e4SLinus Torvalds 	}
230*1da177e4SLinus Torvalds 	while (size-- > 0) {
231*1da177e4SLinus Torvalds 		if (buf <= end)
232*1da177e4SLinus Torvalds 			*buf = ' ';
233*1da177e4SLinus Torvalds 		++buf;
234*1da177e4SLinus Torvalds 	}
235*1da177e4SLinus Torvalds 	return buf;
236*1da177e4SLinus Torvalds }
237*1da177e4SLinus Torvalds 
238*1da177e4SLinus Torvalds /**
239*1da177e4SLinus Torvalds  * vsnprintf - Format a string and place it in a buffer
240*1da177e4SLinus Torvalds  * @buf: The buffer to place the result into
241*1da177e4SLinus Torvalds  * @size: The size of the buffer, including the trailing null space
242*1da177e4SLinus Torvalds  * @fmt: The format string to use
243*1da177e4SLinus Torvalds  * @args: Arguments for the format string
244*1da177e4SLinus Torvalds  *
245*1da177e4SLinus Torvalds  * The return value is the number of characters which would
246*1da177e4SLinus Torvalds  * be generated for the given input, excluding the trailing
247*1da177e4SLinus Torvalds  * '\0', as per ISO C99. If you want to have the exact
248*1da177e4SLinus Torvalds  * number of characters written into @buf as return value
249*1da177e4SLinus Torvalds  * (not including the trailing '\0'), use vscnprintf. If the
250*1da177e4SLinus Torvalds  * return is greater than or equal to @size, the resulting
251*1da177e4SLinus Torvalds  * string is truncated.
252*1da177e4SLinus Torvalds  *
253*1da177e4SLinus Torvalds  * Call this function if you are already dealing with a va_list.
254*1da177e4SLinus Torvalds  * You probably want snprintf instead.
255*1da177e4SLinus Torvalds  */
256*1da177e4SLinus Torvalds int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
257*1da177e4SLinus Torvalds {
258*1da177e4SLinus Torvalds 	int len;
259*1da177e4SLinus Torvalds 	unsigned long long num;
260*1da177e4SLinus Torvalds 	int i, base;
261*1da177e4SLinus Torvalds 	char *str, *end, c;
262*1da177e4SLinus Torvalds 	const char *s;
263*1da177e4SLinus Torvalds 
264*1da177e4SLinus Torvalds 	int flags;		/* flags to number() */
265*1da177e4SLinus Torvalds 
266*1da177e4SLinus Torvalds 	int field_width;	/* width of output field */
267*1da177e4SLinus Torvalds 	int precision;		/* min. # of digits for integers; max
268*1da177e4SLinus Torvalds 				   number of chars for from string */
269*1da177e4SLinus Torvalds 	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
270*1da177e4SLinus Torvalds 				/* 'z' support added 23/7/1999 S.H.    */
271*1da177e4SLinus Torvalds 				/* 'z' changed to 'Z' --davidm 1/25/99 */
272*1da177e4SLinus Torvalds 
273*1da177e4SLinus Torvalds 	/* Reject out-of-range values early */
274*1da177e4SLinus Torvalds 	if (unlikely((int) size < 0)) {
275*1da177e4SLinus Torvalds 		/* There can be only one.. */
276*1da177e4SLinus Torvalds 		static int warn = 1;
277*1da177e4SLinus Torvalds 		WARN_ON(warn);
278*1da177e4SLinus Torvalds 		warn = 0;
279*1da177e4SLinus Torvalds 		return 0;
280*1da177e4SLinus Torvalds 	}
281*1da177e4SLinus Torvalds 
282*1da177e4SLinus Torvalds 	str = buf;
283*1da177e4SLinus Torvalds 	end = buf + size - 1;
284*1da177e4SLinus Torvalds 
285*1da177e4SLinus Torvalds 	if (end < buf - 1) {
286*1da177e4SLinus Torvalds 		end = ((void *) -1);
287*1da177e4SLinus Torvalds 		size = end - buf + 1;
288*1da177e4SLinus Torvalds 	}
289*1da177e4SLinus Torvalds 
290*1da177e4SLinus Torvalds 	for (; *fmt ; ++fmt) {
291*1da177e4SLinus Torvalds 		if (*fmt != '%') {
292*1da177e4SLinus Torvalds 			if (str <= end)
293*1da177e4SLinus Torvalds 				*str = *fmt;
294*1da177e4SLinus Torvalds 			++str;
295*1da177e4SLinus Torvalds 			continue;
296*1da177e4SLinus Torvalds 		}
297*1da177e4SLinus Torvalds 
298*1da177e4SLinus Torvalds 		/* process flags */
299*1da177e4SLinus Torvalds 		flags = 0;
300*1da177e4SLinus Torvalds 		repeat:
301*1da177e4SLinus Torvalds 			++fmt;		/* this also skips first '%' */
302*1da177e4SLinus Torvalds 			switch (*fmt) {
303*1da177e4SLinus Torvalds 				case '-': flags |= LEFT; goto repeat;
304*1da177e4SLinus Torvalds 				case '+': flags |= PLUS; goto repeat;
305*1da177e4SLinus Torvalds 				case ' ': flags |= SPACE; goto repeat;
306*1da177e4SLinus Torvalds 				case '#': flags |= SPECIAL; goto repeat;
307*1da177e4SLinus Torvalds 				case '0': flags |= ZEROPAD; goto repeat;
308*1da177e4SLinus Torvalds 			}
309*1da177e4SLinus Torvalds 
310*1da177e4SLinus Torvalds 		/* get field width */
311*1da177e4SLinus Torvalds 		field_width = -1;
312*1da177e4SLinus Torvalds 		if (isdigit(*fmt))
313*1da177e4SLinus Torvalds 			field_width = skip_atoi(&fmt);
314*1da177e4SLinus Torvalds 		else if (*fmt == '*') {
315*1da177e4SLinus Torvalds 			++fmt;
316*1da177e4SLinus Torvalds 			/* it's the next argument */
317*1da177e4SLinus Torvalds 			field_width = va_arg(args, int);
318*1da177e4SLinus Torvalds 			if (field_width < 0) {
319*1da177e4SLinus Torvalds 				field_width = -field_width;
320*1da177e4SLinus Torvalds 				flags |= LEFT;
321*1da177e4SLinus Torvalds 			}
322*1da177e4SLinus Torvalds 		}
323*1da177e4SLinus Torvalds 
324*1da177e4SLinus Torvalds 		/* get the precision */
325*1da177e4SLinus Torvalds 		precision = -1;
326*1da177e4SLinus Torvalds 		if (*fmt == '.') {
327*1da177e4SLinus Torvalds 			++fmt;
328*1da177e4SLinus Torvalds 			if (isdigit(*fmt))
329*1da177e4SLinus Torvalds 				precision = skip_atoi(&fmt);
330*1da177e4SLinus Torvalds 			else if (*fmt == '*') {
331*1da177e4SLinus Torvalds 				++fmt;
332*1da177e4SLinus Torvalds 				/* it's the next argument */
333*1da177e4SLinus Torvalds 				precision = va_arg(args, int);
334*1da177e4SLinus Torvalds 			}
335*1da177e4SLinus Torvalds 			if (precision < 0)
336*1da177e4SLinus Torvalds 				precision = 0;
337*1da177e4SLinus Torvalds 		}
338*1da177e4SLinus Torvalds 
339*1da177e4SLinus Torvalds 		/* get the conversion qualifier */
340*1da177e4SLinus Torvalds 		qualifier = -1;
341*1da177e4SLinus Torvalds 		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
342*1da177e4SLinus Torvalds 		    *fmt =='Z' || *fmt == 'z') {
343*1da177e4SLinus Torvalds 			qualifier = *fmt;
344*1da177e4SLinus Torvalds 			++fmt;
345*1da177e4SLinus Torvalds 			if (qualifier == 'l' && *fmt == 'l') {
346*1da177e4SLinus Torvalds 				qualifier = 'L';
347*1da177e4SLinus Torvalds 				++fmt;
348*1da177e4SLinus Torvalds 			}
349*1da177e4SLinus Torvalds 		}
350*1da177e4SLinus Torvalds 
351*1da177e4SLinus Torvalds 		/* default base */
352*1da177e4SLinus Torvalds 		base = 10;
353*1da177e4SLinus Torvalds 
354*1da177e4SLinus Torvalds 		switch (*fmt) {
355*1da177e4SLinus Torvalds 			case 'c':
356*1da177e4SLinus Torvalds 				if (!(flags & LEFT)) {
357*1da177e4SLinus Torvalds 					while (--field_width > 0) {
358*1da177e4SLinus Torvalds 						if (str <= end)
359*1da177e4SLinus Torvalds 							*str = ' ';
360*1da177e4SLinus Torvalds 						++str;
361*1da177e4SLinus Torvalds 					}
362*1da177e4SLinus Torvalds 				}
363*1da177e4SLinus Torvalds 				c = (unsigned char) va_arg(args, int);
364*1da177e4SLinus Torvalds 				if (str <= end)
365*1da177e4SLinus Torvalds 					*str = c;
366*1da177e4SLinus Torvalds 				++str;
367*1da177e4SLinus Torvalds 				while (--field_width > 0) {
368*1da177e4SLinus Torvalds 					if (str <= end)
369*1da177e4SLinus Torvalds 						*str = ' ';
370*1da177e4SLinus Torvalds 					++str;
371*1da177e4SLinus Torvalds 				}
372*1da177e4SLinus Torvalds 				continue;
373*1da177e4SLinus Torvalds 
374*1da177e4SLinus Torvalds 			case 's':
375*1da177e4SLinus Torvalds 				s = va_arg(args, char *);
376*1da177e4SLinus Torvalds 				if ((unsigned long)s < PAGE_SIZE)
377*1da177e4SLinus Torvalds 					s = "<NULL>";
378*1da177e4SLinus Torvalds 
379*1da177e4SLinus Torvalds 				len = strnlen(s, precision);
380*1da177e4SLinus Torvalds 
381*1da177e4SLinus Torvalds 				if (!(flags & LEFT)) {
382*1da177e4SLinus Torvalds 					while (len < field_width--) {
383*1da177e4SLinus Torvalds 						if (str <= end)
384*1da177e4SLinus Torvalds 							*str = ' ';
385*1da177e4SLinus Torvalds 						++str;
386*1da177e4SLinus Torvalds 					}
387*1da177e4SLinus Torvalds 				}
388*1da177e4SLinus Torvalds 				for (i = 0; i < len; ++i) {
389*1da177e4SLinus Torvalds 					if (str <= end)
390*1da177e4SLinus Torvalds 						*str = *s;
391*1da177e4SLinus Torvalds 					++str; ++s;
392*1da177e4SLinus Torvalds 				}
393*1da177e4SLinus Torvalds 				while (len < field_width--) {
394*1da177e4SLinus Torvalds 					if (str <= end)
395*1da177e4SLinus Torvalds 						*str = ' ';
396*1da177e4SLinus Torvalds 					++str;
397*1da177e4SLinus Torvalds 				}
398*1da177e4SLinus Torvalds 				continue;
399*1da177e4SLinus Torvalds 
400*1da177e4SLinus Torvalds 			case 'p':
401*1da177e4SLinus Torvalds 				if (field_width == -1) {
402*1da177e4SLinus Torvalds 					field_width = 2*sizeof(void *);
403*1da177e4SLinus Torvalds 					flags |= ZEROPAD;
404*1da177e4SLinus Torvalds 				}
405*1da177e4SLinus Torvalds 				str = number(str, end,
406*1da177e4SLinus Torvalds 						(unsigned long) va_arg(args, void *),
407*1da177e4SLinus Torvalds 						16, field_width, precision, flags);
408*1da177e4SLinus Torvalds 				continue;
409*1da177e4SLinus Torvalds 
410*1da177e4SLinus Torvalds 
411*1da177e4SLinus Torvalds 			case 'n':
412*1da177e4SLinus Torvalds 				/* FIXME:
413*1da177e4SLinus Torvalds 				* What does C99 say about the overflow case here? */
414*1da177e4SLinus Torvalds 				if (qualifier == 'l') {
415*1da177e4SLinus Torvalds 					long * ip = va_arg(args, long *);
416*1da177e4SLinus Torvalds 					*ip = (str - buf);
417*1da177e4SLinus Torvalds 				} else if (qualifier == 'Z' || qualifier == 'z') {
418*1da177e4SLinus Torvalds 					size_t * ip = va_arg(args, size_t *);
419*1da177e4SLinus Torvalds 					*ip = (str - buf);
420*1da177e4SLinus Torvalds 				} else {
421*1da177e4SLinus Torvalds 					int * ip = va_arg(args, int *);
422*1da177e4SLinus Torvalds 					*ip = (str - buf);
423*1da177e4SLinus Torvalds 				}
424*1da177e4SLinus Torvalds 				continue;
425*1da177e4SLinus Torvalds 
426*1da177e4SLinus Torvalds 			case '%':
427*1da177e4SLinus Torvalds 				if (str <= end)
428*1da177e4SLinus Torvalds 					*str = '%';
429*1da177e4SLinus Torvalds 				++str;
430*1da177e4SLinus Torvalds 				continue;
431*1da177e4SLinus Torvalds 
432*1da177e4SLinus Torvalds 				/* integer number formats - set up the flags and "break" */
433*1da177e4SLinus Torvalds 			case 'o':
434*1da177e4SLinus Torvalds 				base = 8;
435*1da177e4SLinus Torvalds 				break;
436*1da177e4SLinus Torvalds 
437*1da177e4SLinus Torvalds 			case 'X':
438*1da177e4SLinus Torvalds 				flags |= LARGE;
439*1da177e4SLinus Torvalds 			case 'x':
440*1da177e4SLinus Torvalds 				base = 16;
441*1da177e4SLinus Torvalds 				break;
442*1da177e4SLinus Torvalds 
443*1da177e4SLinus Torvalds 			case 'd':
444*1da177e4SLinus Torvalds 			case 'i':
445*1da177e4SLinus Torvalds 				flags |= SIGN;
446*1da177e4SLinus Torvalds 			case 'u':
447*1da177e4SLinus Torvalds 				break;
448*1da177e4SLinus Torvalds 
449*1da177e4SLinus Torvalds 			default:
450*1da177e4SLinus Torvalds 				if (str <= end)
451*1da177e4SLinus Torvalds 					*str = '%';
452*1da177e4SLinus Torvalds 				++str;
453*1da177e4SLinus Torvalds 				if (*fmt) {
454*1da177e4SLinus Torvalds 					if (str <= end)
455*1da177e4SLinus Torvalds 						*str = *fmt;
456*1da177e4SLinus Torvalds 					++str;
457*1da177e4SLinus Torvalds 				} else {
458*1da177e4SLinus Torvalds 					--fmt;
459*1da177e4SLinus Torvalds 				}
460*1da177e4SLinus Torvalds 				continue;
461*1da177e4SLinus Torvalds 		}
462*1da177e4SLinus Torvalds 		if (qualifier == 'L')
463*1da177e4SLinus Torvalds 			num = va_arg(args, long long);
464*1da177e4SLinus Torvalds 		else if (qualifier == 'l') {
465*1da177e4SLinus Torvalds 			num = va_arg(args, unsigned long);
466*1da177e4SLinus Torvalds 			if (flags & SIGN)
467*1da177e4SLinus Torvalds 				num = (signed long) num;
468*1da177e4SLinus Torvalds 		} else if (qualifier == 'Z' || qualifier == 'z') {
469*1da177e4SLinus Torvalds 			num = va_arg(args, size_t);
470*1da177e4SLinus Torvalds 		} else if (qualifier == 'h') {
471*1da177e4SLinus Torvalds 			num = (unsigned short) va_arg(args, int);
472*1da177e4SLinus Torvalds 			if (flags & SIGN)
473*1da177e4SLinus Torvalds 				num = (signed short) num;
474*1da177e4SLinus Torvalds 		} else {
475*1da177e4SLinus Torvalds 			num = va_arg(args, unsigned int);
476*1da177e4SLinus Torvalds 			if (flags & SIGN)
477*1da177e4SLinus Torvalds 				num = (signed int) num;
478*1da177e4SLinus Torvalds 		}
479*1da177e4SLinus Torvalds 		str = number(str, end, num, base,
480*1da177e4SLinus Torvalds 				field_width, precision, flags);
481*1da177e4SLinus Torvalds 	}
482*1da177e4SLinus Torvalds 	if (str <= end)
483*1da177e4SLinus Torvalds 		*str = '\0';
484*1da177e4SLinus Torvalds 	else if (size > 0)
485*1da177e4SLinus Torvalds 		/* don't write out a null byte if the buf size is zero */
486*1da177e4SLinus Torvalds 		*end = '\0';
487*1da177e4SLinus Torvalds 	/* the trailing null byte doesn't count towards the total
488*1da177e4SLinus Torvalds 	* ++str;
489*1da177e4SLinus Torvalds 	*/
490*1da177e4SLinus Torvalds 	return str-buf;
491*1da177e4SLinus Torvalds }
492*1da177e4SLinus Torvalds 
493*1da177e4SLinus Torvalds EXPORT_SYMBOL(vsnprintf);
494*1da177e4SLinus Torvalds 
495*1da177e4SLinus Torvalds /**
496*1da177e4SLinus Torvalds  * vscnprintf - Format a string and place it in a buffer
497*1da177e4SLinus Torvalds  * @buf: The buffer to place the result into
498*1da177e4SLinus Torvalds  * @size: The size of the buffer, including the trailing null space
499*1da177e4SLinus Torvalds  * @fmt: The format string to use
500*1da177e4SLinus Torvalds  * @args: Arguments for the format string
501*1da177e4SLinus Torvalds  *
502*1da177e4SLinus Torvalds  * The return value is the number of characters which have been written into
503*1da177e4SLinus Torvalds  * the @buf not including the trailing '\0'. If @size is <= 0 the function
504*1da177e4SLinus Torvalds  * returns 0.
505*1da177e4SLinus Torvalds  *
506*1da177e4SLinus Torvalds  * Call this function if you are already dealing with a va_list.
507*1da177e4SLinus Torvalds  * You probably want scnprintf instead.
508*1da177e4SLinus Torvalds  */
509*1da177e4SLinus Torvalds int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
510*1da177e4SLinus Torvalds {
511*1da177e4SLinus Torvalds 	int i;
512*1da177e4SLinus Torvalds 
513*1da177e4SLinus Torvalds 	i=vsnprintf(buf,size,fmt,args);
514*1da177e4SLinus Torvalds 	return (i >= size) ? (size - 1) : i;
515*1da177e4SLinus Torvalds }
516*1da177e4SLinus Torvalds 
517*1da177e4SLinus Torvalds EXPORT_SYMBOL(vscnprintf);
518*1da177e4SLinus Torvalds 
519*1da177e4SLinus Torvalds /**
520*1da177e4SLinus Torvalds  * snprintf - Format a string and place it in a buffer
521*1da177e4SLinus Torvalds  * @buf: The buffer to place the result into
522*1da177e4SLinus Torvalds  * @size: The size of the buffer, including the trailing null space
523*1da177e4SLinus Torvalds  * @fmt: The format string to use
524*1da177e4SLinus Torvalds  * @...: Arguments for the format string
525*1da177e4SLinus Torvalds  *
526*1da177e4SLinus Torvalds  * The return value is the number of characters which would be
527*1da177e4SLinus Torvalds  * generated for the given input, excluding the trailing null,
528*1da177e4SLinus Torvalds  * as per ISO C99.  If the return is greater than or equal to
529*1da177e4SLinus Torvalds  * @size, the resulting string is truncated.
530*1da177e4SLinus Torvalds  */
531*1da177e4SLinus Torvalds int snprintf(char * buf, size_t size, const char *fmt, ...)
532*1da177e4SLinus Torvalds {
533*1da177e4SLinus Torvalds 	va_list args;
534*1da177e4SLinus Torvalds 	int i;
535*1da177e4SLinus Torvalds 
536*1da177e4SLinus Torvalds 	va_start(args, fmt);
537*1da177e4SLinus Torvalds 	i=vsnprintf(buf,size,fmt,args);
538*1da177e4SLinus Torvalds 	va_end(args);
539*1da177e4SLinus Torvalds 	return i;
540*1da177e4SLinus Torvalds }
541*1da177e4SLinus Torvalds 
542*1da177e4SLinus Torvalds EXPORT_SYMBOL(snprintf);
543*1da177e4SLinus Torvalds 
544*1da177e4SLinus Torvalds /**
545*1da177e4SLinus Torvalds  * scnprintf - Format a string and place it in a buffer
546*1da177e4SLinus Torvalds  * @buf: The buffer to place the result into
547*1da177e4SLinus Torvalds  * @size: The size of the buffer, including the trailing null space
548*1da177e4SLinus Torvalds  * @fmt: The format string to use
549*1da177e4SLinus Torvalds  * @...: Arguments for the format string
550*1da177e4SLinus Torvalds  *
551*1da177e4SLinus Torvalds  * The return value is the number of characters written into @buf not including
552*1da177e4SLinus Torvalds  * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is
553*1da177e4SLinus Torvalds  * greater than or equal to @size, the resulting string is truncated.
554*1da177e4SLinus Torvalds  */
555*1da177e4SLinus Torvalds 
556*1da177e4SLinus Torvalds int scnprintf(char * buf, size_t size, const char *fmt, ...)
557*1da177e4SLinus Torvalds {
558*1da177e4SLinus Torvalds 	va_list args;
559*1da177e4SLinus Torvalds 	int i;
560*1da177e4SLinus Torvalds 
561*1da177e4SLinus Torvalds 	va_start(args, fmt);
562*1da177e4SLinus Torvalds 	i = vsnprintf(buf, size, fmt, args);
563*1da177e4SLinus Torvalds 	va_end(args);
564*1da177e4SLinus Torvalds 	return (i >= size) ? (size - 1) : i;
565*1da177e4SLinus Torvalds }
566*1da177e4SLinus Torvalds EXPORT_SYMBOL(scnprintf);
567*1da177e4SLinus Torvalds 
568*1da177e4SLinus Torvalds /**
569*1da177e4SLinus Torvalds  * vsprintf - Format a string and place it in a buffer
570*1da177e4SLinus Torvalds  * @buf: The buffer to place the result into
571*1da177e4SLinus Torvalds  * @fmt: The format string to use
572*1da177e4SLinus Torvalds  * @args: Arguments for the format string
573*1da177e4SLinus Torvalds  *
574*1da177e4SLinus Torvalds  * The function returns the number of characters written
575*1da177e4SLinus Torvalds  * into @buf. Use vsnprintf or vscnprintf in order to avoid
576*1da177e4SLinus Torvalds  * buffer overflows.
577*1da177e4SLinus Torvalds  *
578*1da177e4SLinus Torvalds  * Call this function if you are already dealing with a va_list.
579*1da177e4SLinus Torvalds  * You probably want sprintf instead.
580*1da177e4SLinus Torvalds  */
581*1da177e4SLinus Torvalds int vsprintf(char *buf, const char *fmt, va_list args)
582*1da177e4SLinus Torvalds {
583*1da177e4SLinus Torvalds 	return vsnprintf(buf, INT_MAX, fmt, args);
584*1da177e4SLinus Torvalds }
585*1da177e4SLinus Torvalds 
586*1da177e4SLinus Torvalds EXPORT_SYMBOL(vsprintf);
587*1da177e4SLinus Torvalds 
588*1da177e4SLinus Torvalds /**
589*1da177e4SLinus Torvalds  * sprintf - Format a string and place it in a buffer
590*1da177e4SLinus Torvalds  * @buf: The buffer to place the result into
591*1da177e4SLinus Torvalds  * @fmt: The format string to use
592*1da177e4SLinus Torvalds  * @...: Arguments for the format string
593*1da177e4SLinus Torvalds  *
594*1da177e4SLinus Torvalds  * The function returns the number of characters written
595*1da177e4SLinus Torvalds  * into @buf. Use snprintf or scnprintf in order to avoid
596*1da177e4SLinus Torvalds  * buffer overflows.
597*1da177e4SLinus Torvalds  */
598*1da177e4SLinus Torvalds int sprintf(char * buf, const char *fmt, ...)
599*1da177e4SLinus Torvalds {
600*1da177e4SLinus Torvalds 	va_list args;
601*1da177e4SLinus Torvalds 	int i;
602*1da177e4SLinus Torvalds 
603*1da177e4SLinus Torvalds 	va_start(args, fmt);
604*1da177e4SLinus Torvalds 	i=vsnprintf(buf, INT_MAX, fmt, args);
605*1da177e4SLinus Torvalds 	va_end(args);
606*1da177e4SLinus Torvalds 	return i;
607*1da177e4SLinus Torvalds }
608*1da177e4SLinus Torvalds 
609*1da177e4SLinus Torvalds EXPORT_SYMBOL(sprintf);
610*1da177e4SLinus Torvalds 
611*1da177e4SLinus Torvalds /**
612*1da177e4SLinus Torvalds  * vsscanf - Unformat a buffer into a list of arguments
613*1da177e4SLinus Torvalds  * @buf:	input buffer
614*1da177e4SLinus Torvalds  * @fmt:	format of buffer
615*1da177e4SLinus Torvalds  * @args:	arguments
616*1da177e4SLinus Torvalds  */
617*1da177e4SLinus Torvalds int vsscanf(const char * buf, const char * fmt, va_list args)
618*1da177e4SLinus Torvalds {
619*1da177e4SLinus Torvalds 	const char *str = buf;
620*1da177e4SLinus Torvalds 	char *next;
621*1da177e4SLinus Torvalds 	char digit;
622*1da177e4SLinus Torvalds 	int num = 0;
623*1da177e4SLinus Torvalds 	int qualifier;
624*1da177e4SLinus Torvalds 	int base;
625*1da177e4SLinus Torvalds 	int field_width;
626*1da177e4SLinus Torvalds 	int is_sign = 0;
627*1da177e4SLinus Torvalds 
628*1da177e4SLinus Torvalds 	while(*fmt && *str) {
629*1da177e4SLinus Torvalds 		/* skip any white space in format */
630*1da177e4SLinus Torvalds 		/* white space in format matchs any amount of
631*1da177e4SLinus Torvalds 		 * white space, including none, in the input.
632*1da177e4SLinus Torvalds 		 */
633*1da177e4SLinus Torvalds 		if (isspace(*fmt)) {
634*1da177e4SLinus Torvalds 			while (isspace(*fmt))
635*1da177e4SLinus Torvalds 				++fmt;
636*1da177e4SLinus Torvalds 			while (isspace(*str))
637*1da177e4SLinus Torvalds 				++str;
638*1da177e4SLinus Torvalds 		}
639*1da177e4SLinus Torvalds 
640*1da177e4SLinus Torvalds 		/* anything that is not a conversion must match exactly */
641*1da177e4SLinus Torvalds 		if (*fmt != '%' && *fmt) {
642*1da177e4SLinus Torvalds 			if (*fmt++ != *str++)
643*1da177e4SLinus Torvalds 				break;
644*1da177e4SLinus Torvalds 			continue;
645*1da177e4SLinus Torvalds 		}
646*1da177e4SLinus Torvalds 
647*1da177e4SLinus Torvalds 		if (!*fmt)
648*1da177e4SLinus Torvalds 			break;
649*1da177e4SLinus Torvalds 		++fmt;
650*1da177e4SLinus Torvalds 
651*1da177e4SLinus Torvalds 		/* skip this conversion.
652*1da177e4SLinus Torvalds 		 * advance both strings to next white space
653*1da177e4SLinus Torvalds 		 */
654*1da177e4SLinus Torvalds 		if (*fmt == '*') {
655*1da177e4SLinus Torvalds 			while (!isspace(*fmt) && *fmt)
656*1da177e4SLinus Torvalds 				fmt++;
657*1da177e4SLinus Torvalds 			while (!isspace(*str) && *str)
658*1da177e4SLinus Torvalds 				str++;
659*1da177e4SLinus Torvalds 			continue;
660*1da177e4SLinus Torvalds 		}
661*1da177e4SLinus Torvalds 
662*1da177e4SLinus Torvalds 		/* get field width */
663*1da177e4SLinus Torvalds 		field_width = -1;
664*1da177e4SLinus Torvalds 		if (isdigit(*fmt))
665*1da177e4SLinus Torvalds 			field_width = skip_atoi(&fmt);
666*1da177e4SLinus Torvalds 
667*1da177e4SLinus Torvalds 		/* get conversion qualifier */
668*1da177e4SLinus Torvalds 		qualifier = -1;
669*1da177e4SLinus Torvalds 		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
670*1da177e4SLinus Torvalds 		    *fmt == 'Z' || *fmt == 'z') {
671*1da177e4SLinus Torvalds 			qualifier = *fmt++;
672*1da177e4SLinus Torvalds 			if (unlikely(qualifier == *fmt)) {
673*1da177e4SLinus Torvalds 				if (qualifier == 'h') {
674*1da177e4SLinus Torvalds 					qualifier = 'H';
675*1da177e4SLinus Torvalds 					fmt++;
676*1da177e4SLinus Torvalds 				} else if (qualifier == 'l') {
677*1da177e4SLinus Torvalds 					qualifier = 'L';
678*1da177e4SLinus Torvalds 					fmt++;
679*1da177e4SLinus Torvalds 				}
680*1da177e4SLinus Torvalds 			}
681*1da177e4SLinus Torvalds 		}
682*1da177e4SLinus Torvalds 		base = 10;
683*1da177e4SLinus Torvalds 		is_sign = 0;
684*1da177e4SLinus Torvalds 
685*1da177e4SLinus Torvalds 		if (!*fmt || !*str)
686*1da177e4SLinus Torvalds 			break;
687*1da177e4SLinus Torvalds 
688*1da177e4SLinus Torvalds 		switch(*fmt++) {
689*1da177e4SLinus Torvalds 		case 'c':
690*1da177e4SLinus Torvalds 		{
691*1da177e4SLinus Torvalds 			char *s = (char *) va_arg(args,char*);
692*1da177e4SLinus Torvalds 			if (field_width == -1)
693*1da177e4SLinus Torvalds 				field_width = 1;
694*1da177e4SLinus Torvalds 			do {
695*1da177e4SLinus Torvalds 				*s++ = *str++;
696*1da177e4SLinus Torvalds 			} while (--field_width > 0 && *str);
697*1da177e4SLinus Torvalds 			num++;
698*1da177e4SLinus Torvalds 		}
699*1da177e4SLinus Torvalds 		continue;
700*1da177e4SLinus Torvalds 		case 's':
701*1da177e4SLinus Torvalds 		{
702*1da177e4SLinus Torvalds 			char *s = (char *) va_arg(args, char *);
703*1da177e4SLinus Torvalds 			if(field_width == -1)
704*1da177e4SLinus Torvalds 				field_width = INT_MAX;
705*1da177e4SLinus Torvalds 			/* first, skip leading white space in buffer */
706*1da177e4SLinus Torvalds 			while (isspace(*str))
707*1da177e4SLinus Torvalds 				str++;
708*1da177e4SLinus Torvalds 
709*1da177e4SLinus Torvalds 			/* now copy until next white space */
710*1da177e4SLinus Torvalds 			while (*str && !isspace(*str) && field_width--) {
711*1da177e4SLinus Torvalds 				*s++ = *str++;
712*1da177e4SLinus Torvalds 			}
713*1da177e4SLinus Torvalds 			*s = '\0';
714*1da177e4SLinus Torvalds 			num++;
715*1da177e4SLinus Torvalds 		}
716*1da177e4SLinus Torvalds 		continue;
717*1da177e4SLinus Torvalds 		case 'n':
718*1da177e4SLinus Torvalds 			/* return number of characters read so far */
719*1da177e4SLinus Torvalds 		{
720*1da177e4SLinus Torvalds 			int *i = (int *)va_arg(args,int*);
721*1da177e4SLinus Torvalds 			*i = str - buf;
722*1da177e4SLinus Torvalds 		}
723*1da177e4SLinus Torvalds 		continue;
724*1da177e4SLinus Torvalds 		case 'o':
725*1da177e4SLinus Torvalds 			base = 8;
726*1da177e4SLinus Torvalds 			break;
727*1da177e4SLinus Torvalds 		case 'x':
728*1da177e4SLinus Torvalds 		case 'X':
729*1da177e4SLinus Torvalds 			base = 16;
730*1da177e4SLinus Torvalds 			break;
731*1da177e4SLinus Torvalds 		case 'i':
732*1da177e4SLinus Torvalds                         base = 0;
733*1da177e4SLinus Torvalds 		case 'd':
734*1da177e4SLinus Torvalds 			is_sign = 1;
735*1da177e4SLinus Torvalds 		case 'u':
736*1da177e4SLinus Torvalds 			break;
737*1da177e4SLinus Torvalds 		case '%':
738*1da177e4SLinus Torvalds 			/* looking for '%' in str */
739*1da177e4SLinus Torvalds 			if (*str++ != '%')
740*1da177e4SLinus Torvalds 				return num;
741*1da177e4SLinus Torvalds 			continue;
742*1da177e4SLinus Torvalds 		default:
743*1da177e4SLinus Torvalds 			/* invalid format; stop here */
744*1da177e4SLinus Torvalds 			return num;
745*1da177e4SLinus Torvalds 		}
746*1da177e4SLinus Torvalds 
747*1da177e4SLinus Torvalds 		/* have some sort of integer conversion.
748*1da177e4SLinus Torvalds 		 * first, skip white space in buffer.
749*1da177e4SLinus Torvalds 		 */
750*1da177e4SLinus Torvalds 		while (isspace(*str))
751*1da177e4SLinus Torvalds 			str++;
752*1da177e4SLinus Torvalds 
753*1da177e4SLinus Torvalds 		digit = *str;
754*1da177e4SLinus Torvalds 		if (is_sign && digit == '-')
755*1da177e4SLinus Torvalds 			digit = *(str + 1);
756*1da177e4SLinus Torvalds 
757*1da177e4SLinus Torvalds 		if (!digit
758*1da177e4SLinus Torvalds                     || (base == 16 && !isxdigit(digit))
759*1da177e4SLinus Torvalds                     || (base == 10 && !isdigit(digit))
760*1da177e4SLinus Torvalds                     || (base == 8 && (!isdigit(digit) || digit > '7'))
761*1da177e4SLinus Torvalds                     || (base == 0 && !isdigit(digit)))
762*1da177e4SLinus Torvalds 				break;
763*1da177e4SLinus Torvalds 
764*1da177e4SLinus Torvalds 		switch(qualifier) {
765*1da177e4SLinus Torvalds 		case 'H':	/* that's 'hh' in format */
766*1da177e4SLinus Torvalds 			if (is_sign) {
767*1da177e4SLinus Torvalds 				signed char *s = (signed char *) va_arg(args,signed char *);
768*1da177e4SLinus Torvalds 				*s = (signed char) simple_strtol(str,&next,base);
769*1da177e4SLinus Torvalds 			} else {
770*1da177e4SLinus Torvalds 				unsigned char *s = (unsigned char *) va_arg(args, unsigned char *);
771*1da177e4SLinus Torvalds 				*s = (unsigned char) simple_strtoul(str, &next, base);
772*1da177e4SLinus Torvalds 			}
773*1da177e4SLinus Torvalds 			break;
774*1da177e4SLinus Torvalds 		case 'h':
775*1da177e4SLinus Torvalds 			if (is_sign) {
776*1da177e4SLinus Torvalds 				short *s = (short *) va_arg(args,short *);
777*1da177e4SLinus Torvalds 				*s = (short) simple_strtol(str,&next,base);
778*1da177e4SLinus Torvalds 			} else {
779*1da177e4SLinus Torvalds 				unsigned short *s = (unsigned short *) va_arg(args, unsigned short *);
780*1da177e4SLinus Torvalds 				*s = (unsigned short) simple_strtoul(str, &next, base);
781*1da177e4SLinus Torvalds 			}
782*1da177e4SLinus Torvalds 			break;
783*1da177e4SLinus Torvalds 		case 'l':
784*1da177e4SLinus Torvalds 			if (is_sign) {
785*1da177e4SLinus Torvalds 				long *l = (long *) va_arg(args,long *);
786*1da177e4SLinus Torvalds 				*l = simple_strtol(str,&next,base);
787*1da177e4SLinus Torvalds 			} else {
788*1da177e4SLinus Torvalds 				unsigned long *l = (unsigned long*) va_arg(args,unsigned long*);
789*1da177e4SLinus Torvalds 				*l = simple_strtoul(str,&next,base);
790*1da177e4SLinus Torvalds 			}
791*1da177e4SLinus Torvalds 			break;
792*1da177e4SLinus Torvalds 		case 'L':
793*1da177e4SLinus Torvalds 			if (is_sign) {
794*1da177e4SLinus Torvalds 				long long *l = (long long*) va_arg(args,long long *);
795*1da177e4SLinus Torvalds 				*l = simple_strtoll(str,&next,base);
796*1da177e4SLinus Torvalds 			} else {
797*1da177e4SLinus Torvalds 				unsigned long long *l = (unsigned long long*) va_arg(args,unsigned long long*);
798*1da177e4SLinus Torvalds 				*l = simple_strtoull(str,&next,base);
799*1da177e4SLinus Torvalds 			}
800*1da177e4SLinus Torvalds 			break;
801*1da177e4SLinus Torvalds 		case 'Z':
802*1da177e4SLinus Torvalds 		case 'z':
803*1da177e4SLinus Torvalds 		{
804*1da177e4SLinus Torvalds 			size_t *s = (size_t*) va_arg(args,size_t*);
805*1da177e4SLinus Torvalds 			*s = (size_t) simple_strtoul(str,&next,base);
806*1da177e4SLinus Torvalds 		}
807*1da177e4SLinus Torvalds 		break;
808*1da177e4SLinus Torvalds 		default:
809*1da177e4SLinus Torvalds 			if (is_sign) {
810*1da177e4SLinus Torvalds 				int *i = (int *) va_arg(args, int*);
811*1da177e4SLinus Torvalds 				*i = (int) simple_strtol(str,&next,base);
812*1da177e4SLinus Torvalds 			} else {
813*1da177e4SLinus Torvalds 				unsigned int *i = (unsigned int*) va_arg(args, unsigned int*);
814*1da177e4SLinus Torvalds 				*i = (unsigned int) simple_strtoul(str,&next,base);
815*1da177e4SLinus Torvalds 			}
816*1da177e4SLinus Torvalds 			break;
817*1da177e4SLinus Torvalds 		}
818*1da177e4SLinus Torvalds 		num++;
819*1da177e4SLinus Torvalds 
820*1da177e4SLinus Torvalds 		if (!next)
821*1da177e4SLinus Torvalds 			break;
822*1da177e4SLinus Torvalds 		str = next;
823*1da177e4SLinus Torvalds 	}
824*1da177e4SLinus Torvalds 	return num;
825*1da177e4SLinus Torvalds }
826*1da177e4SLinus Torvalds 
827*1da177e4SLinus Torvalds EXPORT_SYMBOL(vsscanf);
828*1da177e4SLinus Torvalds 
829*1da177e4SLinus Torvalds /**
830*1da177e4SLinus Torvalds  * sscanf - Unformat a buffer into a list of arguments
831*1da177e4SLinus Torvalds  * @buf:	input buffer
832*1da177e4SLinus Torvalds  * @fmt:	formatting of buffer
833*1da177e4SLinus Torvalds  * @...:	resulting arguments
834*1da177e4SLinus Torvalds  */
835*1da177e4SLinus Torvalds int sscanf(const char * buf, const char * fmt, ...)
836*1da177e4SLinus Torvalds {
837*1da177e4SLinus Torvalds 	va_list args;
838*1da177e4SLinus Torvalds 	int i;
839*1da177e4SLinus Torvalds 
840*1da177e4SLinus Torvalds 	va_start(args,fmt);
841*1da177e4SLinus Torvalds 	i = vsscanf(buf,fmt,args);
842*1da177e4SLinus Torvalds 	va_end(args);
843*1da177e4SLinus Torvalds 	return i;
844*1da177e4SLinus Torvalds }
845*1da177e4SLinus Torvalds 
846*1da177e4SLinus Torvalds EXPORT_SYMBOL(sscanf);
847