printf.c revision 8013:2dfcde2e9998
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 58/* The string s is terminated by a '\0' */ 59void 60PutString(const char *s) 61{ 62 while (*s) 63 PutChar(*s++); 64} 65 66/* print c count times */ 67void 68PutRepChar(char c, int count) 69{ 70 while (count--) 71 PutChar(c); 72} 73 74/* put string reverse */ 75void 76PutStringReverse(const char *s, int index) 77{ 78 while (index-- > 0) 79 PutChar(s[index]); 80} 81 82/* 83 * prints value in radix, in a field width width, with fill 84 * character fill 85 * if radix is negative, print as signed quantity 86 * if width is negative, left justify 87 * if width is 0, use whatever is needed 88 * if fill is 0, use ' ' 89 */ 90void 91PutNumber(long value, int radix, int width, char fill) 92{ 93 char buffer[40]; 94 uint bufferindex = 0; 95 ulong uvalue; 96 ushort digit; 97 ushort left = 0; 98 ushort negative = 0; 99 100 if (fill == 0) 101 fill = ' '; 102 103 if (width < 0) { 104 width = -width; 105 left = 1; 106 } 107 108 if (width < 0 || width > 80) 109 width = 0; 110 111 if (radix < 0) { 112 radix = -radix; 113 if (value < 0) { 114 negative = 1; 115 value = -value; 116 } 117 } 118 119 switch (radix) { 120 case 8: 121 case 10: 122 case 16: 123 break; 124 125 default: 126 PutString("****"); 127 return; 128 } 129 130 uvalue = value; 131 132 do { 133 if (radix != 16) { 134 digit = (ushort)(uvalue % radix); 135 uvalue /= radix; 136 } else { 137 digit = (ushort)(uvalue & 0xf); 138 uvalue = uvalue >> 4; 139 } 140 buffer[bufferindex] = digit + ((digit <= 9) ? '0' : ('A' - 10)); 141 bufferindex += 1; 142 } while (uvalue != 0); 143 144 /* fill # ' ' and negative cannot happen at once */ 145 if (negative) { 146 buffer[bufferindex] = '-'; 147 bufferindex += 1; 148 } 149 150 if ((uint)width <= bufferindex) { 151 PutStringReverse(buffer, bufferindex); 152 } else { 153 width -= bufferindex; 154 if (!left) 155 PutRepChar(fill, width); 156 PutStringReverse(buffer, bufferindex); 157 if (left) 158 PutRepChar(fill, width); 159 } 160} 161 162ulong 163power(long base, long n) 164{ 165 ulong p; 166 167 for (p = 1; n > 0; --n) 168 p = p * base; 169 return p; 170} 171 172void 173putFloat(double a, int fieldwidth, char fill) 174{ 175 int i; 176 ulong b; 177 178 /* 179 * Put out everything before the decimal place. 180 */ 181 PutNumber(((ulong) a), 10, fieldwidth, fill); 182 183 /* 184 * Output the decimal place. 185 */ 186 PutChar('.' & 0x7f); 187 188 /* 189 * Output the n digits after the decimal place. 190 */ 191 for (i = 1; i < 6; i++) { 192 b = (ulong)(power(10, i) * (double)(a - (ulong) a)); 193 PutChar((char)(b % 10) + '0'); 194 } 195} 196 197const char * 198FormatItem(const char *f, va_list *ap) 199{ 200 char c; 201 int fieldwidth = 0; 202 int leftjust = 0; 203 int radix = 0; 204 char fill = ' '; 205 206 if (*f == '0') 207 fill = '0'; 208 209 while (c = *f++) { 210 if (c >= '0' && c <= '9') { 211 fieldwidth = (fieldwidth * 10) + (c - '0'); 212 } else { 213 switch (c) { 214 case '\000': 215 return(--f); 216 case '%': 217 PutChar('%'); 218 return(f); 219 case '-': 220 leftjust = 1; 221 break; 222 case 'c': { 223 char a = (char)va_arg(*ap, int); 224 225 if (leftjust) 226 PutChar(a & 0x7f); 227 if (fieldwidth > 0) 228 PutRepChar(fill, fieldwidth - 1); 229 if (!leftjust) 230 PutChar(a & 0x7f); 231 return(f); 232 } 233 case 's': { 234 const char *a = va_arg(*ap, const char *); 235 236 if (leftjust) 237 PutString((const char *) a); 238 if (fieldwidth > strlen((const char *) a)) 239 PutRepChar(fill, fieldwidth - strlen((const char *)a)); 240 if (!leftjust) 241 PutString((const char *) a); 242 return(f); 243 } 244 case 'd': 245 radix = -10; 246 break; 247 case 'u': 248 radix = 10; 249 break; 250 case 'x': 251 radix = 16; 252 break; 253 case 'X': 254 radix = 16; 255 break; 256 case 'o': 257 radix = 8; 258 break; 259 case 'f': { 260 double a = va_arg(*ap, double); 261 262 putFloat(a, fieldwidth, fill); 263 return(f); 264 } 265 default: /* unknown switch! */ 266 radix = 3; 267 break; 268 } 269 } 270 271 if (radix) 272 break; 273 } 274 275 if (leftjust) 276 fieldwidth = -fieldwidth; 277 278 long a = va_arg(*ap, long); 279 PutNumber(a, radix, fieldwidth, fill); 280 281 return(f); 282} 283 284int 285printf(const char *f, ...) 286{ 287 va_list ap; 288 289 va_start(ap, f); 290 291 while (*f) { 292 if (*f == '%') 293 f = FormatItem(f + 1, &ap); 294 else 295 PutChar(*f++); 296 } 297 298 if (*(f - 1) == '\n') { 299 /* add a line-feed (SimOS console output goes to shell */ 300 PutChar('\r'); 301 } 302 303 va_end(ap); /* clean up */ 304 return 0; 305} 306 307void 308panic(const char *f, ...) 309{ 310 va_list ap; 311 312 va_start(ap, f); 313 314 printf("CONSOLE PANIC (looping): "); 315 while (*f) { 316 if (*f == '%') 317 f = FormatItem(f + 1, &ap); 318 else 319 PutChar(*f++); 320 } 321 322 va_end(ap); /* clean up */ 323 while(1); 324} 325