blob: d743a364e944497bd827af50e56625c0655cfcc4 [file] [log] [blame]
Stefan Roese363ab7b2015-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;
17static char buf[12];
18static unsigned int num;
19static char uc;
20static char zs;
21
22static void out(char c)
23{
24 *bf++ = c;
25}
26
27static void out_dgt(char dgt)
28{
29 out(dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10));
30 zs = 1;
31}
32
33static 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
47int 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
127abort:
128 va_end(va);
129 return 0;
130}