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