blob: 6766a8f1c8b648a201f430b15116dbf69c8a096e [file] [log] [blame]
Stefan Roese7d9cde12015-11-23 07:00:22 +01001/*
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
16static char *bf;
Stefan Roese7d9cde12015-11-23 07:00:22 +010017static char zs;
18
19static void out(char c)
20{
21 *bf++ = c;
22}
23
24static void out_dgt(char dgt)
25{
Stefan Roesea5ecdd02015-11-16 15:26:34 +010026 out(dgt + (dgt < 10 ? '0' : 'a' - 10));
Stefan Roese7d9cde12015-11-23 07:00:22 +010027 zs = 1;
28}
29
Stefan Roesea5ecdd02015-11-16 15:26:34 +010030static void div_out(unsigned int *num, unsigned int div)
Stefan Roese7d9cde12015-11-23 07:00:22 +010031{
32 unsigned char dgt = 0;
33
Stefan Roesea5ecdd02015-11-16 15:26:34 +010034 while (*num >= div) {
35 *num -= div;
Stefan Roese7d9cde12015-11-23 07:00:22 +010036 dgt++;
37 }
38
39 if (zs || dgt > 0)
40 out_dgt(dgt);
41}
42
43int printf(const char *fmt, ...)
44{
45 va_list va;
46 char ch;
47 char *p;
Stefan Roesea5ecdd02015-11-16 15:26:34 +010048 unsigned int num;
49 char buf[12];
50 unsigned int div;
Stefan Roese7d9cde12015-11-23 07:00:22 +010051
52 va_start(va, fmt);
53
54 while ((ch = *(fmt++))) {
55 if (ch != '%') {
56 putc(ch);
57 } else {
58 char lz = 0;
59 char w = 0;
60
61 ch = *(fmt++);
62 if (ch == '0') {
63 ch = *(fmt++);
64 lz = 1;
65 }
66
67 if (ch >= '0' && ch <= '9') {
68 w = 0;
69 while (ch >= '0' && ch <= '9') {
Stefan Roesea5ecdd02015-11-16 15:26:34 +010070 w = (w * 10) + ch - '0';
Stefan Roese7d9cde12015-11-23 07:00:22 +010071 ch = *fmt++;
72 }
73 }
74 bf = buf;
75 p = bf;
76 zs = 0;
77
78 switch (ch) {
79 case 0:
80 goto abort;
81 case 'u':
82 case 'd':
83 num = va_arg(va, unsigned int);
84 if (ch == 'd' && (int)num < 0) {
85 num = -(int)num;
86 out('-');
87 }
Stefan Roesea5ecdd02015-11-16 15:26:34 +010088 for (div = 1000000000; div; div /= 10)
89 div_out(&num, div);
Stefan Roese7d9cde12015-11-23 07:00:22 +010090 break;
91 case 'x':
Stefan Roese7d9cde12015-11-23 07:00:22 +010092 num = va_arg(va, unsigned int);
Stefan Roesea5ecdd02015-11-16 15:26:34 +010093 for (div = 0x10000000; div; div /= 0x10)
94 div_out(&num, div);
Stefan Roese7d9cde12015-11-23 07:00:22 +010095 break;
96 case 'c':
97 out((char)(va_arg(va, int)));
98 break;
99 case 's':
100 p = va_arg(va, char*);
101 break;
102 case '%':
103 out('%');
104 default:
105 break;
106 }
107
108 *bf = 0;
109 bf = p;
110 while (*bf++ && w > 0)
111 w--;
112 while (w-- > 0)
113 putc(lz ? '0' : ' ');
114 while ((ch = *p++))
115 putc(ch);
116 }
117 }
118
119abort:
120 va_end(va);
121 return 0;
122}