printf.c revision 7978:9700266d52f4
1/***************************************************************************** 2 3 Copyright � 1993, 1994 Digital Equipment Corporation, 4 Maynard, Massachusetts. 5 6 All Rights Reserved 7 8Permission to use, copy, modify, and distribute this software and its 9documentation for any purpose and without fee is hereby granted, provided 10that the copyright notice and this permission notice appear in all copies 11of software and supporting documentation, and that the name of Digital not 12be used in advertising or publicity pertaining to distribution of the software 13without specific, written prior permission. Digital grants this permission 14provided that you prominently mark, as not part of the original, any 15modifications made to this software or documentation. 16 17Digital Equipment Corporation disclaims all warranties and/or guarantees 18with regard to this software, including all implied warranties of fitness for 19a particular purpose and merchantability, and makes no representations 20regarding the use of, or the results of the use of, the software and 21documentation in terms of correctness, accuracy, reliability, currentness or 22otherwise; and you rely on the software, documentation and results solely at 23your own risk. 24 25******************************************************************************/ 26 27#ifndef LINT 28static char *rcsid = "$Id: printf.c,v 1.1.1.1 1997/10/30 23:27:12 verghese Exp $"; 29#endif 30 31/* 32 * $Log: printf.c,v $ 33 * Revision 1.1.1.1 1997/10/30 23:27:12 verghese 34 * current 10/29/97 35 * 36 * Revision 1.1 1995/06/26 21:09:35 berc 37 * Initial revision 38 * 39 * Revision 1.8 1994/10/06 20:29:08 fdh 40 * Corrected unsigned long declaration. 41 * 42 * Revision 1.7 1994/08/05 20:16:23 fdh 43 * Updated Copyright header and RCS $Id: identifier. 44 * 45 * Revision 1.6 1994/06/21 15:41:54 rusling 46 * fixedup WNT compiler warnings 47 * 48 * Revision 1.5 1994/06/17 19:35:37 fdh 49 * Clean-up... 50 * 51 * Revision 1.4 1994/01/19 10:40:08 rusling 52 * Ported to Alpha Windows NT. 53 * 54 * Revision 1.3 1993/11/02 21:57:45 fdh 55 * Fixed sign extension problem introduced in version 1.2 56 * 57 * Revision 1.2 1993/10/13 15:29:02 rusling 58 * Added floating point support in printf. This meant adding variable arguments to 59 * it and FormatItem() and including stdarg.h. 60 * 61 * Revision 1.1 1993/06/08 19:56:24 fdh 62 * Initial revision 63 * 64 */ 65 66 67 68/* printf.c 69 L. S. 70 Sun Feb 10 20:18:22 1985 71 */ 72 73#include "system.h" 74#include "lib.h" 75#include <stdarg.h> 76 77 78 79 80 81/* The string s is terminated by a '\0' */ 82void 83PutString(const char *s) 84{ 85 while (*s) PutChar(*s++); 86} 87 88/* print c count times */ 89void 90PutRepChar(char c, int count) 91{ 92 while (count--) PutChar(c); 93} 94 95/* put string reverse */ 96void 97PutStringReverse(const char *s, int index) 98{ 99 while ((index--) > 0) PutChar(s[index]); 100} 101 102/* prints value in radix, in a field width width, with fill 103 character fill 104 if radix is negative, print as signed quantity 105 if width is negative, left justify 106 if width is 0, use whatever is needed 107 if fill is 0, use ' ' 108 */ 109void 110PutNumber(sl value, int radix, int width, char fill) 111{ 112 char buffer[40]; 113 ui bufferindex = 0; 114 ul uvalue; 115 uw digit; 116 uw left = FALSE; 117 uw negative = FALSE; 118 119 if (fill == 0) fill = ' '; 120 121 if (width < 0) { 122 width = -width; 123 left = TRUE; 124 } 125 if (width < 0 || width > 80) width = 0; 126 127 if (radix < 0) { 128 radix = -radix; 129 if (value < 0) { 130 negative = TRUE; 131 value = -value; 132 } 133 } 134 switch (radix) { 135 case 8: 136 case 10: 137 case 16: break; 138 default: { 139 PutString("****"); 140 return; 141 } 142 } 143 uvalue = value; 144 do { 145 if (radix != 16) 146 { 147 digit = (uw)(uvalue % radix); 148 uvalue /= radix; 149 } 150 else 151 { 152 digit = (uw)(uvalue & 0xf); 153 uvalue = uvalue >> 4; 154 } 155 buffer[bufferindex] = digit + ((digit <= 9) ? '0' : ('A' - 10)); 156 bufferindex += 1; 157 } while (uvalue != 0); 158 /* fill # ' ' and negative cannot happen at once */ 159 if (negative) { 160 buffer[bufferindex] = '-'; 161 bufferindex += 1; 162 } 163 if ((ui)width <= bufferindex) PutStringReverse(buffer, bufferindex); 164 else { 165 width -= bufferindex; 166 if (!left) PutRepChar(fill, width); 167 PutStringReverse(buffer, bufferindex); 168 if (left) PutRepChar(fill, width); 169 } 170} 171 172ul power(long base, long n) 173{ 174 ul p; 175 176 for (p = 1; n > 0; --n) 177 p = p * base; 178 return p; 179} 180 181void putFloat(double a, int fieldwidth, char fill) 182{ 183 int i; 184 ul b; 185 186/* 187 * Put out everything before the decimal place. 188 */ 189 PutNumber(((ul) a), 10, fieldwidth, fill); 190/* 191 * Output the decimal place. 192 */ 193 PutChar('.' & 0x7f); 194/* 195 * Output the n digits after the decimal place. 196 */ 197 for (i = 1; i < 6; i++) { 198 b = (ul)(power(10, i) * (double)(a - (ul) a)); 199 PutChar((char)(b % 10) + '0'); 200 } 201} 202const char * 203FormatItem(const char *f, va_list *ap) 204{ 205 char c; 206 int fieldwidth = 0; 207 int leftjust = FALSE; 208 int radix = 0; 209 char fill = ' '; 210 if (*f == '0') fill = '0'; 211 while (c = *f++) { 212 if (c >= '0' && c <= '9') { 213 fieldwidth = (fieldwidth * 10) + (c - '0'); 214 } 215 else switch (c) { 216 case '\000': return(--f); 217 case '%': PutChar('%'); 218 return(f); 219 case '-': leftjust = TRUE; 220 break; 221 case 'c': { 222 char a = va_arg(*ap, char); 223 224 if (leftjust) PutChar(a & 0x7f); 225 if (fieldwidth > 0) PutRepChar(fill, fieldwidth - 1); 226 if (!leftjust) PutChar(a & 0x7f); 227 return(f); 228 } 229 case 's': { 230 const char *a = va_arg(*ap, const char *); 231 232 if (leftjust) PutString((const char *) a); 233 if (fieldwidth > strlen((const char *) a)) 234 PutRepChar(fill, fieldwidth - strlen((const char *)a)); 235 if (!leftjust) PutString((const char *) a); 236 return(f); 237 } 238 case 'd': radix = -10; 239 break; 240 case 'u': radix = 10; 241 break; 242 case 'x': radix = 16; 243 break; 244 case 'X': radix = 16; 245 break; 246 case 'o': radix = 8; 247 break; 248 case 'f': { 249 double a = va_arg(*ap, double); 250 251 putFloat(a, fieldwidth, fill); 252 return(f); 253 } 254 default: /* unknown switch! */ 255 radix = 3; 256 break; 257 } 258 if (radix) break; 259 } 260 if (leftjust) fieldwidth = -fieldwidth; 261 { 262 sl a = va_arg(*ap, sl); 263 PutNumber(a, radix, fieldwidth, fill); 264 } 265 return(f); 266} 267 268int 269printf(const char *f, ...) 270{ 271 va_list ap; 272 273 va_start(ap, f); 274 275 while (*f) { 276 if (*f == '%') f = FormatItem(f + 1, &ap); 277 else PutChar(*f++); 278 } 279 280 if (*(f-1)=='\n') { 281 /* add a line-feed (SimOS console output goes to shell */ 282 PutChar('\r'); 283 } 284 285 va_end(ap); /* clean up */ 286 return 0; 287} 288 289void 290panic(const char *f, ...) 291{ 292 va_list ap; 293 294 va_start(ap, f); 295 296 printf("CONSOLE PANIC (looping): "); 297 while (*f) { 298 if (*f == '%') f = FormatItem(f + 1, &ap); 299 else PutChar(*f++); 300 } 301 302 va_end(ap); /* clean up */ 303 while(1); 304} 305 306 307