xref: /rk3399_rockchip-uboot/lib/tiny-printf.c (revision 45313e83b842ab31464e2593ab2e39aa0287fbf7)
17d9cde10SStefan Roese /*
27d9cde10SStefan Roese  * Tiny printf version for SPL
37d9cde10SStefan Roese  *
47d9cde10SStefan Roese  * Copied from:
57d9cde10SStefan Roese  * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
67d9cde10SStefan Roese  *
77d9cde10SStefan Roese  * Copyright (C) 2004,2008  Kustaa Nyholm
87d9cde10SStefan Roese  *
97d9cde10SStefan Roese  * SPDX-License-Identifier:	LGPL-2.1+
107d9cde10SStefan Roese  */
117d9cde10SStefan Roese 
127d9cde10SStefan Roese #include <common.h>
137d9cde10SStefan Roese #include <stdarg.h>
147d9cde10SStefan Roese #include <serial.h>
157d9cde10SStefan Roese 
16*45313e83SSimon Glass struct printf_info {
17*45313e83SSimon Glass 	char *bf;	/* Digit buffer */
18*45313e83SSimon Glass 	char zs;	/* non-zero if a digit has been written */
19*45313e83SSimon Glass 	char *outstr;	/* Next output position for sprintf() */
207d9cde10SStefan Roese 
21*45313e83SSimon Glass 	/* Output a character */
22*45313e83SSimon Glass 	void (*putc)(struct printf_info *info, char ch);
23*45313e83SSimon Glass };
245c411d88SSimon Glass 
25*45313e83SSimon Glass void putc_normal(struct printf_info *info, char ch)
267d9cde10SStefan Roese {
27*45313e83SSimon Glass 	putc(ch);
287d9cde10SStefan Roese }
297d9cde10SStefan Roese 
30*45313e83SSimon Glass static void out(struct printf_info *info, char c)
317d9cde10SStefan Roese {
32*45313e83SSimon Glass 	*info->bf++ = c;
337d9cde10SStefan Roese }
347d9cde10SStefan Roese 
35*45313e83SSimon Glass static void out_dgt(struct printf_info *info, char dgt)
36*45313e83SSimon Glass {
37*45313e83SSimon Glass 	out(info, dgt + (dgt < 10 ? '0' : 'a' - 10));
38*45313e83SSimon Glass 	info->zs = 1;
39*45313e83SSimon Glass }
40*45313e83SSimon Glass 
41*45313e83SSimon Glass static void div_out(struct printf_info *info, unsigned int *num,
42*45313e83SSimon Glass 		    unsigned int div)
437d9cde10SStefan Roese {
447d9cde10SStefan Roese 	unsigned char dgt = 0;
457d9cde10SStefan Roese 
46a5ecdd08SStefan Roese 	while (*num >= div) {
47a5ecdd08SStefan Roese 		*num -= div;
487d9cde10SStefan Roese 		dgt++;
497d9cde10SStefan Roese 	}
507d9cde10SStefan Roese 
51*45313e83SSimon Glass 	if (info->zs || dgt > 0)
52*45313e83SSimon Glass 		out_dgt(info, dgt);
537d9cde10SStefan Roese }
547d9cde10SStefan Roese 
55*45313e83SSimon Glass int _vprintf(struct printf_info *info, const char *fmt, va_list va)
567d9cde10SStefan Roese {
577d9cde10SStefan Roese 	char ch;
587d9cde10SStefan Roese 	char *p;
59a5ecdd08SStefan Roese 	unsigned int num;
60a5ecdd08SStefan Roese 	char buf[12];
61a5ecdd08SStefan Roese 	unsigned int div;
627d9cde10SStefan Roese 
637d9cde10SStefan Roese 	while ((ch = *(fmt++))) {
647d9cde10SStefan Roese 		if (ch != '%') {
65*45313e83SSimon Glass 			info->putc(info, ch);
667d9cde10SStefan Roese 		} else {
671fb67608SSimon Glass 			bool lz = false;
681fb67608SSimon Glass 			int width = 0;
697d9cde10SStefan Roese 
707d9cde10SStefan Roese 			ch = *(fmt++);
717d9cde10SStefan Roese 			if (ch == '0') {
727d9cde10SStefan Roese 				ch = *(fmt++);
737d9cde10SStefan Roese 				lz = 1;
747d9cde10SStefan Roese 			}
757d9cde10SStefan Roese 
767d9cde10SStefan Roese 			if (ch >= '0' && ch <= '9') {
771fb67608SSimon Glass 				width = 0;
787d9cde10SStefan Roese 				while (ch >= '0' && ch <= '9') {
791fb67608SSimon Glass 					width = (width * 10) + ch - '0';
807d9cde10SStefan Roese 					ch = *fmt++;
817d9cde10SStefan Roese 				}
827d9cde10SStefan Roese 			}
83*45313e83SSimon Glass 			info->bf = buf;
84*45313e83SSimon Glass 			p = info->bf;
85*45313e83SSimon Glass 			info->zs = 0;
867d9cde10SStefan Roese 
877d9cde10SStefan Roese 			switch (ch) {
881fb67608SSimon Glass 			case '\0':
897d9cde10SStefan Roese 				goto abort;
907d9cde10SStefan Roese 			case 'u':
917d9cde10SStefan Roese 			case 'd':
927d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
937d9cde10SStefan Roese 				if (ch == 'd' && (int)num < 0) {
947d9cde10SStefan Roese 					num = -(int)num;
95*45313e83SSimon Glass 					out(info, '-');
967d9cde10SStefan Roese 				}
9774b1320aSSimon Glass 				if (!num) {
98*45313e83SSimon Glass 					out_dgt(info, 0);
9974b1320aSSimon Glass 				} else {
100a5ecdd08SStefan Roese 					for (div = 1000000000; div; div /= 10)
101*45313e83SSimon Glass 						div_out(info, &num, div);
10274b1320aSSimon Glass 				}
1037d9cde10SStefan Roese 				break;
1047d9cde10SStefan Roese 			case 'x':
1057d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
10674b1320aSSimon Glass 				if (!num) {
107*45313e83SSimon Glass 					out_dgt(info, 0);
10874b1320aSSimon Glass 				} else {
109a5ecdd08SStefan Roese 					for (div = 0x10000000; div; div /= 0x10)
110*45313e83SSimon Glass 						div_out(info, &num, div);
11174b1320aSSimon Glass 				}
1127d9cde10SStefan Roese 				break;
1137d9cde10SStefan Roese 			case 'c':
114*45313e83SSimon Glass 				out(info, (char)(va_arg(va, int)));
1157d9cde10SStefan Roese 				break;
1167d9cde10SStefan Roese 			case 's':
1177d9cde10SStefan Roese 				p = va_arg(va, char*);
1187d9cde10SStefan Roese 				break;
1197d9cde10SStefan Roese 			case '%':
120*45313e83SSimon Glass 				out(info, '%');
1217d9cde10SStefan Roese 			default:
1227d9cde10SStefan Roese 				break;
1237d9cde10SStefan Roese 			}
1247d9cde10SStefan Roese 
125*45313e83SSimon Glass 			*info->bf = 0;
126*45313e83SSimon Glass 			info->bf = p;
127*45313e83SSimon Glass 			while (*info->bf++ && width > 0)
1281fb67608SSimon Glass 				width--;
1291fb67608SSimon Glass 			while (width-- > 0)
130*45313e83SSimon Glass 				info->putc(info, lz ? '0' : ' ');
1318e31681cSSimon Glass 			if (p) {
1327d9cde10SStefan Roese 				while ((ch = *p++))
133*45313e83SSimon Glass 					info->putc(info, ch);
1347d9cde10SStefan Roese 			}
1357d9cde10SStefan Roese 		}
1368e31681cSSimon Glass 	}
1377d9cde10SStefan Roese 
1387d9cde10SStefan Roese abort:
1397d9cde10SStefan Roese 	return 0;
1407d9cde10SStefan Roese }
141962a43ccSSjoerd Simons 
142da70b4d1SHans de Goede int vprintf(const char *fmt, va_list va)
143da70b4d1SHans de Goede {
144*45313e83SSimon Glass 	struct printf_info info;
145*45313e83SSimon Glass 
146*45313e83SSimon Glass 	info.putc = putc_normal;
147*45313e83SSimon Glass 	return _vprintf(&info, fmt, va);
148da70b4d1SHans de Goede }
149da70b4d1SHans de Goede 
150962a43ccSSjoerd Simons int printf(const char *fmt, ...)
151962a43ccSSjoerd Simons {
152*45313e83SSimon Glass 	struct printf_info info;
153*45313e83SSimon Glass 
154962a43ccSSjoerd Simons 	va_list va;
155962a43ccSSjoerd Simons 	int ret;
156962a43ccSSjoerd Simons 
157*45313e83SSimon Glass 	info.putc = putc_normal;
158962a43ccSSjoerd Simons 	va_start(va, fmt);
159*45313e83SSimon Glass 	ret = _vprintf(&info, fmt, va);
160962a43ccSSjoerd Simons 	va_end(va);
161962a43ccSSjoerd Simons 
162962a43ccSSjoerd Simons 	return ret;
163962a43ccSSjoerd Simons }
1645c411d88SSimon Glass 
165*45313e83SSimon Glass static void putc_outstr(struct printf_info *info, char ch)
1665c411d88SSimon Glass {
167*45313e83SSimon Glass 	*info->outstr++ = ch;
1685c411d88SSimon Glass }
1695c411d88SSimon Glass 
170abeb272dSMarek Vasut int sprintf(char *buf, const char *fmt, ...)
1715c411d88SSimon Glass {
172*45313e83SSimon Glass 	struct printf_info info;
1735c411d88SSimon Glass 	va_list va;
1745c411d88SSimon Glass 	int ret;
1755c411d88SSimon Glass 
1765c411d88SSimon Glass 	va_start(va, fmt);
177*45313e83SSimon Glass 	info.outstr = buf;
178*45313e83SSimon Glass 	info.putc = putc_outstr;
179*45313e83SSimon Glass 	ret = _vprintf(&info, fmt, va);
1805c411d88SSimon Glass 	va_end(va);
181*45313e83SSimon Glass 	*info.outstr = '\0';
1825c411d88SSimon Glass 
1835c411d88SSimon Glass 	return ret;
1845c411d88SSimon Glass }
185abeb272dSMarek Vasut 
186abeb272dSMarek Vasut /* Note that size is ignored */
187abeb272dSMarek Vasut int snprintf(char *buf, size_t size, const char *fmt, ...)
188abeb272dSMarek Vasut {
189*45313e83SSimon Glass 	struct printf_info info;
190abeb272dSMarek Vasut 	va_list va;
191abeb272dSMarek Vasut 	int ret;
192abeb272dSMarek Vasut 
193abeb272dSMarek Vasut 	va_start(va, fmt);
194*45313e83SSimon Glass 	info.outstr = buf;
195*45313e83SSimon Glass 	info.putc = putc_outstr;
196*45313e83SSimon Glass 	ret = _vprintf(&info, fmt, va);
197abeb272dSMarek Vasut 	va_end(va);
198*45313e83SSimon Glass 	*info.outstr = '\0';
199abeb272dSMarek Vasut 
200abeb272dSMarek Vasut 	return ret;
201abeb272dSMarek Vasut }
202e2409139SSimon Glass 
203e2409139SSimon Glass void __assert_fail(const char *assertion, const char *file, unsigned line,
204e2409139SSimon Glass 		   const char *function)
205e2409139SSimon Glass {
206e2409139SSimon Glass 	/* This will not return */
207e2409139SSimon Glass 	printf("%s:%u: %s: Assertion `%s' failed.", file, line, function,
208e2409139SSimon Glass 	       assertion);
209e2409139SSimon Glass 	hang();
210e2409139SSimon Glass }
211