1/* 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 * 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. 16 * 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. 28 */ 29 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} 302