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