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