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