]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/printf.c
Merge pull request #208 from marshmellow42/master
[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"
9ab7a6c7 41#include "string.h"
f7e3ed82 42
43typedef uint32_t uintmax_t;
44typedef int32_t intmax_t;
45
6f5cb60c 46typedef unsigned char u_char;
47typedef unsigned int u_int;
48typedef unsigned long u_long;
49typedef unsigned short u_short;
50typedef unsigned long long u_quad_t;
51typedef long long quad_t;
f7e3ed82 52
53typedef int ssize_t;
54
6f5cb60c 55#define NBBY 8 /* number of bits in a byte */
f7e3ed82 56
6f5cb60c 57char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
58#define hex2ascii(hex) (hex2ascii_data[hex])
6f5cb60c 59#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
6f5cb60c 60
61/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
62#define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
63
64/*
65 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
66 * order; return an optional length and a pointer to the last character
67 * written in the buffer (i.e., the first character of the string).
68 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
69 */
70static char *
71ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
72{
73 char *p, c;
74
75 p = nbuf;
76 *p = '\0';
77 do {
78 c = hex2ascii(num % base);
79 *++p = upper ? toupper(c) : c;
80 } while (num /= base);
81 if (lenp)
82 *lenp = p - nbuf;
83 return (p);
84}
85
86/*
87 * Scaled down version of printf(3).
88 *
89 * Two additional formats:
90 *
91 * The format %b is supported to decode error registers.
92 * Its usage is:
93 *
94 * printf("reg=%b\n", regval, "*");
95 *
96 * where is the output base expressed as a control character, e.g.
97 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
98 * the first of which gives the bit number to be inspected (origin 1), and
99 * the next characters (up to a control character, i.e. a character <= 32),
100 * give the name of the register. Thus:
101 *
102 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
103 *
104 * would produce output:
105 *
106 * reg=3
107 *
108 * XXX: %D -- Hexdump, takes pointer and separator string:
109 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
110 * ("%*D", len, ptr, " " -> XX XX XX XX ...
111 */
112int
113kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
114{
115#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
116 char nbuf[MAXNBUF];
117 char *d;
118 const char *p, *percent, *q;
119 u_char *up;
120 int ch, n;
121 uintmax_t num;
122 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
123 int cflag, hflag, jflag, tflag, zflag;
124 int dwidth, upper;
125 char padc;
126 int stop = 0, retval = 0;
127
128 num = 0;
129 d = (char *) arg;
130
131 if (fmt == NULL)
132 fmt = "(fmt null)\n";
133
134 if (radix < 2 || radix > 36)
135 radix = 10;
136
137 for (;;) {
138 padc = ' ';
139 width = 0;
140 while ((ch = (u_char)*fmt++) != '%' || stop) {
141 PCHAR(ch);
142 if (ch == '\0')
143 return (retval);
144 }
145 percent = fmt - 1;
146 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
147 sign = 0; dot = 0; dwidth = 0; upper = 0;
148 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
149reswitch: switch (ch = (u_char)*fmt++) {
150 case '.':
151 dot = 1;
152 goto reswitch;
153 case '#':
154 sharpflag = 1;
155 goto reswitch;
156 case '+':
157 sign = 1;
158 goto reswitch;
159 case '-':
160 ladjust = 1;
161 goto reswitch;
162 case '%':
163 PCHAR(ch);
164 break;
165 case '*':
166 if (!dot) {
167 width = va_arg(ap, int);
168 if (width < 0) {
169 ladjust = !ladjust;
170 width = -width;
171 }
172 } else {
173 dwidth = va_arg(ap, int);
174 }
175 goto reswitch;
176 case '0':
177 if (!dot) {
178 padc = '0';
179 goto reswitch;
180 }
181 case '1': case '2': case '3': case '4':
182 case '5': case '6': case '7': case '8': case '9':
183 for (n = 0;; ++fmt) {
184 n = n * 10 + ch - '0';
185 ch = *fmt;
186 if (ch < '0' || ch > '9')
187 break;
188 }
189 if (dot)
190 dwidth = n;
191 else
192 width = n;
193 goto reswitch;
194 case 'b':
195 num = (u_int)va_arg(ap, int);
196 p = va_arg(ap, char *);
197 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
198 PCHAR(*q--);
199
200 if (num == 0)
201 break;
202
203 for (tmp = 0; *p;) {
204 n = *p++;
205 if (num & (1 << (n - 1))) {
206 PCHAR(tmp ? ',' : '<');
207 for (; (n = *p) > ' '; ++p)
208 PCHAR(n);
209 tmp = 1;
210 } else
211 for (; *p > ' '; ++p)
212 continue;
213 }
214 if (tmp)
215 PCHAR('>');
216 break;
217 case 'c':
218 PCHAR(va_arg(ap, int));
219 break;
220 case 'D':
221 up = va_arg(ap, u_char *);
222 p = va_arg(ap, char *);
223 if (!width)
224 width = 16;
225 while(width--) {
226 PCHAR(hex2ascii(*up >> 4));
227 PCHAR(hex2ascii(*up & 0x0f));
228 up++;
229 if (width)
230 for (q=p;*q;q++)
231 PCHAR(*q);
232 }
233 break;
234 case 'd':
235 case 'i':
236 base = 10;
237 sign = 1;
238 goto handle_sign;
239 case 'h':
240 if (hflag) {
241 hflag = 0;
242 cflag = 1;
243 } else
244 hflag = 1;
245 goto reswitch;
246 case 'j':
247 jflag = 1;
248 goto reswitch;
249 case 'l':
250 if (lflag) {
251 lflag = 0;
252 qflag = 1;
253 } else
254 lflag = 1;
255 goto reswitch;
256 case 'n':
257 if (jflag)
258 *(va_arg(ap, intmax_t *)) = retval;
259 else if (qflag)
260 *(va_arg(ap, quad_t *)) = retval;
261 else if (lflag)
262 *(va_arg(ap, long *)) = retval;
263 else if (zflag)
264 *(va_arg(ap, size_t *)) = retval;
265 else if (hflag)
266 *(va_arg(ap, short *)) = retval;
267 else if (cflag)
268 *(va_arg(ap, char *)) = retval;
269 else
270 *(va_arg(ap, int *)) = retval;
271 break;
272 case 'o':
273 base = 8;
274 goto handle_nosign;
275 case 'p':
276 base = 16;
277 sharpflag = (width == 0);
278 sign = 0;
279 num = (uintptr_t)va_arg(ap, void *);
280 goto number;
281 case 'q':
282 qflag = 1;
283 goto reswitch;
284 case 'r':
285 base = radix;
286 if (sign)
287 goto handle_sign;
288 goto handle_nosign;
289 case 's':
290 p = va_arg(ap, char *);
291 if (p == NULL)
292 p = "(null)";
293 if (!dot)
294 n = strlen (p);
295 else
296 for (n = 0; n < dwidth && p[n]; n++)
297 continue;
298
299 width -= n;
300
301 if (!ladjust && width > 0)
302 while (width--)
303 PCHAR(padc);
304 while (n--)
305 PCHAR(*p++);
306 if (ladjust && width > 0)
307 while (width--)
308 PCHAR(padc);
309 break;
310 case 't':
311 tflag = 1;
312 goto reswitch;
313 case 'u':
314 base = 10;
315 goto handle_nosign;
316 case 'X':
317 upper = 1;
318 case 'x':
319 base = 16;
320 goto handle_nosign;
321 case 'y':
322 base = 16;
323 sign = 1;
324 goto handle_sign;
325 case 'z':
326 zflag = 1;
327 goto reswitch;
328handle_nosign:
329 sign = 0;
330 if (jflag)
331 num = va_arg(ap, uintmax_t);
332 else if (qflag)
333 num = va_arg(ap, u_quad_t);
334 else if (tflag)
335 num = va_arg(ap, ptrdiff_t);
336 else if (lflag)
337 num = va_arg(ap, u_long);
338 else if (zflag)
339 num = va_arg(ap, size_t);
340 else if (hflag)
341 num = (u_short)va_arg(ap, int);
342 else if (cflag)
343 num = (u_char)va_arg(ap, int);
344 else
345 num = va_arg(ap, u_int);
346 goto number;
347handle_sign:
348 if (jflag)
349 num = va_arg(ap, intmax_t);
350 else if (qflag)
351 num = va_arg(ap, quad_t);
352 else if (tflag)
353 num = va_arg(ap, ptrdiff_t);
354 else if (lflag)
355 num = va_arg(ap, long);
356 else if (zflag)
357 num = va_arg(ap, ssize_t);
358 else if (hflag)
359 num = (short)va_arg(ap, int);
360 else if (cflag)
361 num = (char)va_arg(ap, int);
362 else
363 num = va_arg(ap, int);
364number:
365 if (sign && (intmax_t)num < 0) {
366 neg = 1;
367 num = -(intmax_t)num;
368 }
369 p = ksprintn(nbuf, num, base, &tmp, upper);
370 if (sharpflag && num != 0) {
371 if (base == 8)
372 tmp++;
373 else if (base == 16)
374 tmp += 2;
375 }
376 if (neg)
377 tmp++;
378
379 if (!ladjust && padc != '0' && width
380 && (width -= tmp) > 0)
381 while (width--)
382 PCHAR(padc);
383 if (neg)
384 PCHAR('-');
385 if (sharpflag && num != 0) {
386 if (base == 8) {
387 PCHAR('0');
388 } else if (base == 16) {
389 PCHAR('0');
390 PCHAR('x');
391 }
392 }
393 if (!ladjust && width && (width -= tmp) > 0)
394 while (width--)
395 PCHAR(padc);
396
397 while (*p)
398 PCHAR(*p--);
399
400 if (ladjust && width && (width -= tmp) > 0)
401 while (width--)
402 PCHAR(padc);
403
404 break;
405 default:
406 while (percent < fmt)
407 PCHAR(*percent++);
408 /*
409 * Since we ignore an formatting argument it is no
410 * longer safe to obey the remaining formatting
411 * arguments as the arguments will no longer match
412 * the format specs.
413 */
414 stop = 1;
415 break;
416 }
417 }
418 PCHAR(0);
419 return retval;
420#undef PCHAR
421}
422
f7e3ed82 423int vsprintf(char *dest, const char *fmt, va_list ap)
424{
425 return kvsprintf(fmt, dest, 10, ap);
426}
427
6f5cb60c 428int
429sprintf(char *dest, const char *fmt, ...)
430{
431 /* http://www.pagetable.com/?p=298 */
432 int retval;
433 va_list ap;
434
435 va_start(ap, fmt);
436 retval = kvsprintf(fmt, dest, 10, ap);
437 va_end(ap);
438 return retval;
439}
Impressum, Datenschutz