printf.c revision 8012:2f71125bf413
1/* 2Copyright 1993, 1994 Hewlett-Packard Development Company, L.P. 3 4Permission is hereby granted, free of charge, to any person obtaining a copy of 5this software and associated documentation files (the "Software"), to deal in 6the Software without restriction, including without limitation the rights to 7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8of the Software, and to permit persons to whom the Software is furnished to do 9so, subject to the following conditions: 10 11The above copyright notice and this permission notice shall be included in all 12copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20SOFTWARE. 21*/ 22 23#ifndef LINT 24static char *rcsid = "$Id: printf.c,v 1.1.1.1 1997/10/30 23:27:12 verghese Exp $"; 25#endif 26 27/* 28 * $Log: printf.c,v $ 29 * Revision 1.1.1.1 1997/10/30 23:27:12 verghese 30 * current 10/29/97 31 * 32 * Revision 1.1 1995/06/26 21:09:35 berc 33 * Initial revision 34 * 35 * Revision 1.8 1994/10/06 20:29:08 fdh 36 * Corrected unsigned long declaration. 37 * 38 * Revision 1.7 1994/08/05 20:16:23 fdh 39 * Updated Copyright header and RCS $Id: identifier. 40 * 41 * Revision 1.6 1994/06/21 15:41:54 rusling 42 * fixedup WNT compiler warnings 43 * 44 * Revision 1.5 1994/06/17 19:35:37 fdh 45 * Clean-up... 46 * 47 * Revision 1.4 1994/01/19 10:40:08 rusling 48 * Ported to Alpha Windows NT. 49 * 50 * Revision 1.3 1993/11/02 21:57:45 fdh 51 * Fixed sign extension problem introduced in version 1.2 52 * 53 * Revision 1.2 1993/10/13 15:29:02 rusling 54 * Added floating point support in printf. This meant adding variable arguments to 55 * it and FormatItem() and including stdarg.h. 56 * 57 * Revision 1.1 1993/06/08 19:56:24 fdh 58 * Initial revision 59 * 60 */ 61 62 63 64/* printf.c 65 L. S. 66 Sun Feb 10 20:18:22 1985 67 */ 68 69//#include "system.h" 70#include "lib.h" 71#include <stdarg.h> 72 73 74 75 76 77/* The string s is terminated by a '\0' */ 78void 79PutString(const char *s) 80{ 81 while (*s) PutChar(*s++); 82} 83 84/* print c count times */ 85void 86PutRepChar(char c, int count) 87{ 88 while (count--) PutChar(c); 89} 90 91/* put string reverse */ 92void 93PutStringReverse(const char *s, int index) 94{ 95 while ((index--) > 0) PutChar(s[index]); 96} 97 98/* prints value in radix, in a field width width, with fill 99 character fill 100 if radix is negative, print as signed quantity 101 if width is negative, left justify 102 if width is 0, use whatever is needed 103 if fill is 0, use ' ' 104 */ 105void 106PutNumber(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} 198const char * 199FormatItem(const char *f, va_list *ap) 200{ 201 char c; 202 int fieldwidth = 0; 203 int leftjust = FALSE; 204 int radix = 0; 205 char fill = ' '; 206 if (*f == '0') fill = '0'; 207 while (c = *f++) { 208 if (c >= '0' && c <= '9') { 209 fieldwidth = (fieldwidth * 10) + (c - '0'); 210 } 211 else switch (c) { 212 case '\000': return(--f); 213 case '%': PutChar('%'); 214 return(f); 215 case '-': leftjust = TRUE; 216 break; 217 case 'c': { 218 char a = va_arg(*ap, char *); 219 220 if (leftjust) PutChar(a & 0x7f); 221 if (fieldwidth > 0) PutRepChar(fill, fieldwidth - 1); 222 if (!leftjust) PutChar(a & 0x7f); 223 return(f); 224 } 225 case 's': { 226 const char *a = va_arg(*ap, const char *); 227 228 if (leftjust) PutString((const char *) a); 229 if (fieldwidth > strlen((const char *) a)) 230 PutRepChar(fill, fieldwidth - strlen((const char *)a)); 231 if (!leftjust) PutString((const char *) a); 232 return(f); 233 } 234 case 'd': radix = -10; 235 break; 236 case 'u': radix = 10; 237 break; 238 case 'x': radix = 16; 239 break; 240 case 'X': radix = 16; 241 break; 242 case 'o': radix = 8; 243 break; 244 case 'f': { 245 double a = va_arg(*ap, double); 246 247 putFloat(a, fieldwidth, fill); 248 return(f); 249 } 250 default: /* unknown switch! */ 251 radix = 3; 252 break; 253 } 254 if (radix) break; 255 } 256 if (leftjust) fieldwidth = -fieldwidth; 257 { 258 sl a = va_arg(*ap, sl); 259 PutNumber(a, radix, fieldwidth, fill); 260 } 261 return(f); 262} 263 264int 265printf(const char *f, ...) 266{ 267 va_list ap; 268 269 va_start(ap, f); 270 271 while (*f) { 272 if (*f == '%') f = FormatItem(f + 1, &ap); 273 else PutChar(*f++); 274 } 275 276 if (*(f-1)=='\n') { 277 /* add a line-feed (SimOS console output goes to shell */ 278 PutChar('\r'); 279 } 280 281 va_end(ap); /* clean up */ 282 return 0; 283} 284 285void 286panic(const char *f, ...) 287{ 288 va_list ap; 289 290 va_start(ap, f); 291 292 printf("CONSOLE PANIC (looping): "); 293 while (*f) { 294 if (*f == '%') f = FormatItem(f + 1, &ap); 295 else PutChar(*f++); 296 } 297 298 va_end(ap); /* clean up */ 299 while(1); 300} 301 302 303