/* * Copyright (c) 2003-2004 The Regents of The University of Michigan * Copyright (c) 1993 The Hewlett-Packard Development Company * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "m5op.h" /* The string s is terminated by a '\0' */ void PutString(const char *s) { while (*s) PutChar(*s++); } /* print c count times */ void PutRepChar(char c, int count) { while (count--) PutChar(c); } /* put string reverse */ void PutStringReverse(const char *s, int index) { while (index-- > 0) PutChar(s[index]); } /* * prints value in radix, in a field width width, with fill * character fill * if radix is negative, print as signed quantity * if width is negative, left justify * if width is 0, use whatever is needed * if fill is 0, use ' ' */ void PutNumber(long value, int radix, int width, char fill) { char buffer[40]; uint bufferindex = 0; ulong uvalue; ushort digit; ushort left = 0; ushort negative = 0; if (fill == 0) fill = ' '; if (width < 0) { width = -width; left = 1; } if (width < 0 || width > 80) width = 0; if (radix < 0) { radix = -radix; if (value < 0) { negative = 1; value = -value; } } switch (radix) { case 8: case 10: case 16: break; default: PutString("****"); return; } uvalue = value; do { if (radix != 16) { digit = (ushort)(uvalue % radix); uvalue /= radix; } else { digit = (ushort)(uvalue & 0xf); uvalue = uvalue >> 4; } buffer[bufferindex] = digit + ((digit <= 9) ? '0' : ('A' - 10)); bufferindex += 1; } while (uvalue != 0); /* fill # ' ' and negative cannot happen at once */ if (negative) { buffer[bufferindex] = '-'; bufferindex += 1; } if ((uint)width <= bufferindex) { PutStringReverse(buffer, bufferindex); } else { width -= bufferindex; if (!left) PutRepChar(fill, width); PutStringReverse(buffer, bufferindex); if (left) PutRepChar(fill, width); } } ulong power(long base, long n) { ulong p; for (p = 1; n > 0; --n) p = p * base; return p; } void putFloat(double a, int fieldwidth, char fill) { int i; ulong b; /* * Put out everything before the decimal place. */ PutNumber(((ulong) a), 10, fieldwidth, fill); /* * Output the decimal place. */ PutChar('.' & 0x7f); /* * Output the n digits after the decimal place. */ for (i = 1; i < 6; i++) { b = (ulong)(power(10, i) * (double)(a - (ulong) a)); PutChar((char)(b % 10) + '0'); } } const char * FormatItem(const char *f, va_list *ap) { char c; int fieldwidth = 0; int leftjust = 0; int radix = 0; char fill = ' '; if (*f == '0') fill = '0'; while (c = *f++) { if (c >= '0' && c <= '9') { fieldwidth = (fieldwidth * 10) + (c - '0'); } else { switch (c) { case '\000': return(--f); case '%': PutChar('%'); return(f); case '-': leftjust = 1; break; case 'c': { char a = (char)va_arg(*ap, int); if (leftjust) PutChar(a & 0x7f); if (fieldwidth > 0) PutRepChar(fill, fieldwidth - 1); if (!leftjust) PutChar(a & 0x7f); return(f); } case 's': { const char *a = va_arg(*ap, const char *); if (leftjust) PutString((const char *) a); if (fieldwidth > strlen((const char *) a)) PutRepChar(fill, fieldwidth - strlen((const char *)a)); if (!leftjust) PutString((const char *) a); return(f); } case 'd': radix = -10; break; case 'u': radix = 10; break; case 'x': radix = 16; break; case 'X': radix = 16; break; case 'o': radix = 8; break; case 'f': { double a = va_arg(*ap, double); putFloat(a, fieldwidth, fill); return(f); } default: /* unknown switch! */ radix = 3; break; } } if (radix) break; } if (leftjust) fieldwidth = -fieldwidth; long a = va_arg(*ap, long); PutNumber(a, radix, fieldwidth, fill); return(f); } int printf(const char *f, ...) { va_list ap; va_start(ap, f); while (*f) { if (*f == '%') f = FormatItem(f + 1, &ap); else PutChar(*f++); } if (*(f - 1) == '\n') { /* add a line-feed (SimOS console output goes to shell */ PutChar('\r'); } va_end(ap); /* clean up */ return 0; } void panic(const char *f, ...) { va_list ap; va_start(ap, f); printf("CONSOLE PANIC (looping): "); while (*f) { if (*f == '%') f = FormatItem(f + 1, &ap); else PutChar(*f++); } va_end(ap); /* clean up */ m5_panic(); }