lib/tiny-printf.c: Add tiny printf function for space limited environments
[oweals/u-boot.git] / lib / tiny-printf.c
1 /*
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
16 static char *bf;
17 static char buf[12];
18 static unsigned int num;
19 static char uc;
20 static char zs;
21
22 static void out(char c)
23 {
24         *bf++ = c;
25 }
26
27 static void out_dgt(char dgt)
28 {
29         out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10));
30         zs = 1;
31 }
32
33 static void div_out(unsigned int div)
34 {
35         unsigned char dgt = 0;
36
37         num &= 0xffff; /* just for testing the code with 32 bit ints */
38         while (num >= div) {
39                 num -= div;
40                 dgt++;
41         }
42
43         if (zs || dgt > 0)
44                 out_dgt(dgt);
45 }
46
47 int printf(const char *fmt, ...)
48 {
49         va_list va;
50         char ch;
51         char *p;
52
53         va_start(va, fmt);
54
55         while ((ch = *(fmt++))) {
56                 if (ch != '%') {
57                         putc(ch);
58                 } else {
59                         char lz = 0;
60                         char w = 0;
61
62                         ch = *(fmt++);
63                         if (ch == '0') {
64                                 ch = *(fmt++);
65                                 lz = 1;
66                         }
67
68                         if (ch >= '0' && ch <= '9') {
69                                 w = 0;
70                                 while (ch >= '0' && ch <= '9') {
71                                         w = (((w << 2) + w) << 1) + ch - '0';
72                                         ch = *fmt++;
73                                 }
74                         }
75                         bf = buf;
76                         p = bf;
77                         zs = 0;
78
79                         switch (ch) {
80                         case 0:
81                                 goto abort;
82                         case 'u':
83                         case 'd':
84                                 num = va_arg(va, unsigned int);
85                                 if (ch == 'd' && (int)num < 0) {
86                                         num = -(int)num;
87                                         out('-');
88                                 }
89                                 div_out(10000);
90                                 div_out(1000);
91                                 div_out(100);
92                                 div_out(10);
93                                 out_dgt(num);
94                                 break;
95                         case 'x':
96                         case 'X':
97                                 uc = ch == 'X';
98                                 num = va_arg(va, unsigned int);
99                                 div_out(0x1000);
100                                 div_out(0x100);
101                                 div_out(0x10);
102                                 out_dgt(num);
103                                 break;
104                         case 'c':
105                                 out((char)(va_arg(va, int)));
106                                 break;
107                         case 's':
108                                 p = va_arg(va, char*);
109                                 break;
110                         case '%':
111                                 out('%');
112                         default:
113                                 break;
114                         }
115
116                         *bf = 0;
117                         bf = p;
118                         while (*bf++ && w > 0)
119                                 w--;
120                         while (w-- > 0)
121                                 putc(lz ? '0' : ' ');
122                         while ((ch = *p++))
123                                 putc(ch);
124                 }
125         }
126
127 abort:
128         va_end(va);
129         return 0;
130 }