xref: /rk3399_rockchip-uboot/lib/tiny-printf.c (revision 8e31681c5a5a2fd6bbdf751bcc900a4481e2fa29)
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 
167d9cde10SStefan Roese static char *bf;
177d9cde10SStefan Roese static char zs;
187d9cde10SStefan Roese 
197d9cde10SStefan Roese static void out(char c)
207d9cde10SStefan Roese {
217d9cde10SStefan Roese 	*bf++ = c;
227d9cde10SStefan Roese }
237d9cde10SStefan Roese 
247d9cde10SStefan Roese static void out_dgt(char dgt)
257d9cde10SStefan Roese {
26a5ecdd08SStefan Roese 	out(dgt + (dgt < 10 ? '0' : 'a' - 10));
277d9cde10SStefan Roese 	zs = 1;
287d9cde10SStefan Roese }
297d9cde10SStefan Roese 
30a5ecdd08SStefan Roese static void div_out(unsigned int *num, unsigned int div)
317d9cde10SStefan Roese {
327d9cde10SStefan Roese 	unsigned char dgt = 0;
337d9cde10SStefan Roese 
34a5ecdd08SStefan Roese 	while (*num >= div) {
35a5ecdd08SStefan Roese 		*num -= div;
367d9cde10SStefan Roese 		dgt++;
377d9cde10SStefan Roese 	}
387d9cde10SStefan Roese 
397d9cde10SStefan Roese 	if (zs || dgt > 0)
407d9cde10SStefan Roese 		out_dgt(dgt);
417d9cde10SStefan Roese }
427d9cde10SStefan Roese 
43962a43ccSSjoerd Simons int vprintf(const char *fmt, va_list va)
447d9cde10SStefan Roese {
457d9cde10SStefan Roese 	char ch;
467d9cde10SStefan Roese 	char *p;
47a5ecdd08SStefan Roese 	unsigned int num;
48a5ecdd08SStefan Roese 	char buf[12];
49a5ecdd08SStefan Roese 	unsigned int div;
507d9cde10SStefan Roese 
517d9cde10SStefan Roese 	while ((ch = *(fmt++))) {
527d9cde10SStefan Roese 		if (ch != '%') {
537d9cde10SStefan Roese 			putc(ch);
547d9cde10SStefan Roese 		} else {
557d9cde10SStefan Roese 			char lz = 0;
567d9cde10SStefan Roese 			char w = 0;
577d9cde10SStefan Roese 
587d9cde10SStefan Roese 			ch = *(fmt++);
597d9cde10SStefan Roese 			if (ch == '0') {
607d9cde10SStefan Roese 				ch = *(fmt++);
617d9cde10SStefan Roese 				lz = 1;
627d9cde10SStefan Roese 			}
637d9cde10SStefan Roese 
647d9cde10SStefan Roese 			if (ch >= '0' && ch <= '9') {
657d9cde10SStefan Roese 				w = 0;
667d9cde10SStefan Roese 				while (ch >= '0' && ch <= '9') {
67a5ecdd08SStefan Roese 					w = (w * 10) + ch - '0';
687d9cde10SStefan Roese 					ch = *fmt++;
697d9cde10SStefan Roese 				}
707d9cde10SStefan Roese 			}
717d9cde10SStefan Roese 			bf = buf;
727d9cde10SStefan Roese 			p = bf;
737d9cde10SStefan Roese 			zs = 0;
747d9cde10SStefan Roese 
757d9cde10SStefan Roese 			switch (ch) {
767d9cde10SStefan Roese 			case 0:
777d9cde10SStefan Roese 				goto abort;
787d9cde10SStefan Roese 			case 'u':
797d9cde10SStefan Roese 			case 'd':
807d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
817d9cde10SStefan Roese 				if (ch == 'd' && (int)num < 0) {
827d9cde10SStefan Roese 					num = -(int)num;
837d9cde10SStefan Roese 					out('-');
847d9cde10SStefan Roese 				}
85a5ecdd08SStefan Roese 				for (div = 1000000000; div; div /= 10)
86a5ecdd08SStefan Roese 					div_out(&num, div);
877d9cde10SStefan Roese 				break;
887d9cde10SStefan Roese 			case 'x':
897d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
90a5ecdd08SStefan Roese 				for (div = 0x10000000; div; div /= 0x10)
91a5ecdd08SStefan Roese 					div_out(&num, div);
927d9cde10SStefan Roese 				break;
937d9cde10SStefan Roese 			case 'c':
947d9cde10SStefan Roese 				out((char)(va_arg(va, int)));
957d9cde10SStefan Roese 				break;
967d9cde10SStefan Roese 			case 's':
977d9cde10SStefan Roese 				p = va_arg(va, char*);
987d9cde10SStefan Roese 				break;
997d9cde10SStefan Roese 			case '%':
1007d9cde10SStefan Roese 				out('%');
1017d9cde10SStefan Roese 			default:
1027d9cde10SStefan Roese 				break;
1037d9cde10SStefan Roese 			}
1047d9cde10SStefan Roese 
1057d9cde10SStefan Roese 			*bf = 0;
1067d9cde10SStefan Roese 			bf = p;
1077d9cde10SStefan Roese 			while (*bf++ && w > 0)
1087d9cde10SStefan Roese 				w--;
1097d9cde10SStefan Roese 			while (w-- > 0)
1107d9cde10SStefan Roese 				putc(lz ? '0' : ' ');
111*8e31681cSSimon Glass 			if (p) {
1127d9cde10SStefan Roese 				while ((ch = *p++))
1137d9cde10SStefan Roese 					putc(ch);
1147d9cde10SStefan Roese 			}
1157d9cde10SStefan Roese 		}
116*8e31681cSSimon Glass 	}
1177d9cde10SStefan Roese 
1187d9cde10SStefan Roese abort:
1197d9cde10SStefan Roese 	return 0;
1207d9cde10SStefan Roese }
121962a43ccSSjoerd Simons 
122962a43ccSSjoerd Simons int printf(const char *fmt, ...)
123962a43ccSSjoerd Simons {
124962a43ccSSjoerd Simons 	va_list va;
125962a43ccSSjoerd Simons 	int ret;
126962a43ccSSjoerd Simons 
127962a43ccSSjoerd Simons 	va_start(va, fmt);
128962a43ccSSjoerd Simons 	ret = vprintf(fmt, va);
129962a43ccSSjoerd Simons 	va_end(va);
130962a43ccSSjoerd Simons 
131962a43ccSSjoerd Simons 	return ret;
132962a43ccSSjoerd Simons }
133