Add Cserve_Get_VM_Time
[qemu-palcode.git] / printf.c
blob469b82cd300dcd9a95d7395c931ce7df49a95c86
1 /* A reduced version of the printf function.
3 Copyright (C) 2011 Richard Henderson
5 This file is part of QEMU PALcode.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the text
15 of the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include <stdarg.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include "console.h"
26 static int print_buf_pad(char *buf, int buflen, char *p, int width, int pad)
28 int len = buf + buflen - p;
29 int r = 0;
31 if (width > len)
33 *--p = pad;
34 len++;
36 while (width > buflen)
38 crb_puts(0, p, 1);
39 width--;
40 r++;
42 while (width > len)
43 *--p = pad, len++;
46 crb_puts(0, p, len);
47 return r + len;
50 static int print_decimal(unsigned long val, int width, int pad)
52 char buf[32];
53 char *p = buf + sizeof(buf);
55 if (val == 0)
56 *--p = '0';
57 else
61 unsigned long d, r;
63 /* Compiling with -Os results in a call to the division routine.
64 Do what the compiler ought to have done. */
65 d = __builtin_alpha_umulh(val, 0xcccccccccccccccd);
66 d >>= 3;
67 r = val - (d * 10);
69 *--p = r + '0';
70 val = d;
72 while (val);
75 return print_buf_pad(buf, sizeof(buf), p, width, pad);
78 static int print_hex(unsigned long val, int width, char pad)
80 char buf[32];
81 char *p = buf + sizeof(buf);
83 if (val == 0)
84 *--p = '0';
85 else
89 int d = val % 16;
90 *--p = (d < 10 ? '0' : 'a' - 10) + d;
91 val /= 16;
93 while (val);
96 return print_buf_pad(buf, sizeof(buf), p, width, pad);
99 int printf(const char *fmt, ...)
101 va_list args;
102 unsigned long val;
103 int r = 0;
105 va_start(args, fmt);
107 for (; *fmt ; fmt++)
108 if (*fmt != '%')
110 crb_puts(0, fmt, 1);
111 r++;
113 else
115 const char *percent = fmt;
116 bool is_long = false;
117 char pad = ' ';
118 int width = 0;
120 restart:
121 switch (*++fmt)
123 case '%':
124 crb_puts(0, "%", 1);
125 r++;
126 break;
128 case 'l':
129 is_long = true;
130 goto restart;
132 case 'd':
133 if (is_long)
135 long d = va_arg (args, long);
136 if (d < 0)
138 crb_puts(0, "-", 1);
139 d = -d;
141 val = d;
143 else
145 int d = va_arg (args, int);
146 if (d < 0)
148 crb_puts(0, "-", 1);
149 d = -d;
150 r++;
152 val = d;
154 goto do_unsigned;
156 case 'u':
157 if (is_long)
158 val = va_arg (args, unsigned long);
159 else
160 val = va_arg (args, unsigned int);
162 do_unsigned:
163 r += print_decimal (val, width, pad);
164 break;
166 case 'x':
167 if (is_long)
168 val = va_arg (args, unsigned long);
169 else
170 val = va_arg (args, unsigned int);
171 r += print_hex (val, width, pad);
172 break;
174 case 's':
176 const char *s = va_arg (args, const char *);
177 int len = strlen(s);
178 crb_puts(0, s, len);
179 r += len;
181 break;
183 case '0':
184 pad = '0';
185 case '1' ... '9':
186 width = *fmt - '0';
187 while (fmt[1] >= '0' && fmt[1] <= '9')
188 width = width * 10 + *++fmt - '0';
189 goto restart;
191 default:
193 int len = fmt - percent;
194 crb_puts(0, percent, len);
195 r += len;
197 break;
201 va_end(args);
202 return r;