xref: /rk3399_rockchip-uboot/lib/tiny-printf.c (revision 7d9cde1031040a4931d6e12da7d9767b7e1d85d4)
1*7d9cde10SStefan Roese /*
2*7d9cde10SStefan Roese  * Tiny printf version for SPL
3*7d9cde10SStefan Roese  *
4*7d9cde10SStefan Roese  * Copied from:
5*7d9cde10SStefan Roese  * http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
6*7d9cde10SStefan Roese  *
7*7d9cde10SStefan Roese  * Copyright (C) 2004,2008  Kustaa Nyholm
8*7d9cde10SStefan Roese  *
9*7d9cde10SStefan Roese  * SPDX-License-Identifier:	LGPL-2.1+
10*7d9cde10SStefan Roese  */
11*7d9cde10SStefan Roese 
12*7d9cde10SStefan Roese #include <common.h>
13*7d9cde10SStefan Roese #include <stdarg.h>
14*7d9cde10SStefan Roese #include <serial.h>
15*7d9cde10SStefan Roese 
16*7d9cde10SStefan Roese static char *bf;
17*7d9cde10SStefan Roese static char buf[12];
18*7d9cde10SStefan Roese static unsigned int num;
19*7d9cde10SStefan Roese static char uc;
20*7d9cde10SStefan Roese static char zs;
21*7d9cde10SStefan Roese 
22*7d9cde10SStefan Roese static void out(char c)
23*7d9cde10SStefan Roese {
24*7d9cde10SStefan Roese 	*bf++ = c;
25*7d9cde10SStefan Roese }
26*7d9cde10SStefan Roese 
27*7d9cde10SStefan Roese static void out_dgt(char dgt)
28*7d9cde10SStefan Roese {
29*7d9cde10SStefan Roese 	out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10));
30*7d9cde10SStefan Roese 	zs = 1;
31*7d9cde10SStefan Roese }
32*7d9cde10SStefan Roese 
33*7d9cde10SStefan Roese static void div_out(unsigned int div)
34*7d9cde10SStefan Roese {
35*7d9cde10SStefan Roese 	unsigned char dgt = 0;
36*7d9cde10SStefan Roese 
37*7d9cde10SStefan Roese 	num &= 0xffff; /* just for testing the code with 32 bit ints */
38*7d9cde10SStefan Roese 	while (num >= div) {
39*7d9cde10SStefan Roese 		num -= div;
40*7d9cde10SStefan Roese 		dgt++;
41*7d9cde10SStefan Roese 	}
42*7d9cde10SStefan Roese 
43*7d9cde10SStefan Roese 	if (zs || dgt > 0)
44*7d9cde10SStefan Roese 		out_dgt(dgt);
45*7d9cde10SStefan Roese }
46*7d9cde10SStefan Roese 
47*7d9cde10SStefan Roese int printf(const char *fmt, ...)
48*7d9cde10SStefan Roese {
49*7d9cde10SStefan Roese 	va_list va;
50*7d9cde10SStefan Roese 	char ch;
51*7d9cde10SStefan Roese 	char *p;
52*7d9cde10SStefan Roese 
53*7d9cde10SStefan Roese 	va_start(va, fmt);
54*7d9cde10SStefan Roese 
55*7d9cde10SStefan Roese 	while ((ch = *(fmt++))) {
56*7d9cde10SStefan Roese 		if (ch != '%') {
57*7d9cde10SStefan Roese 			putc(ch);
58*7d9cde10SStefan Roese 		} else {
59*7d9cde10SStefan Roese 			char lz = 0;
60*7d9cde10SStefan Roese 			char w = 0;
61*7d9cde10SStefan Roese 
62*7d9cde10SStefan Roese 			ch = *(fmt++);
63*7d9cde10SStefan Roese 			if (ch == '0') {
64*7d9cde10SStefan Roese 				ch = *(fmt++);
65*7d9cde10SStefan Roese 				lz = 1;
66*7d9cde10SStefan Roese 			}
67*7d9cde10SStefan Roese 
68*7d9cde10SStefan Roese 			if (ch >= '0' && ch <= '9') {
69*7d9cde10SStefan Roese 				w = 0;
70*7d9cde10SStefan Roese 				while (ch >= '0' && ch <= '9') {
71*7d9cde10SStefan Roese 					w = (((w << 2) + w) << 1) + ch - '0';
72*7d9cde10SStefan Roese 					ch = *fmt++;
73*7d9cde10SStefan Roese 				}
74*7d9cde10SStefan Roese 			}
75*7d9cde10SStefan Roese 			bf = buf;
76*7d9cde10SStefan Roese 			p = bf;
77*7d9cde10SStefan Roese 			zs = 0;
78*7d9cde10SStefan Roese 
79*7d9cde10SStefan Roese 			switch (ch) {
80*7d9cde10SStefan Roese 			case 0:
81*7d9cde10SStefan Roese 				goto abort;
82*7d9cde10SStefan Roese 			case 'u':
83*7d9cde10SStefan Roese 			case 'd':
84*7d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
85*7d9cde10SStefan Roese 				if (ch == 'd' && (int)num < 0) {
86*7d9cde10SStefan Roese 					num = -(int)num;
87*7d9cde10SStefan Roese 					out('-');
88*7d9cde10SStefan Roese 				}
89*7d9cde10SStefan Roese 				div_out(10000);
90*7d9cde10SStefan Roese 				div_out(1000);
91*7d9cde10SStefan Roese 				div_out(100);
92*7d9cde10SStefan Roese 				div_out(10);
93*7d9cde10SStefan Roese 				out_dgt(num);
94*7d9cde10SStefan Roese 				break;
95*7d9cde10SStefan Roese 			case 'x':
96*7d9cde10SStefan Roese 			case 'X':
97*7d9cde10SStefan Roese 				uc = ch == 'X';
98*7d9cde10SStefan Roese 				num = va_arg(va, unsigned int);
99*7d9cde10SStefan Roese 				div_out(0x1000);
100*7d9cde10SStefan Roese 				div_out(0x100);
101*7d9cde10SStefan Roese 				div_out(0x10);
102*7d9cde10SStefan Roese 				out_dgt(num);
103*7d9cde10SStefan Roese 				break;
104*7d9cde10SStefan Roese 			case 'c':
105*7d9cde10SStefan Roese 				out((char)(va_arg(va, int)));
106*7d9cde10SStefan Roese 				break;
107*7d9cde10SStefan Roese 			case 's':
108*7d9cde10SStefan Roese 				p = va_arg(va, char*);
109*7d9cde10SStefan Roese 				break;
110*7d9cde10SStefan Roese 			case '%':
111*7d9cde10SStefan Roese 				out('%');
112*7d9cde10SStefan Roese 			default:
113*7d9cde10SStefan Roese 				break;
114*7d9cde10SStefan Roese 			}
115*7d9cde10SStefan Roese 
116*7d9cde10SStefan Roese 			*bf = 0;
117*7d9cde10SStefan Roese 			bf = p;
118*7d9cde10SStefan Roese 			while (*bf++ && w > 0)
119*7d9cde10SStefan Roese 				w--;
120*7d9cde10SStefan Roese 			while (w-- > 0)
121*7d9cde10SStefan Roese 				putc(lz ? '0' : ' ');
122*7d9cde10SStefan Roese 			while ((ch = *p++))
123*7d9cde10SStefan Roese 				putc(ch);
124*7d9cde10SStefan Roese 		}
125*7d9cde10SStefan Roese 	}
126*7d9cde10SStefan Roese 
127*7d9cde10SStefan Roese abort:
128*7d9cde10SStefan Roese 	va_end(va);
129*7d9cde10SStefan Roese 	return 0;
130*7d9cde10SStefan Roese }
131