printf.c revision 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> 57#include <stdint.h> 58#include "m5op.h" 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 */ 325 m5_panic(); 326} 327