386BSD 0.1 development
[unix-history] / usr / src / bin / csh / printf.c
CommitLineData
0452c863
WJ
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)printf.c 5.4 (Berkeley) 6/16/91";
36#endif /* not lint */
37
38/*
39 * tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
40 * through the putchar() routine. Feel free to use for
41 * anything... -- 7/17/87 Paul Placeway
42 */
43#include <strings.h>
44#include <stdlib.h>
45#if __STDC__
46# include <stdarg.h>
47#else
48# include <varargs.h>
49#endif
50#include "csh.h"
51#include "char.h"
52#include "extern.h"
53
54#ifdef lint
55#undef va_arg
56#define va_arg(a, b) (a ? (b) 0 : (b) 0)
57#endif
58
59#define INF 32766 /* should be bigger than any field to print */
60
61static unsigned char buf[128];
62
63static void
64doprnt(addchar, sfmt, ap)
65 void (*addchar) ();
66 char *sfmt;
67 va_list ap;
68{
69 register unsigned char *f, *bp;
70 register long l;
71 register unsigned long u;
72 register int i;
73 register int fmt;
74 register unsigned char pad = ' ';
75 int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
76 int sign = 0;
77
78 f = (unsigned char *) sfmt;
79 for (; *f; f++) {
80 if (*f != '%') { /* then just out the char */
81 (*addchar) ((int) (*f));
82 }
83 else {
84 f++; /* skip the % */
85
86 if (*f == '-') { /* minus: flush left */
87 flush_left = 1;
88 f++;
89 }
90
91 if (*f == '0' || *f == '.') {
92 /* padding with 0 rather than blank */
93 pad = '0';
94 f++;
95 }
96 if (*f == '*') { /* field width */
97 f_width = va_arg(ap, int);
98 f++;
99 }
100 else if (Isdigit(*f)) {
101 f_width = atoi((char *) f);
102 while (Isdigit(*f))
103 f++; /* skip the digits */
104 }
105
106 if (*f == '.') { /* precision */
107 f++;
108 if (*f == '*') {
109 prec = va_arg(ap, int);
110 f++;
111 }
112 else if (Isdigit(*f)) {
113 prec = atoi((char *) f);
114 while (Isdigit(*f))
115 f++; /* skip the digits */
116 }
117 }
118
119 if (*f == '#') { /* alternate form */
120 hash = 1;
121 f++;
122 }
123
124 if (*f == 'l') { /* long format */
125 do_long = 1;
126 f++;
127 }
128
129 fmt = *f;
130 if (Isupper(fmt)) {
131 do_long = 1;
132 fmt = Tolower(fmt);
133 }
134 bp = buf;
135 switch (fmt) { /* do the format */
136 case 'd':
137 if (do_long)
138 l = va_arg(ap, long);
139 else
140 l = (long) (va_arg(ap, int));
141 if (l < 0) {
142 sign = 1;
143 l = -l;
144 }
145 do {
146 *bp++ = l % 10 + '0';
147 } while ((l /= 10) > 0);
148 if (sign)
149 *bp++ = '-';
150 f_width = f_width - (bp - buf);
151 if (!flush_left)
152 while (f_width-- > 0)
153 (*addchar) ((int) (pad));
154 for (bp--; bp >= buf; bp--)
155 (*addchar) ((int) (*bp));
156 if (flush_left)
157 while (f_width-- > 0)
158 (*addchar) ((int) (' '));
159 break;
160
161 case 'o':
162 case 'x':
163 case 'u':
164 if (do_long)
165 u = va_arg(ap, unsigned long);
166 else
167 u = (unsigned long) (va_arg(ap, unsigned));
168 if (fmt == 'u') { /* unsigned decimal */
169 do {
170 *bp++ = u % 10 + '0';
171 } while ((u /= 10) > 0);
172 }
173 else if (fmt == 'o') { /* octal */
174 do {
175 *bp++ = u % 8 + '0';
176 } while ((u /= 8) > 0);
177 if (hash)
178 *bp++ = '0';
179 }
180 else if (fmt == 'x') { /* hex */
181 do {
182 i = u % 16;
183 if (i < 10)
184 *bp++ = i + '0';
185 else
186 *bp++ = i - 10 + 'a';
187 } while ((u /= 16) > 0);
188 if (hash) {
189 *bp++ = 'x';
190 *bp++ = '0';
191 }
192 }
193 i = f_width - (bp - buf);
194 if (!flush_left)
195 while (i-- > 0)
196 (*addchar) ((int) (pad));
197 for (bp--; bp >= buf; bp--)
198 (*addchar) ((int) (*bp));
199 if (flush_left)
200 while (i-- > 0)
201 (*addchar) ((int) (' '));
202 break;
203
204
205 case 'c':
206 i = va_arg(ap, int);
207 (*addchar) ((int) (i));
208 break;
209
210 case 's':
211 bp = va_arg(ap, unsigned char *);
212 if (!bp)
213 bp = (unsigned char *) "(nil)";
214 f_width = f_width - strlen((char *) bp);
215 if (!flush_left)
216 while (f_width-- > 0)
217 (*addchar) ((int) (pad));
218 for (i = 0; *bp && i < prec; i++) {
219 (*addchar) ((int) (*bp));
220 bp++;
221 }
222 if (flush_left)
223 while (f_width-- > 0)
224 (*addchar) ((int) (' '));
225
226 break;
227
228 case '%':
229 (*addchar) ((int) ('%'));
230 break;
231 }
232 flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
233 sign = 0;
234 pad = ' ';
235 }
236 }
237}
238
239
240static unsigned char *xstring;
241static void
242xaddchar(c)
243 int c;
244{
245 *xstring++ = c;
246}
247
248
249void
250#if __STDC__
251xsprintf(char *str, char *fmt, ...)
252#else
253xsprintf(str, fmt, va_alist)
254 char *str;
255 char *fmt;
256 va_dcl
257#endif
258{
259 va_list va;
260
261#if __STDC__
262 va_start(va, fmt);
263#else
264 va_start(va);
265#endif
266 xstring = (unsigned char *) str;
267 doprnt(xaddchar, fmt, va);
268 va_end(va);
269 *xstring++ = '\0';
270}
271
272
273void
274#if __STDC__
275xprintf(char *fmt, ...)
276#else
277xprintf(fmt, va_alist)
278 char *fmt;
279 va_dcl
280#endif
281{
282 va_list va;
283
284#if __STDC__
285 va_start(va, fmt);
286#else
287 va_start(va);
288#endif
289 doprnt(xputchar, fmt, va);
290 va_end(va);
291}
292
293
294void
295xvprintf(fmt, va)
296 char *fmt;
297 va_list va;
298{
299 doprnt(xputchar, fmt, va);
300}
301
302void
303xvsprintf(str, fmt, va)
304 char *str;
305 char *fmt;
306 va_list va;
307{
308 xstring = (unsigned char *) str;
309 doprnt(xaddchar, fmt, va);
310 *xstring++ = '\0';
311}