xref: /openbmc/u-boot/lib/tiny-printf.c (revision c6e18144)
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 				for (div = 1000000000; div; div /= 10)
86 					div_out(&num, div);
87 				break;
88 			case 'x':
89 				num = va_arg(va, unsigned int);
90 				for (div = 0x10000000; div; div /= 0x10)
91 					div_out(&num, div);
92 				break;
93 			case 'c':
94 				out((char)(va_arg(va, int)));
95 				break;
96 			case 's':
97 				p = va_arg(va, char*);
98 				break;
99 			case '%':
100 				out('%');
101 			default:
102 				break;
103 			}
104 
105 			*bf = 0;
106 			bf = p;
107 			while (*bf++ && w > 0)
108 				w--;
109 			while (w-- > 0)
110 				putc(lz ? '0' : ' ');
111 			while ((ch = *p++))
112 				putc(ch);
113 		}
114 	}
115 
116 abort:
117 	return 0;
118 }
119 
120 int printf(const char *fmt, ...)
121 {
122 	va_list va;
123 	int ret;
124 
125 	va_start(va, fmt);
126 	ret = vprintf(fmt, va);
127 	va_end(va);
128 
129 	return ret;
130 }
131