xref: /openbmc/u-boot/lib/vsprintf.c (revision dd80264d)
1 /*
2  *  linux/lib/vsprintf.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6 
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9  * Wirzenius wrote this portably, Torvalds fucked it up :-)
10  *
11  * from hush: simple_itoa() was lifted from boa-0.93.15
12  */
13 
14 #include <stdarg.h>
15 #include <linux/types.h>
16 #include <linux/string.h>
17 #include <linux/ctype.h>
18 #include <errno.h>
19 
20 #include <common.h>
21 #if !defined (CONFIG_PANIC_HANG)
22 #include <command.h>
23 #endif
24 
25 #include <div64.h>
26 # define NUM_TYPE long long
27 #define noinline __attribute__((noinline))
28 
29 /* some reluctance to put this into a new limits.h, so it is here */
30 #define INT_MAX		((int)(~0U>>1))
31 
32 const char hex_asc[] = "0123456789abcdef";
33 #define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
34 #define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
35 
36 static inline char *pack_hex_byte(char *buf, u8 byte)
37 {
38 	*buf++ = hex_asc_hi(byte);
39 	*buf++ = hex_asc_lo(byte);
40 	return buf;
41 }
42 
43 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
44 {
45 	unsigned long result = 0,value;
46 
47 	if (*cp == '0') {
48 		cp++;
49 		if ((*cp == 'x') && isxdigit(cp[1])) {
50 			base = 16;
51 			cp++;
52 		}
53 		if (!base) {
54 			base = 8;
55 		}
56 	}
57 	if (!base) {
58 		base = 10;
59 	}
60 	while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
61 	    ? toupper(*cp) : *cp)-'A'+10) < base) {
62 		result = result*base + value;
63 		cp++;
64 	}
65 	if (endp)
66 		*endp = (char *)cp;
67 	return result;
68 }
69 
70 int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
71 {
72 	char *tail;
73 	unsigned long val;
74 	size_t len;
75 
76 	*res = 0;
77 	len = strlen(cp);
78 	if (len == 0)
79 		return -EINVAL;
80 
81 	val = simple_strtoul(cp, &tail, base);
82 	if (tail == cp)
83 		return -EINVAL;
84 
85 	if ((*tail == '\0') ||
86 		((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
87 		*res = val;
88 		return 0;
89 	}
90 
91 	return -EINVAL;
92 }
93 
94 long simple_strtol(const char *cp,char **endp,unsigned int base)
95 {
96 	if(*cp=='-')
97 		return -simple_strtoul(cp+1,endp,base);
98 	return simple_strtoul(cp,endp,base);
99 }
100 
101 int ustrtoul(const char *cp, char **endp, unsigned int base)
102 {
103 	unsigned long result = simple_strtoul(cp, endp, base);
104 	switch (**endp) {
105 	case 'G' :
106 		result *= 1024;
107 		/* fall through */
108 	case 'M':
109 		result *= 1024;
110 		/* fall through */
111 	case 'K':
112 	case 'k':
113 		result *= 1024;
114 		if ((*endp)[1] == 'i') {
115 			if ((*endp)[2] == 'B')
116 				(*endp) += 3;
117 			else
118 				(*endp) += 2;
119 		}
120 	}
121 	return result;
122 }
123 
124 unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base)
125 {
126 	unsigned long long result = 0, value;
127 
128 	if (*cp == '0') {
129 		cp++;
130 		if ((*cp == 'x') && isxdigit (cp[1])) {
131 			base = 16;
132 			cp++;
133 		}
134 		if (!base) {
135 			base = 8;
136 		}
137 	}
138 	if (!base) {
139 		base = 10;
140 	}
141 	while (isxdigit (*cp) && (value = isdigit (*cp)
142 				? *cp - '0'
143 				: (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) {
144 		result = result * base + value;
145 		cp++;
146 	}
147 	if (endp)
148 		*endp = (char *) cp;
149 	return result;
150 }
151 
152 /* we use this so that we can do without the ctype library */
153 #define is_digit(c)	((c) >= '0' && (c) <= '9')
154 
155 static int skip_atoi(const char **s)
156 {
157 	int i=0;
158 
159 	while (is_digit(**s))
160 		i = i*10 + *((*s)++) - '0';
161 	return i;
162 }
163 
164 /* Decimal conversion is by far the most typical, and is used
165  * for /proc and /sys data. This directly impacts e.g. top performance
166  * with many processes running. We optimize it for speed
167  * using code from
168  * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
169  * (with permission from the author, Douglas W. Jones). */
170 
171 /* Formats correctly any integer in [0,99999].
172  * Outputs from one to five digits depending on input.
173  * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */
174 static char* put_dec_trunc(char *buf, unsigned q)
175 {
176 	unsigned d3, d2, d1, d0;
177 	d1 = (q>>4) & 0xf;
178 	d2 = (q>>8) & 0xf;
179 	d3 = (q>>12);
180 
181 	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
182 	q = (d0 * 0xcd) >> 11;
183 	d0 = d0 - 10*q;
184 	*buf++ = d0 + '0'; /* least significant digit */
185 	d1 = q + 9*d3 + 5*d2 + d1;
186 	if (d1 != 0) {
187 		q = (d1 * 0xcd) >> 11;
188 		d1 = d1 - 10*q;
189 		*buf++ = d1 + '0'; /* next digit */
190 
191 		d2 = q + 2*d2;
192 		if ((d2 != 0) || (d3 != 0)) {
193 			q = (d2 * 0xd) >> 7;
194 			d2 = d2 - 10*q;
195 			*buf++ = d2 + '0'; /* next digit */
196 
197 			d3 = q + 4*d3;
198 			if (d3 != 0) {
199 				q = (d3 * 0xcd) >> 11;
200 				d3 = d3 - 10*q;
201 				*buf++ = d3 + '0';  /* next digit */
202 				if (q != 0)
203 					*buf++ = q + '0';  /* most sign. digit */
204 			}
205 		}
206 	}
207 	return buf;
208 }
209 /* Same with if's removed. Always emits five digits */
210 static char* put_dec_full(char *buf, unsigned q)
211 {
212 	/* BTW, if q is in [0,9999], 8-bit ints will be enough, */
213 	/* but anyway, gcc produces better code with full-sized ints */
214 	unsigned d3, d2, d1, d0;
215 	d1 = (q>>4) & 0xf;
216 	d2 = (q>>8) & 0xf;
217 	d3 = (q>>12);
218 
219 	/*
220 	 * Possible ways to approx. divide by 10
221 	 * gcc -O2 replaces multiply with shifts and adds
222 	 * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
223 	 * (x * 0x67) >> 10:  1100111
224 	 * (x * 0x34) >> 9:    110100 - same
225 	 * (x * 0x1a) >> 8:     11010 - same
226 	 * (x * 0x0d) >> 7:      1101 - same, shortest code (on i386)
227 	 */
228 
229 	d0 = 6*(d3 + d2 + d1) + (q & 0xf);
230 	q = (d0 * 0xcd) >> 11;
231 	d0 = d0 - 10*q;
232 	*buf++ = d0 + '0';
233 	d1 = q + 9*d3 + 5*d2 + d1;
234 		q = (d1 * 0xcd) >> 11;
235 		d1 = d1 - 10*q;
236 		*buf++ = d1 + '0';
237 
238 		d2 = q + 2*d2;
239 			q = (d2 * 0xd) >> 7;
240 			d2 = d2 - 10*q;
241 			*buf++ = d2 + '0';
242 
243 			d3 = q + 4*d3;
244 				q = (d3 * 0xcd) >> 11; /* - shorter code */
245 				/* q = (d3 * 0x67) >> 10; - would also work */
246 				d3 = d3 - 10*q;
247 				*buf++ = d3 + '0';
248 					*buf++ = q + '0';
249 	return buf;
250 }
251 /* No inlining helps gcc to use registers better */
252 static noinline char* put_dec(char *buf, unsigned NUM_TYPE num)
253 {
254 	while (1) {
255 		unsigned rem;
256 		if (num < 100000)
257 			return put_dec_trunc(buf, num);
258 		rem = do_div(num, 100000);
259 		buf = put_dec_full(buf, rem);
260 	}
261 }
262 
263 #define ZEROPAD	1		/* pad with zero */
264 #define SIGN	2		/* unsigned/signed long */
265 #define PLUS	4		/* show plus */
266 #define SPACE	8		/* space if plus */
267 #define LEFT	16		/* left justified */
268 #define SMALL	32		/* Must be 32 == 0x20 */
269 #define SPECIAL	64		/* 0x */
270 
271 #ifdef CONFIG_SYS_VSNPRINTF
272 /*
273  * Macro to add a new character to our output string, but only if it will
274  * fit. The macro moves to the next character position in the output string.
275  */
276 #define ADDCH(str, ch) do { \
277 	if ((str) < end) \
278 		*(str) = (ch); \
279 	++str; \
280 	} while (0)
281 #else
282 #define ADDCH(str, ch)	(*(str)++ = (ch))
283 #endif
284 
285 static char *number(char *buf, char *end, unsigned NUM_TYPE num,
286 		int base, int size, int precision, int type)
287 {
288 	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
289 	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
290 
291 	char tmp[66];
292 	char sign;
293 	char locase;
294 	int need_pfx = ((type & SPECIAL) && base != 10);
295 	int i;
296 
297 	/* locase = 0 or 0x20. ORing digits or letters with 'locase'
298 	 * produces same digits or (maybe lowercased) letters */
299 	locase = (type & SMALL);
300 	if (type & LEFT)
301 		type &= ~ZEROPAD;
302 	sign = 0;
303 	if (type & SIGN) {
304 		if ((signed NUM_TYPE) num < 0) {
305 			sign = '-';
306 			num = - (signed NUM_TYPE) num;
307 			size--;
308 		} else if (type & PLUS) {
309 			sign = '+';
310 			size--;
311 		} else if (type & SPACE) {
312 			sign = ' ';
313 			size--;
314 		}
315 	}
316 	if (need_pfx) {
317 		size--;
318 		if (base == 16)
319 			size--;
320 	}
321 
322 	/* generate full string in tmp[], in reverse order */
323 	i = 0;
324 	if (num == 0)
325 		tmp[i++] = '0';
326 	/* Generic code, for any base:
327 	else do {
328 		tmp[i++] = (digits[do_div(num,base)] | locase);
329 	} while (num != 0);
330 	*/
331 	else if (base != 10) { /* 8 or 16 */
332 		int mask = base - 1;
333 		int shift = 3;
334 		if (base == 16) shift = 4;
335 		do {
336 			tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
337 			num >>= shift;
338 		} while (num);
339 	} else { /* base 10 */
340 		i = put_dec(tmp, num) - tmp;
341 	}
342 
343 	/* printing 100 using %2d gives "100", not "00" */
344 	if (i > precision)
345 		precision = i;
346 	/* leading space padding */
347 	size -= precision;
348 	if (!(type & (ZEROPAD + LEFT))) {
349 		while (--size >= 0)
350 			ADDCH(buf, ' ');
351 	}
352 	/* sign */
353 	if (sign)
354 		ADDCH(buf, sign);
355 	/* "0x" / "0" prefix */
356 	if (need_pfx) {
357 		ADDCH(buf, '0');
358 		if (base == 16)
359 			ADDCH(buf, 'X' | locase);
360 	}
361 	/* zero or space padding */
362 	if (!(type & LEFT)) {
363 		char c = (type & ZEROPAD) ? '0' : ' ';
364 
365 		while (--size >= 0)
366 			ADDCH(buf, c);
367 	}
368 	/* hmm even more zero padding? */
369 	while (i <= --precision)
370 		ADDCH(buf, '0');
371 	/* actual digits of result */
372 	while (--i >= 0)
373 		ADDCH(buf, tmp[i]);
374 	/* trailing space padding */
375 	while (--size >= 0)
376 		ADDCH(buf, ' ');
377 	return buf;
378 }
379 
380 static char *string(char *buf, char *end, char *s, int field_width,
381 		int precision, int flags)
382 {
383 	int len, i;
384 
385 	if (s == 0)
386 		s = "<NULL>";
387 
388 	len = strnlen(s, precision);
389 
390 	if (!(flags & LEFT))
391 		while (len < field_width--)
392 			ADDCH(buf, ' ');
393 	for (i = 0; i < len; ++i)
394 		ADDCH(buf, *s++);
395 	while (len < field_width--)
396 		ADDCH(buf, ' ');
397 	return buf;
398 }
399 
400 #ifdef CONFIG_CMD_NET
401 static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width,
402 				int precision, int flags)
403 {
404 	char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */
405 	char *p = mac_addr;
406 	int i;
407 
408 	for (i = 0; i < 6; i++) {
409 		p = pack_hex_byte(p, addr[i]);
410 		if (!(flags & SPECIAL) && i != 5)
411 			*p++ = ':';
412 	}
413 	*p = '\0';
414 
415 	return string(buf, end, mac_addr, field_width, precision,
416 		      flags & ~SPECIAL);
417 }
418 
419 static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width,
420 			 int precision, int flags)
421 {
422 	char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */
423 	char *p = ip6_addr;
424 	int i;
425 
426 	for (i = 0; i < 8; i++) {
427 		p = pack_hex_byte(p, addr[2 * i]);
428 		p = pack_hex_byte(p, addr[2 * i + 1]);
429 		if (!(flags & SPECIAL) && i != 7)
430 			*p++ = ':';
431 	}
432 	*p = '\0';
433 
434 	return string(buf, end, ip6_addr, field_width, precision,
435 		      flags & ~SPECIAL);
436 }
437 
438 static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width,
439 			 int precision, int flags)
440 {
441 	char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */
442 	char temp[3];	/* hold each IP quad in reverse order */
443 	char *p = ip4_addr;
444 	int i, digits;
445 
446 	for (i = 0; i < 4; i++) {
447 		digits = put_dec_trunc(temp, addr[i]) - temp;
448 		/* reverse the digits in the quad */
449 		while (digits--)
450 			*p++ = temp[digits];
451 		if (i != 3)
452 			*p++ = '.';
453 	}
454 	*p = '\0';
455 
456 	return string(buf, end, ip4_addr, field_width, precision,
457 		      flags & ~SPECIAL);
458 }
459 #endif
460 
461 /*
462  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
463  * by an extra set of alphanumeric characters that are extended format
464  * specifiers.
465  *
466  * Right now we handle:
467  *
468  * - 'M' For a 6-byte MAC address, it prints the address in the
469  *       usual colon-separated hex notation
470  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated
471  *       decimal for v4 and colon separated network-order 16 bit hex for v6)
472  * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is
473  *       currently the same
474  *
475  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
476  * function pointers are really function descriptors, which contain a
477  * pointer to the real address.
478  */
479 static char *pointer(const char *fmt, char *buf, char *end, void *ptr,
480 		int field_width, int precision, int flags)
481 {
482 	if (!ptr)
483 		return string(buf, end, "(null)", field_width, precision,
484 			      flags);
485 
486 #ifdef CONFIG_CMD_NET
487 	switch (*fmt) {
488 	case 'm':
489 		flags |= SPECIAL;
490 		/* Fallthrough */
491 	case 'M':
492 		return mac_address_string(buf, end, ptr, field_width,
493 					  precision, flags);
494 	case 'i':
495 		flags |= SPECIAL;
496 		/* Fallthrough */
497 	case 'I':
498 		if (fmt[1] == '6')
499 			return ip6_addr_string(buf, end, ptr, field_width,
500 					       precision, flags);
501 		if (fmt[1] == '4')
502 			return ip4_addr_string(buf, end, ptr, field_width,
503 					       precision, flags);
504 		flags &= ~SPECIAL;
505 		break;
506 	}
507 #endif
508 	flags |= SMALL;
509 	if (field_width == -1) {
510 		field_width = 2*sizeof(void *);
511 		flags |= ZEROPAD;
512 	}
513 	return number(buf, end, (unsigned long)ptr, 16, field_width,
514 		      precision, flags);
515 }
516 
517 static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
518 			      va_list args)
519 {
520 	unsigned NUM_TYPE num;
521 	int base;
522 	char *str;
523 
524 	int flags;		/* flags to number() */
525 
526 	int field_width;	/* width of output field */
527 	int precision;		/* min. # of digits for integers; max
528 				   number of chars for from string */
529 	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
530 				/* 'z' support added 23/7/1999 S.H.    */
531 				/* 'z' changed to 'Z' --davidm 1/25/99 */
532 				/* 't' added for ptrdiff_t */
533 	char *end = buf + size;
534 
535 #ifdef CONFIG_SYS_VSNPRINTF
536 	/* Make sure end is always >= buf - do we want this in U-Boot? */
537 	if (end < buf) {
538 		end = ((void *)-1);
539 		size = end - buf;
540 	}
541 #endif
542 	str = buf;
543 
544 	for (; *fmt ; ++fmt) {
545 		if (*fmt != '%') {
546 			ADDCH(str, *fmt);
547 			continue;
548 		}
549 
550 		/* process flags */
551 		flags = 0;
552 		repeat:
553 			++fmt;		/* this also skips first '%' */
554 			switch (*fmt) {
555 				case '-': flags |= LEFT; goto repeat;
556 				case '+': flags |= PLUS; goto repeat;
557 				case ' ': flags |= SPACE; goto repeat;
558 				case '#': flags |= SPECIAL; goto repeat;
559 				case '0': flags |= ZEROPAD; goto repeat;
560 			}
561 
562 		/* get field width */
563 		field_width = -1;
564 		if (is_digit(*fmt))
565 			field_width = skip_atoi(&fmt);
566 		else if (*fmt == '*') {
567 			++fmt;
568 			/* it's the next argument */
569 			field_width = va_arg(args, int);
570 			if (field_width < 0) {
571 				field_width = -field_width;
572 				flags |= LEFT;
573 			}
574 		}
575 
576 		/* get the precision */
577 		precision = -1;
578 		if (*fmt == '.') {
579 			++fmt;
580 			if (is_digit(*fmt))
581 				precision = skip_atoi(&fmt);
582 			else if (*fmt == '*') {
583 				++fmt;
584 				/* it's the next argument */
585 				precision = va_arg(args, int);
586 			}
587 			if (precision < 0)
588 				precision = 0;
589 		}
590 
591 		/* get the conversion qualifier */
592 		qualifier = -1;
593 		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
594 		    *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
595 			qualifier = *fmt;
596 			++fmt;
597 			if (qualifier == 'l' && *fmt == 'l') {
598 				qualifier = 'L';
599 				++fmt;
600 			}
601 		}
602 
603 		/* default base */
604 		base = 10;
605 
606 		switch (*fmt) {
607 		case 'c':
608 			if (!(flags & LEFT)) {
609 				while (--field_width > 0)
610 					ADDCH(str, ' ');
611 			}
612 			ADDCH(str, (unsigned char) va_arg(args, int));
613 			while (--field_width > 0)
614 				ADDCH(str, ' ');
615 			continue;
616 
617 		case 's':
618 			str = string(str, end, va_arg(args, char *),
619 				     field_width, precision, flags);
620 			continue;
621 
622 		case 'p':
623 			str = pointer(fmt+1, str, end,
624 					va_arg(args, void *),
625 					field_width, precision, flags);
626 			/* Skip all alphanumeric pointer suffixes */
627 			while (isalnum(fmt[1]))
628 				fmt++;
629 			continue;
630 
631 		case 'n':
632 			if (qualifier == 'l') {
633 				long * ip = va_arg(args, long *);
634 				*ip = (str - buf);
635 			} else {
636 				int * ip = va_arg(args, int *);
637 				*ip = (str - buf);
638 			}
639 			continue;
640 
641 		case '%':
642 			ADDCH(str, '%');
643 			continue;
644 
645 		/* integer number formats - set up the flags and "break" */
646 		case 'o':
647 			base = 8;
648 			break;
649 
650 		case 'x':
651 			flags |= SMALL;
652 		case 'X':
653 			base = 16;
654 			break;
655 
656 		case 'd':
657 		case 'i':
658 			flags |= SIGN;
659 		case 'u':
660 			break;
661 
662 		default:
663 			ADDCH(str, '%');
664 			if (*fmt)
665 				ADDCH(str, *fmt);
666 			else
667 				--fmt;
668 			continue;
669 		}
670 		if (qualifier == 'L')  /* "quad" for 64 bit variables */
671 			num = va_arg(args, unsigned long long);
672 		else if (qualifier == 'l') {
673 			num = va_arg(args, unsigned long);
674 			if (flags & SIGN)
675 				num = (signed long) num;
676 		} else if (qualifier == 'Z' || qualifier == 'z') {
677 			num = va_arg(args, size_t);
678 		} else if (qualifier == 't') {
679 			num = va_arg(args, ptrdiff_t);
680 		} else if (qualifier == 'h') {
681 			num = (unsigned short) va_arg(args, int);
682 			if (flags & SIGN)
683 				num = (signed short) num;
684 		} else {
685 			num = va_arg(args, unsigned int);
686 			if (flags & SIGN)
687 				num = (signed int) num;
688 		}
689 		str = number(str, end, num, base, field_width, precision,
690 			     flags);
691 	}
692 
693 #ifdef CONFIG_SYS_VSNPRINTF
694 	if (size > 0) {
695 		ADDCH(str, '\0');
696 		if (str > end)
697 			end[-1] = '\0';
698 	}
699 #else
700 	*str = '\0';
701 #endif
702 	/* the trailing null byte doesn't count towards the total */
703 	return str-buf;
704 }
705 
706 #ifdef CONFIG_SYS_VSNPRINTF
707 int vsnprintf(char *buf, size_t size, const char *fmt,
708 			      va_list args)
709 {
710 	return vsnprintf_internal(buf, size, fmt, args);
711 }
712 
713 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
714 {
715 	int i;
716 
717 	i = vsnprintf(buf, size, fmt, args);
718 
719 	if (likely(i < size))
720 		return i;
721 	if (size != 0)
722 		return size - 1;
723 	return 0;
724 }
725 
726 int snprintf(char *buf, size_t size, const char *fmt, ...)
727 {
728 	va_list args;
729 	int i;
730 
731 	va_start(args, fmt);
732 	i = vsnprintf(buf, size, fmt, args);
733 	va_end(args);
734 
735 	return i;
736 }
737 
738 int scnprintf(char *buf, size_t size, const char *fmt, ...)
739 {
740 	va_list args;
741 	int i;
742 
743 	va_start(args, fmt);
744 	i = vscnprintf(buf, size, fmt, args);
745 	va_end(args);
746 
747 	return i;
748 }
749 #endif /* CONFIG_SYS_VSNPRINT */
750 
751 /**
752  * Format a string and place it in a buffer (va_list version)
753  *
754  * @param buf	The buffer to place the result into
755  * @param fmt	The format string to use
756  * @param args	Arguments for the format string
757  *
758  * The function returns the number of characters written
759  * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
760  * buffer overflows.
761  *
762  * If you're not already dealing with a va_list consider using sprintf().
763  */
764 int vsprintf(char *buf, const char *fmt, va_list args)
765 {
766 	return vsnprintf_internal(buf, INT_MAX, fmt, args);
767 }
768 
769 int sprintf(char * buf, const char *fmt, ...)
770 {
771 	va_list args;
772 	int i;
773 
774 	va_start(args, fmt);
775 	i=vsprintf(buf,fmt,args);
776 	va_end(args);
777 	return i;
778 }
779 
780 void panic(const char *fmt, ...)
781 {
782 	va_list	args;
783 	va_start(args, fmt);
784 	vprintf(fmt, args);
785 	putc('\n');
786 	va_end(args);
787 #if defined (CONFIG_PANIC_HANG)
788 	hang();
789 #else
790 	udelay (100000);	/* allow messages to go out */
791 	do_reset (NULL, 0, 0, NULL);
792 #endif
793 	while (1)
794 		;
795 }
796 
797 void __assert_fail(const char *assertion, const char *file, unsigned line,
798 		   const char *function)
799 {
800 	/* This will not return */
801 	panic("%s:%u: %s: Assertion `%s' failed.", file, line, function,
802 	      assertion);
803 }
804 
805 char *simple_itoa(ulong i)
806 {
807 	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
808 	static char local[22];
809 	char *p = &local[21];
810 
811 	*p-- = '\0';
812 	do {
813 		*p-- = '0' + i % 10;
814 		i /= 10;
815 	} while (i > 0);
816 	return p + 1;
817 }
818