xref: /freebsd/contrib/tcsh/tc.printf.c (revision 6560ac57ce879857203bc456cdc3849808dc0700)
1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien  * tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
3c80476e4SDavid E. O'Brien  *	       through the putchar() routine.  Feel free to use for
4c80476e4SDavid E. O'Brien  *	       anything...  -- 7/17/87 Paul Placeway
5c80476e4SDavid E. O'Brien  */
6c80476e4SDavid E. O'Brien /*-
7c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
8c80476e4SDavid E. O'Brien  * All rights reserved.
9c80476e4SDavid E. O'Brien  *
10c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
11c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
12c80476e4SDavid E. O'Brien  * are met:
13c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
14c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
15c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
16c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
17c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1829301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
19c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
20c80476e4SDavid E. O'Brien  *    without specific prior written permission.
21c80476e4SDavid E. O'Brien  *
22c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
33c80476e4SDavid E. O'Brien  */
34c80476e4SDavid E. O'Brien #include "sh.h"
35c80476e4SDavid E. O'Brien 
36c80476e4SDavid E. O'Brien #ifdef lint
37c80476e4SDavid E. O'Brien #undef va_arg
38c80476e4SDavid E. O'Brien #define va_arg(a, b) (a ? (b) 0 : (b) 0)
39c80476e4SDavid E. O'Brien #endif
40c80476e4SDavid E. O'Brien 
4145e5710bSMark Peek #define INF	INT_MAX		/* should be bigger than any field to print */
42c80476e4SDavid E. O'Brien 
4323338178SMark Peek static char snil[] = "(nil)";
44c80476e4SDavid E. O'Brien 
4545e5710bSMark Peek static	void	xaddchar	(int);
46*19d2e3deSDmitry Chagin static	int	doprnt		(void (*) (int), const char *, va_list);
47c80476e4SDavid E. O'Brien 
48*19d2e3deSDmitry Chagin static int
doprnt(void (* addchar)(int),const char * sfmt,va_list ap)4945e5710bSMark Peek doprnt(void (*addchar) (int), const char *sfmt, va_list ap)
50c80476e4SDavid E. O'Brien {
5129301572SMark Peek     char *bp;
5229301572SMark Peek     const char *f;
53c80476e4SDavid E. O'Brien #ifdef SHORT_STRINGS
5445e5710bSMark Peek     const Char *Bp;
55c80476e4SDavid E. O'Brien #endif /* SHORT_STRINGS */
5623338178SMark Peek #ifdef HAVE_LONG_LONG
5729301572SMark Peek     long long l;
5829301572SMark Peek     unsigned long long u;
5929301572SMark Peek #else
6029301572SMark Peek     long l;
6129301572SMark Peek     unsigned long u;
6229301572SMark Peek #endif
6345e5710bSMark Peek     char buf[(CHAR_BIT * sizeof (l) + 2) / 3 + 1]; /* Octal: 3 bits per char */
6429301572SMark Peek     int i;
6529301572SMark Peek     int fmt;
6629301572SMark Peek     unsigned char pad = ' ';
6745e5710bSMark Peek     int     flush_left = 0, f_width = 0, prec = INF, hash = 0;
68*19d2e3deSDmitry Chagin     int	    do_long = 0, do_size_t = 0, do_ptrdiff_t = 0;
69*19d2e3deSDmitry Chagin     int     sign = 0, count = 0;
70c80476e4SDavid E. O'Brien     int     attributes = 0;
71c80476e4SDavid E. O'Brien 
72c80476e4SDavid E. O'Brien 
73c80476e4SDavid E. O'Brien     f = sfmt;
74c80476e4SDavid E. O'Brien     for (; *f; f++) {
75c80476e4SDavid E. O'Brien 	if (*f != '%') {	/* then just out the char */
7645e5710bSMark Peek 	    (*addchar) (((unsigned char)*f) | attributes);
77*19d2e3deSDmitry Chagin 	    count++;
78c80476e4SDavid E. O'Brien 	}
79c80476e4SDavid E. O'Brien 	else {
80c80476e4SDavid E. O'Brien 	    f++;		/* skip the % */
81c80476e4SDavid E. O'Brien 
82c80476e4SDavid E. O'Brien 	    if (*f == '-') {	/* minus: flush left */
83c80476e4SDavid E. O'Brien 		flush_left = 1;
84c80476e4SDavid E. O'Brien 		f++;
85c80476e4SDavid E. O'Brien 	    }
86c80476e4SDavid E. O'Brien 
87c80476e4SDavid E. O'Brien 	    if (*f == '0' || *f == '.') {
88c80476e4SDavid E. O'Brien 		/* padding with 0 rather than blank */
89c80476e4SDavid E. O'Brien 		pad = '0';
90c80476e4SDavid E. O'Brien 		f++;
91c80476e4SDavid E. O'Brien 	    }
92c80476e4SDavid E. O'Brien 	    if (*f == '*') {	/* field width */
93c80476e4SDavid E. O'Brien 		f_width = va_arg(ap, int);
94c80476e4SDavid E. O'Brien 		f++;
95c80476e4SDavid E. O'Brien 	    }
9623338178SMark Peek 	    else if (isdigit((unsigned char) *f)) {
97c80476e4SDavid E. O'Brien 		f_width = atoi(f);
9823338178SMark Peek 		while (isdigit((unsigned char) *f))
99c80476e4SDavid E. O'Brien 		    f++;	/* skip the digits */
100c80476e4SDavid E. O'Brien 	    }
101c80476e4SDavid E. O'Brien 
102c80476e4SDavid E. O'Brien 	    if (*f == '.') {	/* precision */
103c80476e4SDavid E. O'Brien 		f++;
104c80476e4SDavid E. O'Brien 		if (*f == '*') {
105c80476e4SDavid E. O'Brien 		    prec = va_arg(ap, int);
106c80476e4SDavid E. O'Brien 		    f++;
107c80476e4SDavid E. O'Brien 		}
10823338178SMark Peek 		else if (isdigit((unsigned char) *f)) {
10923338178SMark Peek 		    prec = atoi(f);
11023338178SMark Peek 		    while (isdigit((unsigned char) *f))
111c80476e4SDavid E. O'Brien 			f++;	/* skip the digits */
112c80476e4SDavid E. O'Brien 		}
113c80476e4SDavid E. O'Brien 	    }
114c80476e4SDavid E. O'Brien 
115c80476e4SDavid E. O'Brien 	    if (*f == '#') {	/* alternate form */
116c80476e4SDavid E. O'Brien 		hash = 1;
117c80476e4SDavid E. O'Brien 		f++;
118c80476e4SDavid E. O'Brien 	    }
119c80476e4SDavid E. O'Brien 
120c80476e4SDavid E. O'Brien 	    if (*f == 'l') {	/* long format */
12129301572SMark Peek 		do_long++;
122c80476e4SDavid E. O'Brien 		f++;
12329301572SMark Peek 		if (*f == 'l') {
12429301572SMark Peek 		    do_long++;
12529301572SMark Peek 		    f++;
12629301572SMark Peek 		}
127c80476e4SDavid E. O'Brien 	    }
12845e5710bSMark Peek 	    if (*f == 'z') {	/* size_t format */
12945e5710bSMark Peek 		do_size_t++;
13045e5710bSMark Peek 		f++;
13145e5710bSMark Peek 	    }
132*19d2e3deSDmitry Chagin 	    if (*f == 't') {	/* ptrdiff_t format */
133*19d2e3deSDmitry Chagin 		do_ptrdiff_t++;
134*19d2e3deSDmitry Chagin 		f++;
135*19d2e3deSDmitry Chagin 	    }
136c80476e4SDavid E. O'Brien 
137c80476e4SDavid E. O'Brien 	    fmt = (unsigned char) *f;
13823338178SMark Peek 	    if (fmt != 'S' && fmt != 'Q' && isupper(fmt)) {
139c80476e4SDavid E. O'Brien 		do_long = 1;
14023338178SMark Peek 		fmt = tolower(fmt);
141c80476e4SDavid E. O'Brien 	    }
142c80476e4SDavid E. O'Brien 	    bp = buf;
143c80476e4SDavid E. O'Brien 	    switch (fmt) {	/* do the format */
144c80476e4SDavid E. O'Brien 	    case 'd':
14529301572SMark Peek 		switch (do_long) {
14629301572SMark Peek 		case 0:
14745e5710bSMark Peek 		    if (do_size_t)
14845e5710bSMark Peek 			l = (long) (va_arg(ap, size_t));
14945e5710bSMark Peek 		    else
150c80476e4SDavid E. O'Brien 			l = (long) (va_arg(ap, int));
15129301572SMark Peek 		    break;
15229301572SMark Peek 		case 1:
15323338178SMark Peek #ifndef HAVE_LONG_LONG
15429301572SMark Peek 		default:
15529301572SMark Peek #endif
15629301572SMark Peek 		    l = va_arg(ap, long);
15729301572SMark Peek 		    break;
15823338178SMark Peek #ifdef HAVE_LONG_LONG
15929301572SMark Peek 		default:
16029301572SMark Peek 		    l = va_arg(ap, long long);
16129301572SMark Peek 		    break;
16229301572SMark Peek #endif
16329301572SMark Peek 		}
16429301572SMark Peek 
165c80476e4SDavid E. O'Brien 		if (l < 0) {
166c80476e4SDavid E. O'Brien 		    sign = 1;
167c80476e4SDavid E. O'Brien 		    l = -l;
168c80476e4SDavid E. O'Brien 		}
169c80476e4SDavid E. O'Brien 		do {
170c80476e4SDavid E. O'Brien 		    *bp++ = (char) (l % 10) + '0';
171c80476e4SDavid E. O'Brien 		} while ((l /= 10) > 0);
172c80476e4SDavid E. O'Brien 		if (sign)
173c80476e4SDavid E. O'Brien 		    *bp++ = '-';
174c80476e4SDavid E. O'Brien 		f_width = f_width - (int) (bp - buf);
175c80476e4SDavid E. O'Brien 		if (!flush_left)
176*19d2e3deSDmitry Chagin 		    while (f_width-- > 0)  {
17745e5710bSMark Peek 			(*addchar) (pad | attributes);
178*19d2e3deSDmitry Chagin 			count++;
179*19d2e3deSDmitry Chagin 		    }
180*19d2e3deSDmitry Chagin 		for (bp--; bp >= buf; bp--)  {
18145e5710bSMark Peek 		    (*addchar) (((unsigned char) *bp) | attributes);
182*19d2e3deSDmitry Chagin 		    count++;
183*19d2e3deSDmitry Chagin 		}
184c80476e4SDavid E. O'Brien 		if (flush_left)
185*19d2e3deSDmitry Chagin 		    while (f_width-- > 0) {
18645e5710bSMark Peek 			(*addchar) (' ' | attributes);
187*19d2e3deSDmitry Chagin 			count++;
188*19d2e3deSDmitry Chagin 		    }
189c80476e4SDavid E. O'Brien 		break;
190c80476e4SDavid E. O'Brien 
191b2d5d167SMark Peek 	    case 'p':
192b2d5d167SMark Peek 		do_long = 1;
193b2d5d167SMark Peek 		hash = 1;
194b2d5d167SMark Peek 		fmt = 'x';
195b2d5d167SMark Peek 		/*FALLTHROUGH*/
196c80476e4SDavid E. O'Brien 	    case 'o':
197c80476e4SDavid E. O'Brien 	    case 'x':
198c80476e4SDavid E. O'Brien 	    case 'u':
19929301572SMark Peek 		switch (do_long) {
20029301572SMark Peek 		case 0:
20145e5710bSMark Peek 		    if (do_size_t)
20245e5710bSMark Peek 			u = va_arg(ap, size_t);
203*19d2e3deSDmitry Chagin 		    else if (do_ptrdiff_t)
204*19d2e3deSDmitry Chagin 			u = va_arg(ap, ptrdiff_t);
20545e5710bSMark Peek 		    else
20645e5710bSMark Peek 			u = va_arg(ap, unsigned int);
20729301572SMark Peek 		    break;
20829301572SMark Peek 		case 1:
20923338178SMark Peek #ifndef HAVE_LONG_LONG
21029301572SMark Peek 		default:
21129301572SMark Peek #endif
21229301572SMark Peek 		    u = va_arg(ap, unsigned long);
21329301572SMark Peek 		    break;
21423338178SMark Peek #ifdef HAVE_LONG_LONG
21529301572SMark Peek 		default:
21629301572SMark Peek 		    u = va_arg(ap, unsigned long long);
21729301572SMark Peek 		    break;
21829301572SMark Peek #endif
21929301572SMark Peek 		}
220c80476e4SDavid E. O'Brien 		if (fmt == 'u') {	/* unsigned decimal */
221c80476e4SDavid E. O'Brien 		    do {
222c80476e4SDavid E. O'Brien 			*bp++ = (char) (u % 10) + '0';
223c80476e4SDavid E. O'Brien 		    } while ((u /= 10) > 0);
224c80476e4SDavid E. O'Brien 		}
225c80476e4SDavid E. O'Brien 		else if (fmt == 'o') {	/* octal */
226c80476e4SDavid E. O'Brien 		    do {
227c80476e4SDavid E. O'Brien 			*bp++ = (char) (u % 8) + '0';
228c80476e4SDavid E. O'Brien 		    } while ((u /= 8) > 0);
229c80476e4SDavid E. O'Brien 		    if (hash)
230c80476e4SDavid E. O'Brien 			*bp++ = '0';
231c80476e4SDavid E. O'Brien 		}
232c80476e4SDavid E. O'Brien 		else if (fmt == 'x') {	/* hex */
233c80476e4SDavid E. O'Brien 		    do {
234c80476e4SDavid E. O'Brien 			i = (int) (u % 16);
235c80476e4SDavid E. O'Brien 			if (i < 10)
236c80476e4SDavid E. O'Brien 			    *bp++ = i + '0';
237c80476e4SDavid E. O'Brien 			else
238c80476e4SDavid E. O'Brien 			    *bp++ = i - 10 + 'a';
239c80476e4SDavid E. O'Brien 		    } while ((u /= 16) > 0);
240c80476e4SDavid E. O'Brien 		    if (hash) {
241c80476e4SDavid E. O'Brien 			*bp++ = 'x';
242c80476e4SDavid E. O'Brien 			*bp++ = '0';
243c80476e4SDavid E. O'Brien 		    }
244c80476e4SDavid E. O'Brien 		}
245c80476e4SDavid E. O'Brien 		i = f_width - (int) (bp - buf);
246c80476e4SDavid E. O'Brien 		if (!flush_left)
247*19d2e3deSDmitry Chagin 		    while (i-- > 0) {
24845e5710bSMark Peek 			(*addchar) (pad | attributes);
249*19d2e3deSDmitry Chagin 			count++;
250*19d2e3deSDmitry Chagin 		    }
251c80476e4SDavid E. O'Brien 		for (bp--; bp >= buf; bp--)
25245e5710bSMark Peek 		    (*addchar) (((unsigned char) *bp) | attributes);
253c80476e4SDavid E. O'Brien 		if (flush_left)
254*19d2e3deSDmitry Chagin 		    while (i-- > 0) {
25545e5710bSMark Peek 			(*addchar) (' ' | attributes);
256*19d2e3deSDmitry Chagin 			count++;
257*19d2e3deSDmitry Chagin 		    }
258c80476e4SDavid E. O'Brien 		break;
259c80476e4SDavid E. O'Brien 
260c80476e4SDavid E. O'Brien 
261c80476e4SDavid E. O'Brien 	    case 'c':
262c80476e4SDavid E. O'Brien 		i = va_arg(ap, int);
26345e5710bSMark Peek 		(*addchar) (i | attributes);
264*19d2e3deSDmitry Chagin 		count++;
265c80476e4SDavid E. O'Brien 		break;
266c80476e4SDavid E. O'Brien 
267c80476e4SDavid E. O'Brien 	    case 'S':
268c80476e4SDavid E. O'Brien 	    case 'Q':
2696767bd61SMark Peek #ifdef SHORT_STRINGS
270c80476e4SDavid E. O'Brien 		Bp = va_arg(ap, Char *);
271c80476e4SDavid E. O'Brien 		if (!Bp) {
272c80476e4SDavid E. O'Brien 		    bp = NULL;
273c80476e4SDavid E. O'Brien 		    goto lcase_s;
274c80476e4SDavid E. O'Brien 	        }
275c80476e4SDavid E. O'Brien 		f_width = f_width - Strlen(Bp);
276c80476e4SDavid E. O'Brien 		if (!flush_left)
277*19d2e3deSDmitry Chagin 		    while (f_width-- > 0) {
278c80476e4SDavid E. O'Brien 			(*addchar) ((int) (pad | attributes));
279*19d2e3deSDmitry Chagin 			count++;
280*19d2e3deSDmitry Chagin 		    }
281c80476e4SDavid E. O'Brien 		for (i = 0; *Bp && i < prec; i++) {
28223338178SMark Peek 		    char cbuf[MB_LEN_MAX];
28323338178SMark Peek 		    size_t pos, len;
28423338178SMark Peek 
285*19d2e3deSDmitry Chagin 		    if (fmt == 'Q' && *Bp & QUOTE) {
28645e5710bSMark Peek 			(*addchar) ('\\' | attributes);
287*19d2e3deSDmitry Chagin 			count++;
288*19d2e3deSDmitry Chagin 		    }
289*19d2e3deSDmitry Chagin 		    len = one_wctomb(cbuf, *Bp);
290*19d2e3deSDmitry Chagin 		    for (pos = 0; pos < len; pos++) {
29145e5710bSMark Peek 			(*addchar) ((unsigned char)cbuf[pos] | attributes
29245e5710bSMark Peek 				    | (*Bp & ATTRIBUTES));
293*19d2e3deSDmitry Chagin 			count++;
294*19d2e3deSDmitry Chagin 		    }
295c80476e4SDavid E. O'Brien 		    Bp++;
296c80476e4SDavid E. O'Brien 		}
297c80476e4SDavid E. O'Brien 		if (flush_left)
298*19d2e3deSDmitry Chagin 		    while (f_width-- > 0) {
29945e5710bSMark Peek 			(*addchar) (' ' | attributes);
300*19d2e3deSDmitry Chagin 			count++;
301*19d2e3deSDmitry Chagin 		    }
302c80476e4SDavid E. O'Brien 		break;
3036767bd61SMark Peek #endif /* SHORT_STRINGS */
304c80476e4SDavid E. O'Brien 
305c80476e4SDavid E. O'Brien 	    case 's':
306c80476e4SDavid E. O'Brien 	    case 'q':
307c80476e4SDavid E. O'Brien 		bp = va_arg(ap, char *);
308c80476e4SDavid E. O'Brien lcase_s:
309c80476e4SDavid E. O'Brien 		if (!bp)
31023338178SMark Peek 		    bp = snil;
31145e5710bSMark Peek 		f_width = f_width - strlen(bp);
312c80476e4SDavid E. O'Brien 		if (!flush_left)
313*19d2e3deSDmitry Chagin 		    while (f_width-- > 0) {
31445e5710bSMark Peek 			(*addchar) (pad | attributes);
315*19d2e3deSDmitry Chagin 			count++;
316*19d2e3deSDmitry Chagin 		    }
317c80476e4SDavid E. O'Brien 		for (i = 0; *bp && i < prec; i++) {
318*19d2e3deSDmitry Chagin 		    if (fmt == 'q' && *bp & QUOTE) {
31945e5710bSMark Peek 			(*addchar) ('\\' | attributes);
320*19d2e3deSDmitry Chagin 			count++;
321*19d2e3deSDmitry Chagin 		    }
32245e5710bSMark Peek 		    (*addchar) (((unsigned char) *bp & TRIM) | attributes);
323*19d2e3deSDmitry Chagin 		    count++;
324c80476e4SDavid E. O'Brien 		    bp++;
325c80476e4SDavid E. O'Brien 		}
326c80476e4SDavid E. O'Brien 		if (flush_left)
327*19d2e3deSDmitry Chagin 		    while (f_width-- > 0) {
32845e5710bSMark Peek 			(*addchar) (' ' | attributes);
329*19d2e3deSDmitry Chagin 			count++;
330*19d2e3deSDmitry Chagin 		    }
331c80476e4SDavid E. O'Brien 		break;
332c80476e4SDavid E. O'Brien 
333c80476e4SDavid E. O'Brien 	    case 'a':
334c80476e4SDavid E. O'Brien 		attributes = va_arg(ap, int);
335c80476e4SDavid E. O'Brien 		break;
336c80476e4SDavid E. O'Brien 
337c80476e4SDavid E. O'Brien 	    case '%':
33845e5710bSMark Peek 		(*addchar) ('%' | attributes);
339*19d2e3deSDmitry Chagin 		count++;
340c80476e4SDavid E. O'Brien 		break;
341c80476e4SDavid E. O'Brien 
342c80476e4SDavid E. O'Brien 	    default:
343c80476e4SDavid E. O'Brien 		break;
344c80476e4SDavid E. O'Brien 	    }
34545e5710bSMark Peek 	    flush_left = 0, f_width = 0, prec = INF, hash = 0;
346*19d2e3deSDmitry Chagin 	    do_ptrdiff_t = 0, do_size_t = 0, do_long = 0;
347c80476e4SDavid E. O'Brien 	    sign = 0;
348c80476e4SDavid E. O'Brien 	    pad = ' ';
349c80476e4SDavid E. O'Brien 	}
350c80476e4SDavid E. O'Brien     }
351*19d2e3deSDmitry Chagin     return count;
352c80476e4SDavid E. O'Brien }
353c80476e4SDavid E. O'Brien 
354c80476e4SDavid E. O'Brien 
355c80476e4SDavid E. O'Brien static char *xstring, *xestring;
356c80476e4SDavid E. O'Brien static void
xaddchar(int c)35745e5710bSMark Peek xaddchar(int c)
358c80476e4SDavid E. O'Brien {
359c80476e4SDavid E. O'Brien     if (xestring == xstring)
360c80476e4SDavid E. O'Brien 	*xstring = '\0';
361c80476e4SDavid E. O'Brien     else
362c80476e4SDavid E. O'Brien 	*xstring++ = (char) c;
363c80476e4SDavid E. O'Brien }
364c80476e4SDavid E. O'Brien 
365c80476e4SDavid E. O'Brien 
366*19d2e3deSDmitry Chagin int
367c80476e4SDavid E. O'Brien /*VARARGS*/
xsnprintf(char * str,size_t size,const char * fmt,...)368c80476e4SDavid E. O'Brien xsnprintf(char *str, size_t size, const char *fmt, ...)
369c80476e4SDavid E. O'Brien {
370*19d2e3deSDmitry Chagin     int count;
371c80476e4SDavid E. O'Brien     va_list va;
372c80476e4SDavid E. O'Brien     va_start(va, fmt);
373c80476e4SDavid E. O'Brien 
374c80476e4SDavid E. O'Brien     xstring = str;
375c80476e4SDavid E. O'Brien     xestring = str + size - 1;
376*19d2e3deSDmitry Chagin     count = doprnt(xaddchar, fmt, va);
377c80476e4SDavid E. O'Brien     va_end(va);
378c80476e4SDavid E. O'Brien     *xstring++ = '\0';
379*19d2e3deSDmitry Chagin     return count;
380c80476e4SDavid E. O'Brien }
381c80476e4SDavid E. O'Brien 
382*19d2e3deSDmitry Chagin int
383c80476e4SDavid E. O'Brien /*VARARGS*/
xprintf(const char * fmt,...)384c80476e4SDavid E. O'Brien xprintf(const char *fmt, ...)
385c80476e4SDavid E. O'Brien {
386*19d2e3deSDmitry Chagin     int count;
387c80476e4SDavid E. O'Brien     va_list va;
388c80476e4SDavid E. O'Brien     va_start(va, fmt);
389*19d2e3deSDmitry Chagin     count = doprnt(xputchar, fmt, va);
390c80476e4SDavid E. O'Brien     va_end(va);
391*19d2e3deSDmitry Chagin     return count;
392c80476e4SDavid E. O'Brien }
393c80476e4SDavid E. O'Brien 
394*19d2e3deSDmitry Chagin int
xvprintf(const char * fmt,va_list va)39545e5710bSMark Peek xvprintf(const char *fmt, va_list va)
396c80476e4SDavid E. O'Brien {
397*19d2e3deSDmitry Chagin     return doprnt(xputchar, fmt, va);
398c80476e4SDavid E. O'Brien }
399c80476e4SDavid E. O'Brien 
400*19d2e3deSDmitry Chagin int
xvsnprintf(char * str,size_t size,const char * fmt,va_list va)40145e5710bSMark Peek xvsnprintf(char *str, size_t size, const char *fmt, va_list va)
402c80476e4SDavid E. O'Brien {
403*19d2e3deSDmitry Chagin     int count;
404c80476e4SDavid E. O'Brien     xstring = str;
405c80476e4SDavid E. O'Brien     xestring = str + size - 1;
406*19d2e3deSDmitry Chagin     count = doprnt(xaddchar, fmt, va);
407c80476e4SDavid E. O'Brien     *xstring++ = '\0';
408*19d2e3deSDmitry Chagin     return count;
409c80476e4SDavid E. O'Brien }
410c80476e4SDavid E. O'Brien 
41145e5710bSMark Peek char *
xvasprintf(const char * fmt,va_list va)41245e5710bSMark Peek xvasprintf(const char *fmt, va_list va)
41345e5710bSMark Peek {
41445e5710bSMark Peek     size_t size;
41545e5710bSMark Peek     char *buf;
41645e5710bSMark Peek 
41745e5710bSMark Peek     buf = NULL;
41845e5710bSMark Peek     size = 2048; /* Arbitrary */
41945e5710bSMark Peek     for (;;) {
42045e5710bSMark Peek 	va_list copy;
42145e5710bSMark Peek 
42245e5710bSMark Peek 	buf = xrealloc(buf, size);
42345e5710bSMark Peek 	xstring = buf;
42445e5710bSMark Peek 	xestring = buf + size - 1;
42545e5710bSMark Peek 	va_copy(copy, va);
42645e5710bSMark Peek 	doprnt(xaddchar, fmt, copy);
42745e5710bSMark Peek 	va_end(copy);
42845e5710bSMark Peek 	if (xstring < xestring)
42945e5710bSMark Peek 	    break;
43045e5710bSMark Peek 	size *= 2;
43145e5710bSMark Peek     }
43245e5710bSMark Peek     *xstring++ = '\0';
43345e5710bSMark Peek     return xrealloc(buf, xstring - buf);
43445e5710bSMark Peek }
43545e5710bSMark Peek 
43645e5710bSMark Peek char *
xasprintf(const char * fmt,...)43745e5710bSMark Peek xasprintf(const char *fmt, ...)
43845e5710bSMark Peek {
43945e5710bSMark Peek     va_list va;
44045e5710bSMark Peek     char *ret;
44145e5710bSMark Peek 
44245e5710bSMark Peek     va_start (va, fmt);
44345e5710bSMark Peek     ret = xvasprintf(fmt, va);
44445e5710bSMark Peek     va_end(va);
44545e5710bSMark Peek     return ret;
44645e5710bSMark Peek }
447c80476e4SDavid E. O'Brien 
448c80476e4SDavid E. O'Brien 
449c80476e4SDavid E. O'Brien #ifdef PURIFY
450c80476e4SDavid E. O'Brien /* Purify uses (some of..) the following functions to output memory-use
451c80476e4SDavid E. O'Brien  * debugging info.  Given all the messing with file descriptors that
452c80476e4SDavid E. O'Brien  * tcsh does, the easiest way I could think of to get it (Purify) to
453c80476e4SDavid E. O'Brien  * print anything was by replacing some standard functions with
454c80476e4SDavid E. O'Brien  * ones that do tcsh output directly - see dumb hook in doreaddirs()
455c80476e4SDavid E. O'Brien  * (sh.dir.c) -sg
456c80476e4SDavid E. O'Brien  */
457c80476e4SDavid E. O'Brien #ifndef FILE
458c80476e4SDavid E. O'Brien #define FILE int
459c80476e4SDavid E. O'Brien #endif
460c80476e4SDavid E. O'Brien int
fprintf(FILE * fp,const char * fmt,...)461c80476e4SDavid E. O'Brien fprintf(FILE *fp, const char* fmt, ...)
462c80476e4SDavid E. O'Brien {
463*19d2e3deSDmitry Chagin     int count;
464c80476e4SDavid E. O'Brien     va_list va;
465c80476e4SDavid E. O'Brien     va_start(va, fmt);
466*19d2e3deSDmitry Chagin     count = doprnt(xputchar, fmt, va);
467c80476e4SDavid E. O'Brien     va_end(va);
468*19d2e3deSDmitry Chagin     return count;
469c80476e4SDavid E. O'Brien }
470c80476e4SDavid E. O'Brien 
471c80476e4SDavid E. O'Brien int
vfprintf(FILE * fp,const char * fmt,va_list va)47245e5710bSMark Peek vfprintf(FILE *fp, const char *fmt, va_list va)
473c80476e4SDavid E. O'Brien {
474*19d2e3deSDmitry Chagin     return doprnt(xputchar, fmt, va);
475c80476e4SDavid E. O'Brien }
476c80476e4SDavid E. O'Brien 
477c80476e4SDavid E. O'Brien #endif	/* PURIFY */
478