printf.c revision 8026:680f5c014bed
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.
7 *
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.
26 */
27
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}
324