]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/printf.c
Clean up data types, some header cleanup, etc.
[proxmark3-svn] / armsrc / printf.c
CommitLineData
6f5cb60c 1/*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
35 */
36
f7e3ed82 37#include <stddef.h>
38#include <stdarg.h>
39#include "printf.h"
40#include "util.h"
41
42typedef uint32_t uintmax_t;
43typedef int32_t intmax_t;
44
6f5cb60c 45typedef unsigned char u_char;
46typedef unsigned int u_int;
47typedef unsigned long u_long;
48typedef unsigned short u_short;
49typedef unsigned long long u_quad_t;
50typedef long long quad_t;
f7e3ed82 51
52typedef int ssize_t;
53
6f5cb60c 54#define NBBY 8 /* number of bits in a byte */
f7e3ed82 55
6f5cb60c 56char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
57#define hex2ascii(hex) (hex2ascii_data[hex])
6f5cb60c 58#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
6f5cb60c 59
60/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
61#define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
62
63/*
64 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
65 * order; return an optional length and a pointer to the last character
66 * written in the buffer (i.e., the first character of the string).
67 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
68 */
69static char *
70ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
71{
72 char *p, c;
73
74 p = nbuf;
75 *p = '\0';
76 do {
77 c = hex2ascii(num % base);
78 *++p = upper ? toupper(c) : c;
79 } while (num /= base);
80 if (lenp)
81 *lenp = p - nbuf;
82 return (p);
83}
84
85/*
86 * Scaled down version of printf(3).
87 *
88 * Two additional formats:
89 *
90 * The format %b is supported to decode error registers.
91 * Its usage is:
92 *
93 * printf("reg=%b\n", regval, "*");
94 *
95 * where is the output base expressed as a control character, e.g.
96 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
97 * the first of which gives the bit number to be inspected (origin 1), and
98 * the next characters (up to a control character, i.e. a character <= 32),
99 * give the name of the register. Thus:
100 *
101 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
102 *
103 * would produce output:
104 *
105 * reg=3
106 *
107 * XXX: %D -- Hexdump, takes pointer and separator string:
108 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
109 * ("%*D", len, ptr, " " -> XX XX XX XX ...
110 */
111int
112kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
113{
114#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
115 char nbuf[MAXNBUF];
116 char *d;
117 const char *p, *percent, *q;
118 u_char *up;
119 int ch, n;
120 uintmax_t num;
121 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
122 int cflag, hflag, jflag, tflag, zflag;
123 int dwidth, upper;
124 char padc;
125 int stop = 0, retval = 0;
126
127 num = 0;
128 d = (char *) arg;
129
130 if (fmt == NULL)
131 fmt = "(fmt null)\n";
132
133 if (radix < 2 || radix > 36)
134 radix = 10;
135
136 for (;;) {
137 padc = ' ';
138 width = 0;
139 while ((ch = (u_char)*fmt++) != '%' || stop) {
140 PCHAR(ch);
141 if (ch == '\0')
142 return (retval);
143 }
144 percent = fmt - 1;
145 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
146 sign = 0; dot = 0; dwidth = 0; upper = 0;
147 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
148reswitch: switch (ch = (u_char)*fmt++) {
149 case '.':
150 dot = 1;
151 goto reswitch;
152 case '#':
153 sharpflag = 1;
154 goto reswitch;
155 case '+':
156 sign = 1;
157 goto reswitch;
158 case '-':
159 ladjust = 1;
160 goto reswitch;
161 case '%':
162 PCHAR(ch);
163 break;
164 case '*':
165 if (!dot) {
166 width = va_arg(ap, int);
167 if (width < 0) {
168 ladjust = !ladjust;
169 width = -width;
170 }
171 } else {
172 dwidth = va_arg(ap, int);
173 }
174 goto reswitch;
175 case '0':
176 if (!dot) {
177 padc = '0';
178 goto reswitch;
179 }
180 case '1': case '2': case '3': case '4':
181 case '5': case '6': case '7': case '8': case '9':
182 for (n = 0;; ++fmt) {
183 n = n * 10 + ch - '0';
184 ch = *fmt;
185 if (ch < '0' || ch > '9')
186 break;
187 }
188 if (dot)
189 dwidth = n;
190 else
191 width = n;
192 goto reswitch;
193 case 'b':
194 num = (u_int)va_arg(ap, int);
195 p = va_arg(ap, char *);
196 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
197 PCHAR(*q--);
198
199 if (num == 0)
200 break;
201
202 for (tmp = 0; *p;) {
203 n = *p++;
204 if (num & (1 << (n - 1))) {
205 PCHAR(tmp ? ',' : '<');
206 for (; (n = *p) > ' '; ++p)
207 PCHAR(n);
208 tmp = 1;
209 } else
210 for (; *p > ' '; ++p)
211 continue;
212 }
213 if (tmp)
214 PCHAR('>');
215 break;
216 case 'c':
217 PCHAR(va_arg(ap, int));
218 break;
219 case 'D':
220 up = va_arg(ap, u_char *);
221 p = va_arg(ap, char *);
222 if (!width)
223 width = 16;
224 while(width--) {
225 PCHAR(hex2ascii(*up >> 4));
226 PCHAR(hex2ascii(*up & 0x0f));
227 up++;
228 if (width)
229 for (q=p;*q;q++)
230 PCHAR(*q);
231 }
232 break;
233 case 'd':
234 case 'i':
235 base = 10;
236 sign = 1;
237 goto handle_sign;
238 case 'h':
239 if (hflag) {
240 hflag = 0;
241 cflag = 1;
242 } else
243 hflag = 1;
244 goto reswitch;
245 case 'j':
246 jflag = 1;
247 goto reswitch;
248 case 'l':
249 if (lflag) {
250 lflag = 0;
251 qflag = 1;
252 } else
253 lflag = 1;
254 goto reswitch;
255 case 'n':
256 if (jflag)
257 *(va_arg(ap, intmax_t *)) = retval;
258 else if (qflag)
259 *(va_arg(ap, quad_t *)) = retval;
260 else if (lflag)
261 *(va_arg(ap, long *)) = retval;
262 else if (zflag)
263 *(va_arg(ap, size_t *)) = retval;
264 else if (hflag)
265 *(va_arg(ap, short *)) = retval;
266 else if (cflag)
267 *(va_arg(ap, char *)) = retval;
268 else
269 *(va_arg(ap, int *)) = retval;
270 break;
271 case 'o':
272 base = 8;
273 goto handle_nosign;
274 case 'p':
275 base = 16;
276 sharpflag = (width == 0);
277 sign = 0;
278 num = (uintptr_t)va_arg(ap, void *);
279 goto number;
280 case 'q':
281 qflag = 1;
282 goto reswitch;
283 case 'r':
284 base = radix;
285 if (sign)
286 goto handle_sign;
287 goto handle_nosign;
288 case 's':
289 p = va_arg(ap, char *);
290 if (p == NULL)
291 p = "(null)";
292 if (!dot)
293 n = strlen (p);
294 else
295 for (n = 0; n < dwidth && p[n]; n++)
296 continue;
297
298 width -= n;
299
300 if (!ladjust && width > 0)
301 while (width--)
302 PCHAR(padc);
303 while (n--)
304 PCHAR(*p++);
305 if (ladjust && width > 0)
306 while (width--)
307 PCHAR(padc);
308 break;
309 case 't':
310 tflag = 1;
311 goto reswitch;
312 case 'u':
313 base = 10;
314 goto handle_nosign;
315 case 'X':
316 upper = 1;
317 case 'x':
318 base = 16;
319 goto handle_nosign;
320 case 'y':
321 base = 16;
322 sign = 1;
323 goto handle_sign;
324 case 'z':
325 zflag = 1;
326 goto reswitch;
327handle_nosign:
328 sign = 0;
329 if (jflag)
330 num = va_arg(ap, uintmax_t);
331 else if (qflag)
332 num = va_arg(ap, u_quad_t);
333 else if (tflag)
334 num = va_arg(ap, ptrdiff_t);
335 else if (lflag)
336 num = va_arg(ap, u_long);
337 else if (zflag)
338 num = va_arg(ap, size_t);
339 else if (hflag)
340 num = (u_short)va_arg(ap, int);
341 else if (cflag)
342 num = (u_char)va_arg(ap, int);
343 else
344 num = va_arg(ap, u_int);
345 goto number;
346handle_sign:
347 if (jflag)
348 num = va_arg(ap, intmax_t);
349 else if (qflag)
350 num = va_arg(ap, quad_t);
351 else if (tflag)
352 num = va_arg(ap, ptrdiff_t);
353 else if (lflag)
354 num = va_arg(ap, long);
355 else if (zflag)
356 num = va_arg(ap, ssize_t);
357 else if (hflag)
358 num = (short)va_arg(ap, int);
359 else if (cflag)
360 num = (char)va_arg(ap, int);
361 else
362 num = va_arg(ap, int);
363number:
364 if (sign && (intmax_t)num < 0) {
365 neg = 1;
366 num = -(intmax_t)num;
367 }
368 p = ksprintn(nbuf, num, base, &tmp, upper);
369 if (sharpflag && num != 0) {
370 if (base == 8)
371 tmp++;
372 else if (base == 16)
373 tmp += 2;
374 }
375 if (neg)
376 tmp++;
377
378 if (!ladjust && padc != '0' && width
379 && (width -= tmp) > 0)
380 while (width--)
381 PCHAR(padc);
382 if (neg)
383 PCHAR('-');
384 if (sharpflag && num != 0) {
385 if (base == 8) {
386 PCHAR('0');
387 } else if (base == 16) {
388 PCHAR('0');
389 PCHAR('x');
390 }
391 }
392 if (!ladjust && width && (width -= tmp) > 0)
393 while (width--)
394 PCHAR(padc);
395
396 while (*p)
397 PCHAR(*p--);
398
399 if (ladjust && width && (width -= tmp) > 0)
400 while (width--)
401 PCHAR(padc);
402
403 break;
404 default:
405 while (percent < fmt)
406 PCHAR(*percent++);
407 /*
408 * Since we ignore an formatting argument it is no
409 * longer safe to obey the remaining formatting
410 * arguments as the arguments will no longer match
411 * the format specs.
412 */
413 stop = 1;
414 break;
415 }
416 }
417 PCHAR(0);
418 return retval;
419#undef PCHAR
420}
421
f7e3ed82 422int vsprintf(char *dest, const char *fmt, va_list ap)
423{
424 return kvsprintf(fmt, dest, 10, ap);
425}
426
6f5cb60c 427int
428sprintf(char *dest, const char *fmt, ...)
429{
430 /* http://www.pagetable.com/?p=298 */
431 int retval;
432 va_list ap;
433
434 va_start(ap, fmt);
435 retval = kvsprintf(fmt, dest, 10, ap);
436 va_end(ap);
437 return retval;
438}
Impressum, Datenschutz