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