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