]> git.ipfire.org Git - people/ms/u-boot.git/blame - lib/tiny-printf.c
libfdt: fix fdt_stringlist_count()
[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
41static void div_out(struct printf_info *info, unsigned int *num,
42 unsigned int 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;
a5ecdd08
SR
59 unsigned int num;
60 char buf[12];
61 unsigned int 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;
7d9cde10
SR
69
70 ch = *(fmt++);
71 if (ch == '0') {
72 ch = *(fmt++);
73 lz = 1;
74 }
75
76 if (ch >= '0' && ch <= '9') {
1fb67608 77 width = 0;
7d9cde10 78 while (ch >= '0' && ch <= '9') {
1fb67608 79 width = (width * 10) + ch - '0';
7d9cde10
SR
80 ch = *fmt++;
81 }
82 }
45313e83
SG
83 info->bf = buf;
84 p = info->bf;
85 info->zs = 0;
7d9cde10
SR
86
87 switch (ch) {
1fb67608 88 case '\0':
7d9cde10
SR
89 goto abort;
90 case 'u':
91 case 'd':
92 num = va_arg(va, unsigned int);
93 if (ch == 'd' && (int)num < 0) {
94 num = -(int)num;
45313e83 95 out(info, '-');
7d9cde10 96 }
74b1320a 97 if (!num) {
45313e83 98 out_dgt(info, 0);
74b1320a
SG
99 } else {
100 for (div = 1000000000; div; div /= 10)
45313e83 101 div_out(info, &num, div);
74b1320a 102 }
7d9cde10
SR
103 break;
104 case 'x':
7d9cde10 105 num = va_arg(va, unsigned int);
74b1320a 106 if (!num) {
45313e83 107 out_dgt(info, 0);
74b1320a
SG
108 } else {
109 for (div = 0x10000000; div; div /= 0x10)
45313e83 110 div_out(info, &num, div);
74b1320a 111 }
7d9cde10
SR
112 break;
113 case 'c':
45313e83 114 out(info, (char)(va_arg(va, int)));
7d9cde10
SR
115 break;
116 case 's':
117 p = va_arg(va, char*);
118 break;
119 case '%':
45313e83 120 out(info, '%');
7d9cde10
SR
121 default:
122 break;
123 }
124
45313e83
SG
125 *info->bf = 0;
126 info->bf = p;
127 while (*info->bf++ && width > 0)
1fb67608
SG
128 width--;
129 while (width-- > 0)
45313e83 130 info->putc(info, lz ? '0' : ' ');
8e31681c
SG
131 if (p) {
132 while ((ch = *p++))
45313e83 133 info->putc(info, ch);
8e31681c 134 }
7d9cde10
SR
135 }
136 }
137
138abort:
7d9cde10
SR
139 return 0;
140}
962a43cc 141
da70b4d1
HG
142int vprintf(const char *fmt, va_list va)
143{
45313e83
SG
144 struct printf_info info;
145
146 info.putc = putc_normal;
147 return _vprintf(&info, fmt, va);
da70b4d1
HG
148}
149
962a43cc
SS
150int printf(const char *fmt, ...)
151{
45313e83
SG
152 struct printf_info info;
153
962a43cc
SS
154 va_list va;
155 int ret;
156
45313e83 157 info.putc = putc_normal;
962a43cc 158 va_start(va, fmt);
45313e83 159 ret = _vprintf(&info, fmt, va);
5c411d88
SG
160 va_end(va);
161
162 return ret;
163}
164
45313e83 165static void putc_outstr(struct printf_info *info, char ch)
5c411d88 166{
45313e83 167 *info->outstr++ = ch;
5c411d88
SG
168}
169
abeb272d 170int sprintf(char *buf, const char *fmt, ...)
5c411d88 171{
45313e83 172 struct printf_info info;
5c411d88
SG
173 va_list va;
174 int ret;
175
176 va_start(va, fmt);
45313e83
SG
177 info.outstr = buf;
178 info.putc = putc_outstr;
179 ret = _vprintf(&info, fmt, va);
962a43cc 180 va_end(va);
45313e83 181 *info.outstr = '\0';
962a43cc
SS
182
183 return ret;
184}
abeb272d
MV
185
186/* Note that size is ignored */
187int snprintf(char *buf, size_t size, const char *fmt, ...)
188{
45313e83 189 struct printf_info info;
abeb272d
MV
190 va_list va;
191 int ret;
192
193 va_start(va, fmt);
45313e83
SG
194 info.outstr = buf;
195 info.putc = putc_outstr;
196 ret = _vprintf(&info, fmt, va);
abeb272d 197 va_end(va);
45313e83 198 *info.outstr = '\0';
abeb272d
MV
199
200 return ret;
201}
e2409139
SG
202
203void __assert_fail(const char *assertion, const char *file, unsigned line,
204 const char *function)
205{
206 /* This will not return */
207 printf("%s:%u: %s: Assertion `%s' failed.", file, line, function,
208 assertion);
209 hang();
210}