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