xref: /openbmc/u-boot/lib/tiny-printf.c (revision 5be93569)
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 printf(const char *fmt, ...)
44 {
45 	va_list va;
46 	char ch;
47 	char *p;
48 	unsigned int num;
49 	char buf[12];
50 	unsigned int div;
51 
52 	va_start(va, fmt);
53 
54 	while ((ch = *(fmt++))) {
55 		if (ch != '%') {
56 			putc(ch);
57 		} else {
58 			char lz = 0;
59 			char w = 0;
60 
61 			ch = *(fmt++);
62 			if (ch == '0') {
63 				ch = *(fmt++);
64 				lz = 1;
65 			}
66 
67 			if (ch >= '0' && ch <= '9') {
68 				w = 0;
69 				while (ch >= '0' && ch <= '9') {
70 					w = (w * 10) + ch - '0';
71 					ch = *fmt++;
72 				}
73 			}
74 			bf = buf;
75 			p = bf;
76 			zs = 0;
77 
78 			switch (ch) {
79 			case 0:
80 				goto abort;
81 			case 'u':
82 			case 'd':
83 				num = va_arg(va, unsigned int);
84 				if (ch == 'd' && (int)num < 0) {
85 					num = -(int)num;
86 					out('-');
87 				}
88 				for (div = 1000000000; div; div /= 10)
89 					div_out(&num, div);
90 				break;
91 			case 'x':
92 				num = va_arg(va, unsigned int);
93 				for (div = 0x10000000; div; div /= 0x10)
94 					div_out(&num, div);
95 				break;
96 			case 'c':
97 				out((char)(va_arg(va, int)));
98 				break;
99 			case 's':
100 				p = va_arg(va, char*);
101 				break;
102 			case '%':
103 				out('%');
104 			default:
105 				break;
106 			}
107 
108 			*bf = 0;
109 			bf = p;
110 			while (*bf++ && w > 0)
111 				w--;
112 			while (w-- > 0)
113 				putc(lz ? '0' : ' ');
114 			while ((ch = *p++))
115 				putc(ch);
116 		}
117 	}
118 
119 abort:
120 	va_end(va);
121 	return 0;
122 }
123