]> git.ipfire.org Git - people/ms/u-boot.git/blob - lib/tiny-printf.c
Merge git://git.denx.de/u-boot-nand-flash
[people/ms/u-boot.git] / lib / tiny-printf.c
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 /* Current position in sprintf() output string */
20 static char *outstr;
21
22 static void out(char c)
23 {
24 *bf++ = c;
25 }
26
27 static void out_dgt(char dgt)
28 {
29 out(dgt + (dgt < 10 ? '0' : 'a' - 10));
30 zs = 1;
31 }
32
33 static void div_out(unsigned int *num, unsigned int div)
34 {
35 unsigned char dgt = 0;
36
37 while (*num >= div) {
38 *num -= div;
39 dgt++;
40 }
41
42 if (zs || dgt > 0)
43 out_dgt(dgt);
44 }
45
46 int _vprintf(const char *fmt, va_list va, void (*putc)(const char ch))
47 {
48 char ch;
49 char *p;
50 unsigned int num;
51 char buf[12];
52 unsigned int div;
53
54 while ((ch = *(fmt++))) {
55 if (ch != '%') {
56 putc(ch);
57 } else {
58 bool lz = false;
59 int width = 0;
60
61 ch = *(fmt++);
62 if (ch == '0') {
63 ch = *(fmt++);
64 lz = 1;
65 }
66
67 if (ch >= '0' && ch <= '9') {
68 width = 0;
69 while (ch >= '0' && ch <= '9') {
70 width = (width * 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 if (!num) {
89 out_dgt(0);
90 } else {
91 for (div = 1000000000; div; div /= 10)
92 div_out(&num, div);
93 }
94 break;
95 case 'x':
96 num = va_arg(va, unsigned int);
97 if (!num) {
98 out_dgt(0);
99 } else {
100 for (div = 0x10000000; div; div /= 0x10)
101 div_out(&num, div);
102 }
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;
118 while (*bf++ && width > 0)
119 width--;
120 while (width-- > 0)
121 putc(lz ? '0' : ' ');
122 if (p) {
123 while ((ch = *p++))
124 putc(ch);
125 }
126 }
127 }
128
129 abort:
130 return 0;
131 }
132
133 int printf(const char *fmt, ...)
134 {
135 va_list va;
136 int ret;
137
138 va_start(va, fmt);
139 ret = _vprintf(fmt, va, putc);
140 va_end(va);
141
142 return ret;
143 }
144
145 static void putc_outstr(char ch)
146 {
147 *outstr++ = ch;
148 }
149
150 int sprintf(char *buf, const char *fmt, ...)
151 {
152 va_list va;
153 int ret;
154
155 va_start(va, fmt);
156 outstr = buf;
157 ret = _vprintf(fmt, va, putc_outstr);
158 va_end(va);
159 *outstr = '\0';
160
161 return ret;
162 }
163
164 /* Note that size is ignored */
165 int snprintf(char *buf, size_t size, const char *fmt, ...)
166 {
167 va_list va;
168 int ret;
169
170 va_start(va, fmt);
171 outstr = buf;
172 ret = _vprintf(fmt, va, putc_outstr);
173 va_end(va);
174 *outstr = '\0';
175
176 return ret;
177 }