1 /* $Header: /src/pub/tcsh/tc.printf.c,v 3.23 2002/03/08 17:36:47 christos Exp $ */
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
8 * Copyright (c) 1980, 1991 The Regents of the University of California.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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
37 RCSID("$Id: tc.printf.c,v 3.23 2002/03/08 17:36:47 christos Exp $")
41 #define va_arg(a, b) (a ? (b) 0 : (b) 0)
44 #define INF 32766 /* should be bigger than any field to print */
48 static void xaddchar
__P((int));
49 static void doprnt
__P((void (*) __P((int)), const char *, va_list));
52 doprnt(addchar
, sfmt
, ap
)
53 void (*addchar
) __P((int));
61 #endif /* SHORT_STRINGS */
71 unsigned char pad
= ' ';
72 int flush_left
= 0, f_width
= 0, prec
= INF
, hash
= 0, do_long
= 0;
79 if (*f
!= '%') { /* then just out the char */
80 (*addchar
) ((int) (((unsigned char)*f
) | attributes
));
85 if (*f
== '-') { /* minus: flush left */
90 if (*f
== '0' || *f
== '.') {
91 /* padding with 0 rather than blank */
95 if (*f
== '*') { /* field width */
96 f_width
= va_arg(ap
, int);
99 else if (Isdigit((unsigned char) *f
)) {
101 while (Isdigit((unsigned char) *f
))
102 f
++; /* skip the digits */
105 if (*f
== '.') { /* precision */
108 prec
= va_arg(ap
, int);
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 */
123 if (*f
== 'l') { /* long format */
132 fmt
= (unsigned char) *f
;
133 if (fmt
!= 'S' && fmt
!= 'Q' && Isupper(fmt
)) {
138 switch (fmt
) { /* do the format */
142 l
= (long) (va_arg(ap
, int));
148 l
= va_arg(ap
, long);
152 l
= va_arg(ap
, long long);
162 *bp
++ = (char) (l
% 10) + '0';
163 } while ((l
/= 10) > 0);
166 f_width
= f_width
- (int) (bp
- buf
);
168 while (f_width
-- > 0)
169 (*addchar
) ((int) (pad
| attributes
));
170 for (bp
--; bp
>= buf
; bp
--)
171 (*addchar
) ((int) (((unsigned char) *bp
) | attributes
));
173 while (f_width
-- > 0)
174 (*addchar
) ((int) (' ' | attributes
));
182 u
= (unsigned long) (va_arg(ap
, unsigned int));
188 u
= va_arg(ap
, unsigned long);
192 u
= va_arg(ap
, unsigned long long);
196 if (fmt
== 'u') { /* unsigned decimal */
198 *bp
++ = (char) (u
% 10) + '0';
199 } while ((u
/= 10) > 0);
201 else if (fmt
== 'o') { /* octal */
203 *bp
++ = (char) (u
% 8) + '0';
204 } while ((u
/= 8) > 0);
208 else if (fmt
== 'x') { /* hex */
214 *bp
++ = i
- 10 + 'a';
215 } while ((u
/= 16) > 0);
221 i
= f_width
- (int) (bp
- buf
);
224 (*addchar
) ((int) (pad
| attributes
));
225 for (bp
--; bp
>= buf
; bp
--)
226 (*addchar
) ((int) (((unsigned char) *bp
) | attributes
));
229 (*addchar
) ((int) (' ' | attributes
));
235 (*addchar
) ((int) (i
| attributes
));
241 Bp
= va_arg(ap
, Char
*);
246 f_width
= f_width
- Strlen(Bp
);
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
));
257 while (f_width
-- > 0)
258 (*addchar
) ((int) (' ' | attributes
));
260 #endif /* SHORT_STRINGS */
264 bp
= va_arg(ap
, char *);
268 f_width
= f_width
- strlen((char *) bp
);
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
) |
280 while (f_width
-- > 0)
281 (*addchar
) ((int) (' ' | attributes
));
285 attributes
= va_arg(ap
, int);
289 (*addchar
) ((int) ('%' | attributes
));
295 flush_left
= 0, f_width
= 0, prec
= INF
, hash
= 0, do_long
= 0;
303 static char *xstring
, *xestring
;
308 if (xestring
== xstring
)
311 *xstring
++ = (char) c
;
318 xsnprintf(char *str
, size_t size
, const char *fmt
, ...)
332 str
= va_arg(va
, char *);
333 size
= va_arg(va
, size_t);
334 fmt
= va_arg(va
, char *);
338 xestring
= str
+ size
- 1;
339 doprnt(xaddchar
, fmt
, va
);
350 xprintf(const char *fmt
, ...)
363 fmt
= va_arg(va
, char *);
365 doprnt(xputchar
, fmt
, va
);
378 doprnt(xputchar
, fmt
, va
);
385 xvsnprintf(str
, size
, fmt
, va
)
392 xestring
= str
+ size
- 1;
393 doprnt(xaddchar
, fmt
, va
);
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()
415 fprintf(FILE *fp
, const char* fmt
, ...)
429 fp
= va_arg(va
, FILE *);
430 fmt
= va_arg(va
, const char *);
432 doprnt(xputchar
, fmt
, va
);
438 vfprintf(fp
, fmt
, va
)
443 doprnt(xputchar
, fmt
, va
);