xref: /openbmc/u-boot/lib/vsprintf.c (revision 9d86f0c3)
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 static 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 unsigned long 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 == NULL)
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 	/*
499 	 * Being a boot loader, we explicitly allow pointers to
500 	 * (physical) address null.
501 	 */
502 #if 0
503 	if (!ptr)
504 		return string(buf, end, "(null)", field_width, precision,
505 			      flags);
506 #endif
507 
508 #ifdef CONFIG_CMD_NET
509 	switch (*fmt) {
510 	case 'm':
511 		flags |= SPECIAL;
512 		/* Fallthrough */
513 	case 'M':
514 		return mac_address_string(buf, end, ptr, field_width,
515 					  precision, flags);
516 	case 'i':
517 		flags |= SPECIAL;
518 		/* Fallthrough */
519 	case 'I':
520 		if (fmt[1] == '6')
521 			return ip6_addr_string(buf, end, ptr, field_width,
522 					       precision, flags);
523 		if (fmt[1] == '4')
524 			return ip4_addr_string(buf, end, ptr, field_width,
525 					       precision, flags);
526 		flags &= ~SPECIAL;
527 		break;
528 	}
529 #endif
530 	flags |= SMALL;
531 	if (field_width == -1) {
532 		field_width = 2*sizeof(void *);
533 		flags |= ZEROPAD;
534 	}
535 	return number(buf, end, (unsigned long)ptr, 16, field_width,
536 		      precision, flags);
537 }
538 
539 static int vsnprintf_internal(char *buf, size_t size, const char *fmt,
540 			      va_list args)
541 {
542 	u64 num;
543 	int base;
544 	char *str;
545 
546 	int flags;		/* flags to number() */
547 
548 	int field_width;	/* width of output field */
549 	int precision;		/* min. # of digits for integers; max
550 				   number of chars for from string */
551 	int qualifier;		/* 'h', 'l', or 'L' for integer fields */
552 				/* 'z' support added 23/7/1999 S.H.    */
553 				/* 'z' changed to 'Z' --davidm 1/25/99 */
554 				/* 't' added for ptrdiff_t */
555 	char *end = buf + size;
556 
557 #ifdef CONFIG_SYS_VSNPRINTF
558 	/* Make sure end is always >= buf - do we want this in U-Boot? */
559 	if (end < buf) {
560 		end = ((void *)-1);
561 		size = end - buf;
562 	}
563 #endif
564 	str = buf;
565 
566 	for (; *fmt ; ++fmt) {
567 		if (*fmt != '%') {
568 			ADDCH(str, *fmt);
569 			continue;
570 		}
571 
572 		/* process flags */
573 		flags = 0;
574 repeat:
575 			++fmt;		/* this also skips first '%' */
576 			switch (*fmt) {
577 			case '-':
578 				flags |= LEFT;
579 				goto repeat;
580 			case '+':
581 				flags |= PLUS;
582 				goto repeat;
583 			case ' ':
584 				flags |= SPACE;
585 				goto repeat;
586 			case '#':
587 				flags |= SPECIAL;
588 				goto repeat;
589 			case '0':
590 				flags |= ZEROPAD;
591 				goto repeat;
592 			}
593 
594 		/* get field width */
595 		field_width = -1;
596 		if (is_digit(*fmt))
597 			field_width = skip_atoi(&fmt);
598 		else if (*fmt == '*') {
599 			++fmt;
600 			/* it's the next argument */
601 			field_width = va_arg(args, int);
602 			if (field_width < 0) {
603 				field_width = -field_width;
604 				flags |= LEFT;
605 			}
606 		}
607 
608 		/* get the precision */
609 		precision = -1;
610 		if (*fmt == '.') {
611 			++fmt;
612 			if (is_digit(*fmt))
613 				precision = skip_atoi(&fmt);
614 			else if (*fmt == '*') {
615 				++fmt;
616 				/* it's the next argument */
617 				precision = va_arg(args, int);
618 			}
619 			if (precision < 0)
620 				precision = 0;
621 		}
622 
623 		/* get the conversion qualifier */
624 		qualifier = -1;
625 		if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
626 		    *fmt == 'Z' || *fmt == 'z' || *fmt == 't') {
627 			qualifier = *fmt;
628 			++fmt;
629 			if (qualifier == 'l' && *fmt == 'l') {
630 				qualifier = 'L';
631 				++fmt;
632 			}
633 		}
634 
635 		/* default base */
636 		base = 10;
637 
638 		switch (*fmt) {
639 		case 'c':
640 			if (!(flags & LEFT)) {
641 				while (--field_width > 0)
642 					ADDCH(str, ' ');
643 			}
644 			ADDCH(str, (unsigned char) va_arg(args, int));
645 			while (--field_width > 0)
646 				ADDCH(str, ' ');
647 			continue;
648 
649 		case 's':
650 			str = string(str, end, va_arg(args, char *),
651 				     field_width, precision, flags);
652 			continue;
653 
654 		case 'p':
655 			str = pointer(fmt + 1, str, end,
656 					va_arg(args, void *),
657 					field_width, precision, flags);
658 			/* Skip all alphanumeric pointer suffixes */
659 			while (isalnum(fmt[1]))
660 				fmt++;
661 			continue;
662 
663 		case 'n':
664 			if (qualifier == 'l') {
665 				long *ip = va_arg(args, long *);
666 				*ip = (str - buf);
667 			} else {
668 				int *ip = va_arg(args, int *);
669 				*ip = (str - buf);
670 			}
671 			continue;
672 
673 		case '%':
674 			ADDCH(str, '%');
675 			continue;
676 
677 		/* integer number formats - set up the flags and "break" */
678 		case 'o':
679 			base = 8;
680 			break;
681 
682 		case 'x':
683 			flags |= SMALL;
684 		case 'X':
685 			base = 16;
686 			break;
687 
688 		case 'd':
689 		case 'i':
690 			flags |= SIGN;
691 		case 'u':
692 			break;
693 
694 		default:
695 			ADDCH(str, '%');
696 			if (*fmt)
697 				ADDCH(str, *fmt);
698 			else
699 				--fmt;
700 			continue;
701 		}
702 		if (qualifier == 'L')  /* "quad" for 64 bit variables */
703 			num = va_arg(args, unsigned long long);
704 		else if (qualifier == 'l') {
705 			num = va_arg(args, unsigned long);
706 			if (flags & SIGN)
707 				num = (signed long) num;
708 		} else if (qualifier == 'Z' || qualifier == 'z') {
709 			num = va_arg(args, size_t);
710 		} else if (qualifier == 't') {
711 			num = va_arg(args, ptrdiff_t);
712 		} else if (qualifier == 'h') {
713 			num = (unsigned short) va_arg(args, int);
714 			if (flags & SIGN)
715 				num = (signed short) num;
716 		} else {
717 			num = va_arg(args, unsigned int);
718 			if (flags & SIGN)
719 				num = (signed int) num;
720 		}
721 		str = number(str, end, num, base, field_width, precision,
722 			     flags);
723 	}
724 
725 #ifdef CONFIG_SYS_VSNPRINTF
726 	if (size > 0) {
727 		ADDCH(str, '\0');
728 		if (str > end)
729 			end[-1] = '\0';
730 	}
731 #else
732 	*str = '\0';
733 #endif
734 	/* the trailing null byte doesn't count towards the total */
735 	return str - buf;
736 }
737 
738 #ifdef CONFIG_SYS_VSNPRINTF
739 int vsnprintf(char *buf, size_t size, const char *fmt,
740 			      va_list args)
741 {
742 	return vsnprintf_internal(buf, size, fmt, args);
743 }
744 
745 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
746 {
747 	int i;
748 
749 	i = vsnprintf(buf, size, fmt, args);
750 
751 	if (likely(i < size))
752 		return i;
753 	if (size != 0)
754 		return size - 1;
755 	return 0;
756 }
757 
758 int snprintf(char *buf, size_t size, const char *fmt, ...)
759 {
760 	va_list args;
761 	int i;
762 
763 	va_start(args, fmt);
764 	i = vsnprintf(buf, size, fmt, args);
765 	va_end(args);
766 
767 	return i;
768 }
769 
770 int scnprintf(char *buf, size_t size, const char *fmt, ...)
771 {
772 	va_list args;
773 	int i;
774 
775 	va_start(args, fmt);
776 	i = vscnprintf(buf, size, fmt, args);
777 	va_end(args);
778 
779 	return i;
780 }
781 #endif /* CONFIG_SYS_VSNPRINT */
782 
783 /**
784  * Format a string and place it in a buffer (va_list version)
785  *
786  * @param buf	The buffer to place the result into
787  * @param fmt	The format string to use
788  * @param args	Arguments for the format string
789  *
790  * The function returns the number of characters written
791  * into @buf. Use vsnprintf() or vscnprintf() in order to avoid
792  * buffer overflows.
793  *
794  * If you're not already dealing with a va_list consider using sprintf().
795  */
796 int vsprintf(char *buf, const char *fmt, va_list args)
797 {
798 	return vsnprintf_internal(buf, INT_MAX, fmt, args);
799 }
800 
801 int sprintf(char *buf, const char *fmt, ...)
802 {
803 	va_list args;
804 	int i;
805 
806 	va_start(args, fmt);
807 	i = vsprintf(buf, fmt, args);
808 	va_end(args);
809 	return i;
810 }
811 
812 void panic(const char *fmt, ...)
813 {
814 	va_list args;
815 	va_start(args, fmt);
816 	vprintf(fmt, args);
817 	putc('\n');
818 	va_end(args);
819 #if defined(CONFIG_PANIC_HANG)
820 	hang();
821 #else
822 	udelay(100000);	/* allow messages to go out */
823 	do_reset(NULL, 0, 0, NULL);
824 #endif
825 	while (1)
826 		;
827 }
828 
829 void __assert_fail(const char *assertion, const char *file, unsigned line,
830 		   const char *function)
831 {
832 	/* This will not return */
833 	panic("%s:%u: %s: Assertion `%s' failed.", file, line, function,
834 	      assertion);
835 }
836 
837 char *simple_itoa(ulong i)
838 {
839 	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
840 	static char local[22];
841 	char *p = &local[21];
842 
843 	*p-- = '\0';
844 	do {
845 		*p-- = '0' + i % 10;
846 		i /= 10;
847 	} while (i > 0);
848 	return p + 1;
849 }
850