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