xref: /rk3399_rockchip-uboot/lib/tiny-printf.c (revision a5ecdd08fdf647c7c5a97e937ebed2d97549352f)
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 {
26*a5ecdd08SStefan Roese 	out(dgt + (dgt < 10 ? '0' : 'a' - 10));
277d9cde10SStefan Roese 	zs = 1;
287d9cde10SStefan Roese }
297d9cde10SStefan Roese 
30*a5ecdd08SStefan Roese static void div_out(unsigned int *num, unsigned int div)
317d9cde10SStefan Roese {
327d9cde10SStefan Roese 	unsigned char dgt = 0;
337d9cde10SStefan Roese 
34*a5ecdd08SStefan Roese 	while (*num >= div) {
35*a5ecdd08SStefan 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 
437d9cde10SStefan Roese int printf(const char *fmt, ...)
447d9cde10SStefan Roese {
457d9cde10SStefan Roese 	va_list va;
467d9cde10SStefan Roese 	char ch;
477d9cde10SStefan Roese 	char *p;
48*a5ecdd08SStefan Roese 	unsigned int num;
49*a5ecdd08SStefan Roese 	char buf[12];
50*a5ecdd08SStefan Roese 	unsigned int div;
517d9cde10SStefan Roese 
527d9cde10SStefan Roese 	va_start(va, fmt);
537d9cde10SStefan Roese 
547d9cde10SStefan Roese 	while ((ch = *(fmt++))) {
557d9cde10SStefan Roese 		if (ch != '%') {
567d9cde10SStefan Roese 			putc(ch);
577d9cde10SStefan Roese 		} else {
587d9cde10SStefan Roese 			char lz = 0;
597d9cde10SStefan Roese 			char w = 0;
607d9cde10SStefan Roese 
617d9cde10SStefan Roese 			ch = *(fmt++);
627d9cde10SStefan Roese 			if (ch == '0') {
637d9cde10SStefan Roese 				ch = *(fmt++);
647d9cde10SStefan Roese 				lz = 1;
657d9cde10SStefan Roese 			}
667d9cde10SStefan Roese 
677d9cde10SStefan Roese 			if (ch >= '0' && ch <= '9') {
687d9cde10SStefan Roese 				w = 0;
697d9cde10SStefan Roese 				while (ch >= '0' && ch <= '9') {
70*a5ecdd08SStefan Roese 					w = (w * 10) + ch - '0';
717d9cde10SStefan Roese 					ch = *fmt++;
727d9cde10SStefan Roese 				}
737d9cde10SStefan Roese 			}
747d9cde10SStefan Roese 			bf = buf;
757d9cde10SStefan Roese 			p = bf;
767d9cde10SStefan Roese 			zs = 0;
777d9cde10SStefan Roese 
787d9cde10SStefan Roese 			switch (ch) {
797d9cde10SStefan Roese 			case 0:
807d9cde10SStefan Roese 				goto abort;
817d9cde10SStefan Roese 			case 'u':
827d9cde10SStefan Roese 			case 'd':
837d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
847d9cde10SStefan Roese 				if (ch == 'd' && (int)num < 0) {
857d9cde10SStefan Roese 					num = -(int)num;
867d9cde10SStefan Roese 					out('-');
877d9cde10SStefan Roese 				}
88*a5ecdd08SStefan Roese 				for (div = 1000000000; div; div /= 10)
89*a5ecdd08SStefan Roese 					div_out(&num, div);
907d9cde10SStefan Roese 				break;
917d9cde10SStefan Roese 			case 'x':
927d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
93*a5ecdd08SStefan Roese 				for (div = 0x10000000; div; div /= 0x10)
94*a5ecdd08SStefan Roese 					div_out(&num, div);
957d9cde10SStefan Roese 				break;
967d9cde10SStefan Roese 			case 'c':
977d9cde10SStefan Roese 				out((char)(va_arg(va, int)));
987d9cde10SStefan Roese 				break;
997d9cde10SStefan Roese 			case 's':
1007d9cde10SStefan Roese 				p = va_arg(va, char*);
1017d9cde10SStefan Roese 				break;
1027d9cde10SStefan Roese 			case '%':
1037d9cde10SStefan Roese 				out('%');
1047d9cde10SStefan Roese 			default:
1057d9cde10SStefan Roese 				break;
1067d9cde10SStefan Roese 			}
1077d9cde10SStefan Roese 
1087d9cde10SStefan Roese 			*bf = 0;
1097d9cde10SStefan Roese 			bf = p;
1107d9cde10SStefan Roese 			while (*bf++ && w > 0)
1117d9cde10SStefan Roese 				w--;
1127d9cde10SStefan Roese 			while (w-- > 0)
1137d9cde10SStefan Roese 				putc(lz ? '0' : ' ');
1147d9cde10SStefan Roese 			while ((ch = *p++))
1157d9cde10SStefan Roese 				putc(ch);
1167d9cde10SStefan Roese 		}
1177d9cde10SStefan Roese 	}
1187d9cde10SStefan Roese 
1197d9cde10SStefan Roese abort:
1207d9cde10SStefan Roese 	va_end(va);
1217d9cde10SStefan Roese 	return 0;
1227d9cde10SStefan Roese }
123