]>
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; | |
17 | static char buf[12]; | |
18 | static unsigned int num; | |
19 | static char uc; | |
20 | static char zs; | |
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' : (uc ? 'A' : 'a') - 10)); | |
30 | zs = 1; | |
31 | } | |
32 | ||
33 | static void div_out(unsigned int div) | |
34 | { | |
35 | unsigned char dgt = 0; | |
36 | ||
37 | num &= 0xffff; /* just for testing the code with 32 bit ints */ | |
38 | while (num >= div) { | |
39 | num -= div; | |
40 | dgt++; | |
41 | } | |
42 | ||
43 | if (zs || dgt > 0) | |
44 | out_dgt(dgt); | |
45 | } | |
46 | ||
47 | int printf(const char *fmt, ...) | |
48 | { | |
49 | va_list va; | |
50 | char ch; | |
51 | char *p; | |
52 | ||
53 | va_start(va, fmt); | |
54 | ||
55 | while ((ch = *(fmt++))) { | |
56 | if (ch != '%') { | |
57 | putc(ch); | |
58 | } else { | |
59 | char lz = 0; | |
60 | char w = 0; | |
61 | ||
62 | ch = *(fmt++); | |
63 | if (ch == '0') { | |
64 | ch = *(fmt++); | |
65 | lz = 1; | |
66 | } | |
67 | ||
68 | if (ch >= '0' && ch <= '9') { | |
69 | w = 0; | |
70 | while (ch >= '0' && ch <= '9') { | |
71 | w = (((w << 2) + w) << 1) + ch - '0'; | |
72 | ch = *fmt++; | |
73 | } | |
74 | } | |
75 | bf = buf; | |
76 | p = bf; | |
77 | zs = 0; | |
78 | ||
79 | switch (ch) { | |
80 | case 0: | |
81 | goto abort; | |
82 | case 'u': | |
83 | case 'd': | |
84 | num = va_arg(va, unsigned int); | |
85 | if (ch == 'd' && (int)num < 0) { | |
86 | num = -(int)num; | |
87 | out('-'); | |
88 | } | |
89 | div_out(10000); | |
90 | div_out(1000); | |
91 | div_out(100); | |
92 | div_out(10); | |
93 | out_dgt(num); | |
94 | break; | |
95 | case 'x': | |
96 | case 'X': | |
97 | uc = ch == 'X'; | |
98 | num = va_arg(va, unsigned int); | |
99 | div_out(0x1000); | |
100 | div_out(0x100); | |
101 | div_out(0x10); | |
102 | out_dgt(num); | |
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++ && w > 0) | |
119 | w--; | |
120 | while (w-- > 0) | |
121 | putc(lz ? '0' : ' '); | |
122 | while ((ch = *p++)) | |
123 | putc(ch); | |
124 | } | |
125 | } | |
126 | ||
127 | abort: | |
128 | va_end(va); | |
129 | return 0; | |
130 | } |