printf.c (8013:2dfcde2e9998) printf.c (8024:27ce7490bd3b)
1/*
2 * Copyright (c) 2003, 2004
3 * The Regents of The University of Michigan
4 * All Rights Reserved
5 *
6 * This code is part of the M5 simulator, developed by Nathan Binkert,
7 * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
8 * from Ron Dreslinski, Dave Greene, Lisa Hsu, Ali Saidi, and Andrew
9 * Schultz.
10 *
11 * Permission is granted to use, copy, create derivative works and
12 * redistribute this software and such derivative works for any purpose,
13 * so long as the copyright notice above, this grant of permission, and
14 * the disclaimer below appear in all copies made; and so long as the
15 * name of The University of Michigan is not used in any advertising or
16 * publicity pertaining to the use or distribution of this software
17 * without specific, written prior authorization.
18 *
19 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
20 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT
21 * WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR
22 * IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF
24 * THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
25 * INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
26 * DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION
27 * WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31/*
32 * Copyright 1993 Hewlett-Packard Development Company, L.P.
33 *
34 * Permission is hereby granted, free of charge, to any person
35 * obtaining a copy of this software and associated documentation
36 * files (the "Software"), to deal in the Software without
37 * restriction, including without limitation the rights to use, copy,
38 * modify, merge, publish, distribute, sublicense, and/or sell copies
39 * of the Software, and to permit persons to whom the Software is
40 * furnished to do so, subject to the following conditions:
41 *
42 * The above copyright notice and this permission notice shall be
43 * included in all copies or substantial portions of the Software.
44 *
45 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
49 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
50 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
51 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 * SOFTWARE.
53 */
54
55#include <sys/types.h>
56#include <stdarg.h>
1/*
2 * Copyright (c) 2003, 2004
3 * The Regents of The University of Michigan
4 * All Rights Reserved
5 *
6 * This code is part of the M5 simulator, developed by Nathan Binkert,
7 * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
8 * from Ron Dreslinski, Dave Greene, Lisa Hsu, Ali Saidi, and Andrew
9 * Schultz.
10 *
11 * Permission is granted to use, copy, create derivative works and
12 * redistribute this software and such derivative works for any purpose,
13 * so long as the copyright notice above, this grant of permission, and
14 * the disclaimer below appear in all copies made; and so long as the
15 * name of The University of Michigan is not used in any advertising or
16 * publicity pertaining to the use or distribution of this software
17 * without specific, written prior authorization.
18 *
19 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
20 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT
21 * WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR
22 * IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF
24 * THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
25 * INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
26 * DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION
27 * WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
29 */
30
31/*
32 * Copyright 1993 Hewlett-Packard Development Company, L.P.
33 *
34 * Permission is hereby granted, free of charge, to any person
35 * obtaining a copy of this software and associated documentation
36 * files (the "Software"), to deal in the Software without
37 * restriction, including without limitation the rights to use, copy,
38 * modify, merge, publish, distribute, sublicense, and/or sell copies
39 * of the Software, and to permit persons to whom the Software is
40 * furnished to do so, subject to the following conditions:
41 *
42 * The above copyright notice and this permission notice shall be
43 * included in all copies or substantial portions of the Software.
44 *
45 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
49 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
50 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
51 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 * SOFTWARE.
53 */
54
55#include <sys/types.h>
56#include <stdarg.h>
57#include <stdint.h>
58#include "m5op.h"
57
58/* The string s is terminated by a '\0' */
59void
60PutString(const char *s)
61{
62 while (*s)
63 PutChar(*s++);
64}
65
66/* print c count times */
67void
68PutRepChar(char c, int count)
69{
70 while (count--)
71 PutChar(c);
72}
73
74/* put string reverse */
75void
76PutStringReverse(const char *s, int index)
77{
78 while (index-- > 0)
79 PutChar(s[index]);
80}
81
82/*
83 * prints value in radix, in a field width width, with fill
84 * character fill
85 * if radix is negative, print as signed quantity
86 * if width is negative, left justify
87 * if width is 0, use whatever is needed
88 * if fill is 0, use ' '
89 */
90void
91PutNumber(long value, int radix, int width, char fill)
92{
93 char buffer[40];
94 uint bufferindex = 0;
95 ulong uvalue;
96 ushort digit;
97 ushort left = 0;
98 ushort negative = 0;
99
100 if (fill == 0)
101 fill = ' ';
102
103 if (width < 0) {
104 width = -width;
105 left = 1;
106 }
107
108 if (width < 0 || width > 80)
109 width = 0;
110
111 if (radix < 0) {
112 radix = -radix;
113 if (value < 0) {
114 negative = 1;
115 value = -value;
116 }
117 }
118
119 switch (radix) {
120 case 8:
121 case 10:
122 case 16:
123 break;
124
125 default:
126 PutString("****");
127 return;
128 }
129
130 uvalue = value;
131
132 do {
133 if (radix != 16) {
134 digit = (ushort)(uvalue % radix);
135 uvalue /= radix;
136 } else {
137 digit = (ushort)(uvalue & 0xf);
138 uvalue = uvalue >> 4;
139 }
140 buffer[bufferindex] = digit + ((digit <= 9) ? '0' : ('A' - 10));
141 bufferindex += 1;
142 } while (uvalue != 0);
143
144 /* fill # ' ' and negative cannot happen at once */
145 if (negative) {
146 buffer[bufferindex] = '-';
147 bufferindex += 1;
148 }
149
150 if ((uint)width <= bufferindex) {
151 PutStringReverse(buffer, bufferindex);
152 } else {
153 width -= bufferindex;
154 if (!left)
155 PutRepChar(fill, width);
156 PutStringReverse(buffer, bufferindex);
157 if (left)
158 PutRepChar(fill, width);
159 }
160}
161
162ulong
163power(long base, long n)
164{
165 ulong p;
166
167 for (p = 1; n > 0; --n)
168 p = p * base;
169 return p;
170}
171
172void
173putFloat(double a, int fieldwidth, char fill)
174{
175 int i;
176 ulong b;
177
178 /*
179 * Put out everything before the decimal place.
180 */
181 PutNumber(((ulong) a), 10, fieldwidth, fill);
182
183 /*
184 * Output the decimal place.
185 */
186 PutChar('.' & 0x7f);
187
188 /*
189 * Output the n digits after the decimal place.
190 */
191 for (i = 1; i < 6; i++) {
192 b = (ulong)(power(10, i) * (double)(a - (ulong) a));
193 PutChar((char)(b % 10) + '0');
194 }
195}
196
197const char *
198FormatItem(const char *f, va_list *ap)
199{
200 char c;
201 int fieldwidth = 0;
202 int leftjust = 0;
203 int radix = 0;
204 char fill = ' ';
205
206 if (*f == '0')
207 fill = '0';
208
209 while (c = *f++) {
210 if (c >= '0' && c <= '9') {
211 fieldwidth = (fieldwidth * 10) + (c - '0');
212 } else {
213 switch (c) {
214 case '\000':
215 return(--f);
216 case '%':
217 PutChar('%');
218 return(f);
219 case '-':
220 leftjust = 1;
221 break;
222 case 'c': {
223 char a = (char)va_arg(*ap, int);
224
225 if (leftjust)
226 PutChar(a & 0x7f);
227 if (fieldwidth > 0)
228 PutRepChar(fill, fieldwidth - 1);
229 if (!leftjust)
230 PutChar(a & 0x7f);
231 return(f);
232 }
233 case 's': {
234 const char *a = va_arg(*ap, const char *);
235
236 if (leftjust)
237 PutString((const char *) a);
238 if (fieldwidth > strlen((const char *) a))
239 PutRepChar(fill, fieldwidth - strlen((const char *)a));
240 if (!leftjust)
241 PutString((const char *) a);
242 return(f);
243 }
244 case 'd':
245 radix = -10;
246 break;
247 case 'u':
248 radix = 10;
249 break;
250 case 'x':
251 radix = 16;
252 break;
253 case 'X':
254 radix = 16;
255 break;
256 case 'o':
257 radix = 8;
258 break;
259 case 'f': {
260 double a = va_arg(*ap, double);
261
262 putFloat(a, fieldwidth, fill);
263 return(f);
264 }
265 default: /* unknown switch! */
266 radix = 3;
267 break;
268 }
269 }
270
271 if (radix)
272 break;
273 }
274
275 if (leftjust)
276 fieldwidth = -fieldwidth;
277
278 long a = va_arg(*ap, long);
279 PutNumber(a, radix, fieldwidth, fill);
280
281 return(f);
282}
283
284int
285printf(const char *f, ...)
286{
287 va_list ap;
288
289 va_start(ap, f);
290
291 while (*f) {
292 if (*f == '%')
293 f = FormatItem(f + 1, &ap);
294 else
295 PutChar(*f++);
296 }
297
298 if (*(f - 1) == '\n') {
299 /* add a line-feed (SimOS console output goes to shell */
300 PutChar('\r');
301 }
302
303 va_end(ap); /* clean up */
304 return 0;
305}
306
307void
308panic(const char *f, ...)
309{
310 va_list ap;
311
312 va_start(ap, f);
313
314 printf("CONSOLE PANIC (looping): ");
315 while (*f) {
316 if (*f == '%')
317 f = FormatItem(f + 1, &ap);
318 else
319 PutChar(*f++);
320 }
321
322 va_end(ap); /* clean up */
59
60/* The string s is terminated by a '\0' */
61void
62PutString(const char *s)
63{
64 while (*s)
65 PutChar(*s++);
66}
67
68/* print c count times */
69void
70PutRepChar(char c, int count)
71{
72 while (count--)
73 PutChar(c);
74}
75
76/* put string reverse */
77void
78PutStringReverse(const char *s, int index)
79{
80 while (index-- > 0)
81 PutChar(s[index]);
82}
83
84/*
85 * prints value in radix, in a field width width, with fill
86 * character fill
87 * if radix is negative, print as signed quantity
88 * if width is negative, left justify
89 * if width is 0, use whatever is needed
90 * if fill is 0, use ' '
91 */
92void
93PutNumber(long value, int radix, int width, char fill)
94{
95 char buffer[40];
96 uint bufferindex = 0;
97 ulong uvalue;
98 ushort digit;
99 ushort left = 0;
100 ushort negative = 0;
101
102 if (fill == 0)
103 fill = ' ';
104
105 if (width < 0) {
106 width = -width;
107 left = 1;
108 }
109
110 if (width < 0 || width > 80)
111 width = 0;
112
113 if (radix < 0) {
114 radix = -radix;
115 if (value < 0) {
116 negative = 1;
117 value = -value;
118 }
119 }
120
121 switch (radix) {
122 case 8:
123 case 10:
124 case 16:
125 break;
126
127 default:
128 PutString("****");
129 return;
130 }
131
132 uvalue = value;
133
134 do {
135 if (radix != 16) {
136 digit = (ushort)(uvalue % radix);
137 uvalue /= radix;
138 } else {
139 digit = (ushort)(uvalue & 0xf);
140 uvalue = uvalue >> 4;
141 }
142 buffer[bufferindex] = digit + ((digit <= 9) ? '0' : ('A' - 10));
143 bufferindex += 1;
144 } while (uvalue != 0);
145
146 /* fill # ' ' and negative cannot happen at once */
147 if (negative) {
148 buffer[bufferindex] = '-';
149 bufferindex += 1;
150 }
151
152 if ((uint)width <= bufferindex) {
153 PutStringReverse(buffer, bufferindex);
154 } else {
155 width -= bufferindex;
156 if (!left)
157 PutRepChar(fill, width);
158 PutStringReverse(buffer, bufferindex);
159 if (left)
160 PutRepChar(fill, width);
161 }
162}
163
164ulong
165power(long base, long n)
166{
167 ulong p;
168
169 for (p = 1; n > 0; --n)
170 p = p * base;
171 return p;
172}
173
174void
175putFloat(double a, int fieldwidth, char fill)
176{
177 int i;
178 ulong b;
179
180 /*
181 * Put out everything before the decimal place.
182 */
183 PutNumber(((ulong) a), 10, fieldwidth, fill);
184
185 /*
186 * Output the decimal place.
187 */
188 PutChar('.' & 0x7f);
189
190 /*
191 * Output the n digits after the decimal place.
192 */
193 for (i = 1; i < 6; i++) {
194 b = (ulong)(power(10, i) * (double)(a - (ulong) a));
195 PutChar((char)(b % 10) + '0');
196 }
197}
198
199const char *
200FormatItem(const char *f, va_list *ap)
201{
202 char c;
203 int fieldwidth = 0;
204 int leftjust = 0;
205 int radix = 0;
206 char fill = ' ';
207
208 if (*f == '0')
209 fill = '0';
210
211 while (c = *f++) {
212 if (c >= '0' && c <= '9') {
213 fieldwidth = (fieldwidth * 10) + (c - '0');
214 } else {
215 switch (c) {
216 case '\000':
217 return(--f);
218 case '%':
219 PutChar('%');
220 return(f);
221 case '-':
222 leftjust = 1;
223 break;
224 case 'c': {
225 char a = (char)va_arg(*ap, int);
226
227 if (leftjust)
228 PutChar(a & 0x7f);
229 if (fieldwidth > 0)
230 PutRepChar(fill, fieldwidth - 1);
231 if (!leftjust)
232 PutChar(a & 0x7f);
233 return(f);
234 }
235 case 's': {
236 const char *a = va_arg(*ap, const char *);
237
238 if (leftjust)
239 PutString((const char *) a);
240 if (fieldwidth > strlen((const char *) a))
241 PutRepChar(fill, fieldwidth - strlen((const char *)a));
242 if (!leftjust)
243 PutString((const char *) a);
244 return(f);
245 }
246 case 'd':
247 radix = -10;
248 break;
249 case 'u':
250 radix = 10;
251 break;
252 case 'x':
253 radix = 16;
254 break;
255 case 'X':
256 radix = 16;
257 break;
258 case 'o':
259 radix = 8;
260 break;
261 case 'f': {
262 double a = va_arg(*ap, double);
263
264 putFloat(a, fieldwidth, fill);
265 return(f);
266 }
267 default: /* unknown switch! */
268 radix = 3;
269 break;
270 }
271 }
272
273 if (radix)
274 break;
275 }
276
277 if (leftjust)
278 fieldwidth = -fieldwidth;
279
280 long a = va_arg(*ap, long);
281 PutNumber(a, radix, fieldwidth, fill);
282
283 return(f);
284}
285
286int
287printf(const char *f, ...)
288{
289 va_list ap;
290
291 va_start(ap, f);
292
293 while (*f) {
294 if (*f == '%')
295 f = FormatItem(f + 1, &ap);
296 else
297 PutChar(*f++);
298 }
299
300 if (*(f - 1) == '\n') {
301 /* add a line-feed (SimOS console output goes to shell */
302 PutChar('\r');
303 }
304
305 va_end(ap); /* clean up */
306 return 0;
307}
308
309void
310panic(const char *f, ...)
311{
312 va_list ap;
313
314 va_start(ap, f);
315
316 printf("CONSOLE PANIC (looping): ");
317 while (*f) {
318 if (*f == '%')
319 f = FormatItem(f + 1, &ap);
320 else
321 PutChar(*f++);
322 }
323
324 va_end(ap); /* clean up */
323 while(1);
325 m5_panic();
324}
326}