1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <printf.h>
19 #include <cpu/inc/cpuMath.h>
20
21
StrPrvPrintfEx_number(printf_write_c putc_,void * userData,uint64_t number,bool base10,bool zeroExtend,bool isSigned,uint32_t padToLength,bool caps,bool * bail)22 static uint32_t StrPrvPrintfEx_number(printf_write_c putc_, void* userData, uint64_t number, bool base10, bool zeroExtend, bool isSigned, uint32_t padToLength, bool caps, bool* bail)
23 {
24 char buf[64];
25 uint32_t idx = sizeof(buf) - 1;
26 uint32_t chr, i;
27 bool neg = false;
28 uint32_t numPrinted = 0;
29
30 *bail = false;
31
32 if (padToLength > sizeof(buf) - 1)
33 padToLength = sizeof(buf) - 1;
34
35 buf[idx--] = 0; //terminate
36
37 if (isSigned) {
38
39 if (((int64_t)number) < 0) {
40
41 neg = true;
42 number = -number;
43 }
44 }
45
46 do{
47 if (base10) {
48 uint64_t t = U64_DIV_BY_CONST_U16(number, 10);
49 chr = (number - t * 10) + '0';
50 number = t;
51 }
52 else {
53 chr = number & 0x0F;
54 number >>= 4;
55 chr = (chr >= 10) ? (chr + (caps ? 'A' : 'a') - 10) : (chr + '0');
56 }
57
58 buf[idx--] = chr;
59
60 numPrinted++;
61
62 } while (number);
63
64 if (neg) {
65
66 buf[idx--] = '-';
67 numPrinted++;
68 }
69
70 if (padToLength > numPrinted) {
71
72 padToLength -= numPrinted;
73 }
74 else {
75
76 padToLength = 0;
77 }
78
79 while (padToLength--) {
80
81 buf[idx--] = zeroExtend ? '0' : ' ';
82 numPrinted++;
83 }
84
85 idx++;
86
87
88 for(i = 0; i < numPrinted; i++) {
89
90 if (!putc_(userData,(buf + idx)[i])) {
91
92 *bail = true;
93 break;
94 }
95 }
96
97
98 return i;
99 }
100
StrVPrintf_StrLen_withMax(const char * s,uint32_t max)101 static uint32_t StrVPrintf_StrLen_withMax(const char* s, uint32_t max)
102 {
103 uint32_t len = 0;
104
105 while ((*s++) && (len < max)) len++;
106
107 return len;
108 }
109
StrVPrintf_StrLen(const char * s)110 static uint32_t StrVPrintf_StrLen(const char* s)
111 {
112 uint32_t len = 0;
113
114 while (*s++) len++;
115
116 return len;
117 }
118
prvGetChar(const char ** fmtP)119 static inline char prvGetChar(const char** fmtP)
120 {
121
122 return *(*fmtP)++;
123 }
124
cvprintf(printf_write_c putc_f,void * userData,const char * fmtStr,va_list vl)125 uint32_t cvprintf(printf_write_c putc_f, void* userData, const char* fmtStr, va_list vl)
126 {
127
128 char c, t;
129 uint32_t numPrinted = 0;
130 uint64_t val64;
131
132 #define putc_(_ud,_c) \
133 do { \
134 if (!putc_f(_ud,_c)) \
135 goto out; \
136 } while(0)
137
138 while ((c = prvGetChar(&fmtStr)) != 0) {
139
140 if (c == '\n') {
141
142 putc_(userData,c);
143 numPrinted++;
144 }
145 else if (c == '%') {
146
147 bool zeroExtend = false, useLong = false, useLongLong = false, useSizeT = false, bail = false, caps = false;
148 uint32_t padToLength = 0, len, i;
149 const char* str;
150
151 more_fmt:
152
153 c = prvGetChar(&fmtStr);
154
155 switch(c) {
156
157 case '%':
158
159 putc_(userData,c);
160 numPrinted++;
161 break;
162
163 case 'c':
164
165 t = va_arg(vl,unsigned int);
166 putc_(userData,t);
167 numPrinted++;
168 break;
169
170 case 's':
171
172 str = va_arg(vl,char*);
173 if (!str) str = "(null)";
174 if (padToLength)
175 len = StrVPrintf_StrLen_withMax(str,padToLength);
176 else
177 padToLength = len = StrVPrintf_StrLen(str);
178
179 if (len > padToLength)
180 len = padToLength;
181 else {
182 for(i = len; i < padToLength; i++)
183 putc_(userData, ' ');
184 }
185 numPrinted += padToLength;
186 for(i = 0; i < len; i++)
187 putc_(userData,*str++);
188
189 numPrinted += len;
190 break;
191
192 case '0':
193 case '.':
194
195 if (!zeroExtend && !padToLength) {
196
197 zeroExtend = true;
198 goto more_fmt;
199 }
200
201 case '1':
202 case '2':
203 case '3':
204 case '4':
205 case '5':
206 case '6':
207 case '7':
208 case '8':
209 case '9':
210
211 padToLength = (padToLength * 10) + c - '0';
212 goto more_fmt;
213
214 #define GET_UVAL64() \
215 useSizeT ? va_arg(vl, size_t) : \
216 useLongLong ? va_arg(vl, unsigned long long) : \
217 useLong ? va_arg(vl, unsigned long) : \
218 va_arg(vl, unsigned int)
219
220 #define GET_SVAL64() \
221 useSizeT ? va_arg(vl, size_t) : \
222 useLongLong ? va_arg(vl, signed long long) : \
223 useLong ? va_arg(vl, signed long) : \
224 va_arg(vl, signed int)
225
226 case 'u':
227
228 val64 = GET_UVAL64();
229 numPrinted += StrPrvPrintfEx_number(putc_f, userData, val64, true, zeroExtend,0,padToLength,0,&bail);
230 if (bail)
231 goto out;
232 break;
233
234 case 'd':
235 case 'i':
236
237 val64 = GET_SVAL64();
238 numPrinted += StrPrvPrintfEx_number(putc_f, userData, val64, true, zeroExtend, true, padToLength, false, &bail);
239 if (bail)
240 goto out;
241 break;
242
243 case 'X':
244 caps = true;
245
246 case 'x':
247
248 val64 = GET_UVAL64();
249 numPrinted += StrPrvPrintfEx_number(putc_f, userData, val64, false, zeroExtend, false, padToLength, caps, &bail);
250 if (bail)
251 goto out;
252 break;
253
254 case 'p':
255 putc_(userData,'0');
256 putc_(userData,'x');
257 numPrinted += 2;
258 val64 = (uintptr_t)va_arg(vl, const void*);
259 numPrinted += StrPrvPrintfEx_number(putc_f, userData, val64, false, zeroExtend, false, padToLength, caps, &bail);
260 if (bail)
261 goto out;
262 break;
263
264 #undef GET_UVAL64
265 #undef GET_SVAL64
266
267 case 'L':
268 case 'l':
269 if (useLong)
270 useLongLong = true;
271 useLong = true;
272 goto more_fmt;
273
274 case 'z':
275 useSizeT = true;
276 goto more_fmt;
277
278 default:
279
280 putc_(userData,c);
281 numPrinted++;
282 break;
283
284 }
285 }
286 else {
287
288 putc_(userData,c);
289 numPrinted++;
290 }
291 }
292
293 out:
294
295 return numPrinted;
296 }
297