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