Kernel part of bluetooth stack ported by Dmitry Komissaroff. Very much work
[dragonfly.git] / contrib / tcsh / tc.printf.c
bloba6f130afea344aa103b072cbe5b611420e8532a8
1 /* $Header: /src/pub/tcsh/tc.printf.c,v 3.23 2002/03/08 17:36:47 christos Exp $ */
2 /*
3 * tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
4 * through the putchar() routine. Feel free to use for
5 * anything... -- 7/17/87 Paul Placeway
6 */
7 /*-
8 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 #include "sh.h"
37 RCSID("$Id: tc.printf.c,v 3.23 2002/03/08 17:36:47 christos Exp $")
39 #ifdef lint
40 #undef va_arg
41 #define va_arg(a, b) (a ? (b) 0 : (b) 0)
42 #endif
44 #define INF 32766 /* should be bigger than any field to print */
46 static char buf[128];
48 static void xaddchar __P((int));
49 static void doprnt __P((void (*) __P((int)), const char *, va_list));
51 static void
52 doprnt(addchar, sfmt, ap)
53 void (*addchar) __P((int));
54 const char *sfmt;
55 va_list ap;
57 char *bp;
58 const char *f;
59 #ifdef SHORT_STRINGS
60 Char *Bp;
61 #endif /* SHORT_STRINGS */
62 #ifdef HAVE_QUAD
63 long long l;
64 unsigned long long u;
65 #else
66 long l;
67 unsigned long u;
68 #endif
69 int i;
70 int fmt;
71 unsigned char pad = ' ';
72 int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
73 int sign = 0;
74 int attributes = 0;
77 f = sfmt;
78 for (; *f; f++) {
79 if (*f != '%') { /* then just out the char */
80 (*addchar) ((int) (((unsigned char)*f) | attributes));
82 else {
83 f++; /* skip the % */
85 if (*f == '-') { /* minus: flush left */
86 flush_left = 1;
87 f++;
90 if (*f == '0' || *f == '.') {
91 /* padding with 0 rather than blank */
92 pad = '0';
93 f++;
95 if (*f == '*') { /* field width */
96 f_width = va_arg(ap, int);
97 f++;
99 else if (Isdigit((unsigned char) *f)) {
100 f_width = atoi(f);
101 while (Isdigit((unsigned char) *f))
102 f++; /* skip the digits */
105 if (*f == '.') { /* precision */
106 f++;
107 if (*f == '*') {
108 prec = va_arg(ap, int);
109 f++;
111 else if (Isdigit((unsigned char) *f)) {
112 prec = atoi((char *) f);
113 while (Isdigit((unsigned char) *f))
114 f++; /* skip the digits */
118 if (*f == '#') { /* alternate form */
119 hash = 1;
120 f++;
123 if (*f == 'l') { /* long format */
124 do_long++;
125 f++;
126 if (*f == 'l') {
127 do_long++;
128 f++;
132 fmt = (unsigned char) *f;
133 if (fmt != 'S' && fmt != 'Q' && Isupper(fmt)) {
134 do_long = 1;
135 fmt = Tolower(fmt);
137 bp = buf;
138 switch (fmt) { /* do the format */
139 case 'd':
140 switch (do_long) {
141 case 0:
142 l = (long) (va_arg(ap, int));
143 break;
144 case 1:
145 #ifndef HAVE_QUAD
146 default:
147 #endif
148 l = va_arg(ap, long);
149 break;
150 #ifdef HAVE_QUAD
151 default:
152 l = va_arg(ap, long long);
153 break;
154 #endif
157 if (l < 0) {
158 sign = 1;
159 l = -l;
161 do {
162 *bp++ = (char) (l % 10) + '0';
163 } while ((l /= 10) > 0);
164 if (sign)
165 *bp++ = '-';
166 f_width = f_width - (int) (bp - buf);
167 if (!flush_left)
168 while (f_width-- > 0)
169 (*addchar) ((int) (pad | attributes));
170 for (bp--; bp >= buf; bp--)
171 (*addchar) ((int) (((unsigned char) *bp) | attributes));
172 if (flush_left)
173 while (f_width-- > 0)
174 (*addchar) ((int) (' ' | attributes));
175 break;
177 case 'o':
178 case 'x':
179 case 'u':
180 switch (do_long) {
181 case 0:
182 u = (unsigned long) (va_arg(ap, unsigned int));
183 break;
184 case 1:
185 #ifndef HAVE_QUAD
186 default:
187 #endif
188 u = va_arg(ap, unsigned long);
189 break;
190 #ifdef HAVE_QUAD
191 default:
192 u = va_arg(ap, unsigned long long);
193 break;
194 #endif
196 if (fmt == 'u') { /* unsigned decimal */
197 do {
198 *bp++ = (char) (u % 10) + '0';
199 } while ((u /= 10) > 0);
201 else if (fmt == 'o') { /* octal */
202 do {
203 *bp++ = (char) (u % 8) + '0';
204 } while ((u /= 8) > 0);
205 if (hash)
206 *bp++ = '0';
208 else if (fmt == 'x') { /* hex */
209 do {
210 i = (int) (u % 16);
211 if (i < 10)
212 *bp++ = i + '0';
213 else
214 *bp++ = i - 10 + 'a';
215 } while ((u /= 16) > 0);
216 if (hash) {
217 *bp++ = 'x';
218 *bp++ = '0';
221 i = f_width - (int) (bp - buf);
222 if (!flush_left)
223 while (i-- > 0)
224 (*addchar) ((int) (pad | attributes));
225 for (bp--; bp >= buf; bp--)
226 (*addchar) ((int) (((unsigned char) *bp) | attributes));
227 if (flush_left)
228 while (i-- > 0)
229 (*addchar) ((int) (' ' | attributes));
230 break;
233 case 'c':
234 i = va_arg(ap, int);
235 (*addchar) ((int) (i | attributes));
236 break;
238 case 'S':
239 case 'Q':
240 #ifdef SHORT_STRINGS
241 Bp = va_arg(ap, Char *);
242 if (!Bp) {
243 bp = NULL;
244 goto lcase_s;
246 f_width = f_width - Strlen(Bp);
247 if (!flush_left)
248 while (f_width-- > 0)
249 (*addchar) ((int) (pad | attributes));
250 for (i = 0; *Bp && i < prec; i++) {
251 if (fmt == 'Q' && *Bp & QUOTE)
252 (*addchar) ((int) ('\\' | attributes));
253 (*addchar) ((int) ((*Bp & TRIM) | attributes));
254 Bp++;
256 if (flush_left)
257 while (f_width-- > 0)
258 (*addchar) ((int) (' ' | attributes));
259 break;
260 #endif /* SHORT_STRINGS */
262 case 's':
263 case 'q':
264 bp = va_arg(ap, char *);
265 lcase_s:
266 if (!bp)
267 bp = "(nil)";
268 f_width = f_width - strlen((char *) bp);
269 if (!flush_left)
270 while (f_width-- > 0)
271 (*addchar) ((int) (pad | attributes));
272 for (i = 0; *bp && i < prec; i++) {
273 if (fmt == 'q' && *bp & QUOTE)
274 (*addchar) ((int) ('\\' | attributes));
275 (*addchar) ((int) (((unsigned char) *bp & TRIM) |
276 attributes));
277 bp++;
279 if (flush_left)
280 while (f_width-- > 0)
281 (*addchar) ((int) (' ' | attributes));
282 break;
284 case 'a':
285 attributes = va_arg(ap, int);
286 break;
288 case '%':
289 (*addchar) ((int) ('%' | attributes));
290 break;
292 default:
293 break;
295 flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
296 sign = 0;
297 pad = ' ';
303 static char *xstring, *xestring;
304 static void
305 xaddchar(c)
306 int c;
308 if (xestring == xstring)
309 *xstring = '\0';
310 else
311 *xstring++ = (char) c;
315 pret_t
316 /*VARARGS*/
317 #ifdef FUNCPROTO
318 xsnprintf(char *str, size_t size, const char *fmt, ...)
319 #else
320 xsnprintf(va_alist)
321 va_dcl
322 #endif
324 va_list va;
325 #ifdef FUNCPROTO
326 va_start(va, fmt);
327 #else
328 char *str, *fmt;
329 size_t size;
331 va_start(va);
332 str = va_arg(va, char *);
333 size = va_arg(va, size_t);
334 fmt = va_arg(va, char *);
335 #endif
337 xstring = str;
338 xestring = str + size - 1;
339 doprnt(xaddchar, fmt, va);
340 va_end(va);
341 *xstring++ = '\0';
342 #ifdef PURIFY
343 return 1;
344 #endif
347 pret_t
348 /*VARARGS*/
349 #ifdef FUNCPROTO
350 xprintf(const char *fmt, ...)
351 #else
352 xprintf(va_alist)
353 va_dcl
354 #endif
356 va_list va;
357 #ifdef FUNCPROTO
358 va_start(va, fmt);
359 #else
360 char *fmt;
362 va_start(va);
363 fmt = va_arg(va, char *);
364 #endif
365 doprnt(xputchar, fmt, va);
366 va_end(va);
367 #ifdef PURIFY
368 return 1;
369 #endif
373 pret_t
374 xvprintf(fmt, va)
375 const char *fmt;
376 va_list va;
378 doprnt(xputchar, fmt, va);
379 #ifdef PURIFY
380 return 1;
381 #endif
384 pret_t
385 xvsnprintf(str, size, fmt, va)
386 char *str;
387 size_t size;
388 const char *fmt;
389 va_list va;
391 xstring = str;
392 xestring = str + size - 1;
393 doprnt(xaddchar, fmt, va);
394 *xstring++ = '\0';
395 #ifdef PURIFY
396 return 1;
397 #endif
402 #ifdef PURIFY
403 /* Purify uses (some of..) the following functions to output memory-use
404 * debugging info. Given all the messing with file descriptors that
405 * tcsh does, the easiest way I could think of to get it (Purify) to
406 * print anything was by replacing some standard functions with
407 * ones that do tcsh output directly - see dumb hook in doreaddirs()
408 * (sh.dir.c) -sg
410 #ifndef FILE
411 #define FILE int
412 #endif
413 int
414 #ifdef FUNCPROTO
415 fprintf(FILE *fp, const char* fmt, ...)
416 #else
417 fprintf(va_alist)
418 va_dcl
419 #endif
421 va_list va;
422 #ifdef FUNCPROTO
423 va_start(va, fmt);
424 #else
425 FILE *fp;
426 const char *fmt;
428 va_start(va);
429 fp = va_arg(va, FILE *);
430 fmt = va_arg(va, const char *);
431 #endif
432 doprnt(xputchar, fmt, va);
433 va_end(va);
434 return 1;
437 int
438 vfprintf(fp, fmt, va)
439 FILE *fp;
440 const char *fmt;
441 va_list va;
443 doprnt(xputchar, fmt, va);
444 return 1;
447 #endif /* PURIFY */