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)
82void
83PutString(const char *s)
84{
85 while (*s) PutChar(*s++);
86}
87
88/* print c count times */
88void PutRepChar(char c, int count)
89void
90PutRepChar(char c, int count)
91{
92 while (count--) PutChar(c);
93}
94
95/* put string reverse */
94void PutStringReverse(char *s, int index)
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 */
106void PutNumber(sl value, int radix, int width, char fill)
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}
198char *FormatItem(char *f, va_list *ap)
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': {
225 char *a = va_arg(*ap, char *);
230 const char *a = va_arg(*ap, const char *);
231
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);
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
263void printf(char *f, ...)
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
282void panic(char *f, ...)
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