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