]>
Commit | Line | Data |
---|---|---|
7d9cde10 SR |
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; | |
7d9cde10 SR |
17 | static char zs; |
18 | ||
5c411d88 SG |
19 | /* Current position in sprintf() output string */ |
20 | static char *outstr; | |
21 | ||
7d9cde10 SR |
22 | static void out(char c) |
23 | { | |
24 | *bf++ = c; | |
25 | } | |
26 | ||
27 | static void out_dgt(char dgt) | |
28 | { | |
a5ecdd08 | 29 | out(dgt + (dgt < 10 ? '0' : 'a' - 10)); |
7d9cde10 SR |
30 | zs = 1; |
31 | } | |
32 | ||
a5ecdd08 | 33 | static void div_out(unsigned int *num, unsigned int div) |
7d9cde10 SR |
34 | { |
35 | unsigned char dgt = 0; | |
36 | ||
a5ecdd08 SR |
37 | while (*num >= div) { |
38 | *num -= div; | |
7d9cde10 SR |
39 | dgt++; |
40 | } | |
41 | ||
42 | if (zs || dgt > 0) | |
43 | out_dgt(dgt); | |
44 | } | |
45 | ||
5c411d88 | 46 | int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch)) |
7d9cde10 | 47 | { |
7d9cde10 SR |
48 | char ch; |
49 | char *p; | |
a5ecdd08 SR |
50 | unsigned int num; |
51 | char buf[12]; | |
52 | unsigned int div; | |
7d9cde10 | 53 | |
7d9cde10 SR |
54 | while ((ch = *(fmt++))) { |
55 | if (ch != '%') { | |
56 | putc(ch); | |
57 | } else { | |
1fb67608 SG |
58 | bool lz = false; |
59 | int width = 0; | |
7d9cde10 SR |
60 | |
61 | ch = *(fmt++); | |
62 | if (ch == '0') { | |
63 | ch = *(fmt++); | |
64 | lz = 1; | |
65 | } | |
66 | ||
67 | if (ch >= '0' && ch <= '9') { | |
1fb67608 | 68 | width = 0; |
7d9cde10 | 69 | while (ch >= '0' && ch <= '9') { |
1fb67608 | 70 | width = (width * 10) + ch - '0'; |
7d9cde10 SR |
71 | ch = *fmt++; |
72 | } | |
73 | } | |
74 | bf = buf; | |
75 | p = bf; | |
76 | zs = 0; | |
77 | ||
78 | switch (ch) { | |
1fb67608 | 79 | case '\0': |
7d9cde10 SR |
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 | } | |
74b1320a SG |
88 | if (!num) { |
89 | out_dgt(0); | |
90 | } else { | |
91 | for (div = 1000000000; div; div /= 10) | |
92 | div_out(&num, div); | |
93 | } | |
7d9cde10 SR |
94 | break; |
95 | case 'x': | |
7d9cde10 | 96 | num = va_arg(va, unsigned int); |
74b1320a SG |
97 | if (!num) { |
98 | out_dgt(0); | |
99 | } else { | |
100 | for (div = 0x10000000; div; div /= 0x10) | |
101 | div_out(&num, div); | |
102 | } | |
7d9cde10 SR |
103 | break; |
104 | case 'c': | |
105 | out((char)(va_arg(va, int))); | |
106 | break; | |
107 | case 's': | |
108 | p = va_arg(va, char*); | |
109 | break; | |
110 | case '%': | |
111 | out('%'); | |
112 | default: | |
113 | break; | |
114 | } | |
115 | ||
116 | *bf = 0; | |
117 | bf = p; | |
1fb67608 SG |
118 | while (*bf++ && width > 0) |
119 | width--; | |
120 | while (width-- > 0) | |
7d9cde10 | 121 | putc(lz ? '0' : ' '); |
8e31681c SG |
122 | if (p) { |
123 | while ((ch = *p++)) | |
124 | putc(ch); | |
125 | } | |
7d9cde10 SR |
126 | } |
127 | } | |
128 | ||
129 | abort: | |
7d9cde10 SR |
130 | return 0; |
131 | } | |
962a43cc | 132 | |
da70b4d1 HG |
133 | int vprintf(const char *fmt, va_list va) |
134 | { | |
135 | return _vprintf(fmt, va, putc); | |
136 | } | |
137 | ||
962a43cc SS |
138 | int printf(const char *fmt, ...) |
139 | { | |
140 | va_list va; | |
141 | int ret; | |
142 | ||
143 | va_start(va, fmt); | |
5c411d88 SG |
144 | ret = _vprintf(fmt, va, putc); |
145 | va_end(va); | |
146 | ||
147 | return ret; | |
148 | } | |
149 | ||
150 | static void putc_outstr(char ch) | |
151 | { | |
152 | *outstr++ = ch; | |
153 | } | |
154 | ||
abeb272d | 155 | int sprintf(char *buf, const char *fmt, ...) |
5c411d88 SG |
156 | { |
157 | va_list va; | |
158 | int ret; | |
159 | ||
160 | va_start(va, fmt); | |
161 | outstr = buf; | |
162 | ret = _vprintf(fmt, va, putc_outstr); | |
962a43cc | 163 | va_end(va); |
5c411d88 | 164 | *outstr = '\0'; |
962a43cc SS |
165 | |
166 | return ret; | |
167 | } | |
abeb272d MV |
168 | |
169 | /* Note that size is ignored */ | |
170 | int snprintf(char *buf, size_t size, const char *fmt, ...) | |
171 | { | |
172 | va_list va; | |
173 | int ret; | |
174 | ||
175 | va_start(va, fmt); | |
3191d840 SG |
176 | outstr = buf; |
177 | ret = _vprintf(fmt, va, putc_outstr); | |
abeb272d | 178 | va_end(va); |
3191d840 | 179 | *outstr = '\0'; |
abeb272d MV |
180 | |
181 | return ret; | |
182 | } |