]> git.ipfire.org Git - people/ms/u-boot.git/blame - lib/tiny-printf.c
common: env_sf: Use CONFIG_SF_DEFAULT_xxx as the default value for CONFIG_ENV_SPI_xxx
[people/ms/u-boot.git] / lib / tiny-printf.c
CommitLineData
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
45313e83
SG
16struct printf_info {
17 char *bf; /* Digit buffer */
18 char zs; /* non-zero if a digit has been written */
19 char *outstr; /* Next output position for sprintf() */
7d9cde10 20
45313e83
SG
21 /* Output a character */
22 void (*putc)(struct printf_info *info, char ch);
23};
5c411d88 24
45313e83 25void putc_normal(struct printf_info *info, char ch)
7d9cde10 26{
45313e83 27 putc(ch);
7d9cde10
SR
28}
29
45313e83 30static void out(struct printf_info *info, char c)
7d9cde10 31{
45313e83 32 *info->bf++ = c;
7d9cde10
SR
33}
34
45313e83
SG
35static void out_dgt(struct printf_info *info, char dgt)
36{
37 out(info, dgt + (dgt < 10 ? '0' : 'a' - 10));
38 info->zs = 1;
39}
40
a28e1d98
AP
41static void div_out(struct printf_info *info, unsigned long *num,
42 unsigned long div)
7d9cde10
SR
43{
44 unsigned char dgt = 0;
45
a5ecdd08
SR
46 while (*num >= div) {
47 *num -= div;
7d9cde10
SR
48 dgt++;
49 }
50
45313e83
SG
51 if (info->zs || dgt > 0)
52 out_dgt(info, dgt);
7d9cde10
SR
53}
54
45313e83 55int _vprintf(struct printf_info *info, const char *fmt, va_list va)
7d9cde10 56{
7d9cde10
SR
57 char ch;
58 char *p;
a28e1d98 59 unsigned long num;
a5ecdd08 60 char buf[12];
a28e1d98 61 unsigned long div;
7d9cde10 62
7d9cde10
SR
63 while ((ch = *(fmt++))) {
64 if (ch != '%') {
45313e83 65 info->putc(info, ch);
7d9cde10 66 } else {
1fb67608
SG
67 bool lz = false;
68 int width = 0;
a28e1d98 69 bool islong = false;
7d9cde10
SR
70
71 ch = *(fmt++);
1c853629
AP
72 if (ch == '-')
73 ch = *(fmt++);
74
7d9cde10
SR
75 if (ch == '0') {
76 ch = *(fmt++);
77 lz = 1;
78 }
79
80 if (ch >= '0' && ch <= '9') {
1fb67608 81 width = 0;
7d9cde10 82 while (ch >= '0' && ch <= '9') {
1fb67608 83 width = (width * 10) + ch - '0';
7d9cde10
SR
84 ch = *fmt++;
85 }
86 }
a28e1d98
AP
87 if (ch == 'l') {
88 ch = *(fmt++);
89 islong = true;
90 }
91
45313e83
SG
92 info->bf = buf;
93 p = info->bf;
94 info->zs = 0;
7d9cde10
SR
95
96 switch (ch) {
1fb67608 97 case '\0':
7d9cde10
SR
98 goto abort;
99 case 'u':
100 case 'd':
a28e1d98
AP
101 div = 1000000000;
102 if (islong) {
103 num = va_arg(va, unsigned long);
104 if (sizeof(long) > 4)
105 div *= div * 10;
106 } else {
107 num = va_arg(va, unsigned int);
108 }
109
110 if (ch == 'd') {
111 if (islong && (long)num < 0) {
112 num = -(long)num;
113 out(info, '-');
114 } else if (!islong && (int)num < 0) {
115 num = -(int)num;
116 out(info, '-');
117 }
7d9cde10 118 }
74b1320a 119 if (!num) {
45313e83 120 out_dgt(info, 0);
74b1320a 121 } else {
a28e1d98 122 for (; div; div /= 10)
45313e83 123 div_out(info, &num, div);
74b1320a 124 }
7d9cde10
SR
125 break;
126 case 'x':
a28e1d98
AP
127 if (islong) {
128 num = va_arg(va, unsigned long);
129 div = 1UL << (sizeof(long) * 8 - 4);
130 } else {
131 num = va_arg(va, unsigned int);
132 div = 0x10000000;
133 }
74b1320a 134 if (!num) {
45313e83 135 out_dgt(info, 0);
74b1320a 136 } else {
a28e1d98 137 for (; div; div /= 0x10)
45313e83 138 div_out(info, &num, div);
74b1320a 139 }
7d9cde10
SR
140 break;
141 case 'c':
45313e83 142 out(info, (char)(va_arg(va, int)));
7d9cde10
SR
143 break;
144 case 's':
145 p = va_arg(va, char*);
146 break;
147 case '%':
45313e83 148 out(info, '%');
7d9cde10
SR
149 default:
150 break;
151 }
152
45313e83
SG
153 *info->bf = 0;
154 info->bf = p;
155 while (*info->bf++ && width > 0)
1fb67608
SG
156 width--;
157 while (width-- > 0)
45313e83 158 info->putc(info, lz ? '0' : ' ');
8e31681c
SG
159 if (p) {
160 while ((ch = *p++))
45313e83 161 info->putc(info, ch);
8e31681c 162 }
7d9cde10
SR
163 }
164 }
165
166abort:
7d9cde10
SR
167 return 0;
168}
962a43cc 169
da70b4d1
HG
170int vprintf(const char *fmt, va_list va)
171{
45313e83
SG
172 struct printf_info info;
173
174 info.putc = putc_normal;
175 return _vprintf(&info, fmt, va);
da70b4d1
HG
176}
177
962a43cc
SS
178int printf(const char *fmt, ...)
179{
45313e83
SG
180 struct printf_info info;
181
962a43cc
SS
182 va_list va;
183 int ret;
184
45313e83 185 info.putc = putc_normal;
962a43cc 186 va_start(va, fmt);
45313e83 187 ret = _vprintf(&info, fmt, va);
5c411d88
SG
188 va_end(va);
189
190 return ret;
191}
192
45313e83 193static void putc_outstr(struct printf_info *info, char ch)
5c411d88 194{
45313e83 195 *info->outstr++ = ch;
5c411d88
SG
196}
197
abeb272d 198int sprintf(char *buf, const char *fmt, ...)
5c411d88 199{
45313e83 200 struct printf_info info;
5c411d88
SG
201 va_list va;
202 int ret;
203
204 va_start(va, fmt);
45313e83
SG
205 info.outstr = buf;
206 info.putc = putc_outstr;
207 ret = _vprintf(&info, fmt, va);
962a43cc 208 va_end(va);
45313e83 209 *info.outstr = '\0';
962a43cc
SS
210
211 return ret;
212}
abeb272d
MV
213
214/* Note that size is ignored */
215int snprintf(char *buf, size_t size, const char *fmt, ...)
216{
45313e83 217 struct printf_info info;
abeb272d
MV
218 va_list va;
219 int ret;
220
221 va_start(va, fmt);
45313e83
SG
222 info.outstr = buf;
223 info.putc = putc_outstr;
224 ret = _vprintf(&info, fmt, va);
abeb272d 225 va_end(va);
45313e83 226 *info.outstr = '\0';
abeb272d
MV
227
228 return ret;
229}
e2409139
SG
230
231void __assert_fail(const char *assertion, const char *file, unsigned line,
232 const char *function)
233{
234 /* This will not return */
235 printf("%s:%u: %s: Assertion `%s' failed.", file, line, function,
236 assertion);
237 hang();
238}