printf.c revision 7996:f89e2d31764c
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