source: trunk/third/tcsh/tc.printf.c @ 12039

Revision 12039, 9.2 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/tc.printf.c,v 1.1.1.2 1998-10-03 21:10:14 danw 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.
10 *
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. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *      This product includes software developed by the University of
22 *      California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39#include "sh.h"
40
41RCSID("$Id: tc.printf.c,v 1.1.1.2 1998-10-03 21:10:14 danw Exp $")
42
43#ifdef lint
44#undef va_arg
45#define va_arg(a, b) (a ? (b) 0 : (b) 0)
46#endif
47
48#define INF     32766           /* should be bigger than any field to print */
49
50static char buf[128];
51
52static  void    xaddchar        __P((int));
53static  void    doprnt          __P((void (*) __P((int)), const char *, va_list));
54
55static void
56doprnt(addchar, sfmt, ap)
57    void    (*addchar) __P((int));
58    const char   *sfmt;
59    va_list ap;
60{
61    register char *bp;
62    register const char *f;
63#ifdef SHORT_STRINGS
64    register Char *Bp;
65#endif /* SHORT_STRINGS */
66    register long l;
67    register unsigned long u;
68    register int i;
69    register int fmt;
70    register unsigned char pad = ' ';
71    int     flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
72    int     sign = 0;
73    int     attributes = 0;
74
75
76    f = sfmt;
77    for (; *f; f++) {
78        if (*f != '%') {        /* then just out the char */
79            (*addchar) ((int) (((unsigned char)*f) | attributes));
80        }
81        else {
82            f++;                /* skip the % */
83
84            if (*f == '-') {    /* minus: flush left */
85                flush_left = 1;
86                f++;
87            }
88
89            if (*f == '0' || *f == '.') {
90                /* padding with 0 rather than blank */
91                pad = '0';
92                f++;
93            }
94            if (*f == '*') {    /* field width */
95                f_width = va_arg(ap, int);
96                f++;
97            }
98            else if (Isdigit((unsigned char) *f)) {
99                f_width = atoi(f);
100                while (Isdigit((unsigned char) *f))
101                    f++;        /* skip the digits */
102            }
103
104            if (*f == '.') {    /* precision */
105                f++;
106                if (*f == '*') {
107                    prec = va_arg(ap, int);
108                    f++;
109                }
110                else if (Isdigit((unsigned char) *f)) {
111                    prec = atoi((char *) f);
112                    while (Isdigit((unsigned char) *f))
113                        f++;    /* skip the digits */
114                }
115            }
116
117            if (*f == '#') {    /* alternate form */
118                hash = 1;
119                f++;
120            }
121
122            if (*f == 'l') {    /* long format */
123                do_long = 1;
124                f++;
125            }
126
127            fmt = (unsigned char) *f;
128            if (fmt != 'S' && fmt != 'Q' && Isupper(fmt)) {
129                do_long = 1;
130                fmt = Tolower(fmt);
131            }
132            bp = buf;
133            switch (fmt) {      /* do the format */
134            case 'd':
135                if (do_long)
136                    l = va_arg(ap, long);
137                else
138                    l = (long) (va_arg(ap, int));
139                if (l < 0) {
140                    sign = 1;
141                    l = -l;
142                }
143                do {
144                    *bp++ = (char) (l % 10) + '0';
145                } while ((l /= 10) > 0);
146                if (sign)
147                    *bp++ = '-';
148                f_width = f_width - (bp - buf);
149                if (!flush_left)
150                    while (f_width-- > 0)
151                        (*addchar) ((int) (pad | attributes));
152                for (bp--; bp >= buf; bp--)
153                    (*addchar) ((int) (((unsigned char) *bp) | attributes));
154                if (flush_left)
155                    while (f_width-- > 0)
156                        (*addchar) ((int) (' ' | attributes));
157                break;
158
159            case 'o':
160            case 'x':
161            case 'u':
162                if (do_long)
163                    u = va_arg(ap, unsigned long);
164                else
165                    u = (unsigned long) (va_arg(ap, unsigned int));
166                if (fmt == 'u') {       /* unsigned decimal */
167                    do {
168                        *bp++ = (char) (u % 10) + '0';
169                    } while ((u /= 10) > 0);
170                }
171                else if (fmt == 'o') {  /* octal */
172                    do {
173                        *bp++ = (char) (u % 8) + '0';
174                    } while ((u /= 8) > 0);
175                    if (hash)
176                        *bp++ = '0';
177                }
178                else if (fmt == 'x') {  /* hex */
179                    do {
180                        i = u % 16;
181                        if (i < 10)
182                            *bp++ = i + '0';
183                        else
184                            *bp++ = i - 10 + 'a';
185                    } while ((u /= 16) > 0);
186                    if (hash) {
187                        *bp++ = 'x';
188                        *bp++ = '0';
189                    }
190                }
191                i = f_width - (bp - buf);
192                if (!flush_left)
193                    while (i-- > 0)
194                        (*addchar) ((int) (pad | attributes));
195                for (bp--; bp >= buf; bp--)
196                    (*addchar) ((int) (((unsigned char) *bp) | attributes));
197                if (flush_left)
198                    while (i-- > 0)
199                        (*addchar) ((int) (' ' | attributes));
200                break;
201
202
203            case 'c':
204                i = va_arg(ap, int);
205                (*addchar) ((int) (i | attributes));
206                break;
207
208            case 'S':
209            case 'Q':
210                Bp = va_arg(ap, Char *);
211                if (!Bp) {
212                    bp = NULL;
213                    goto lcase_s;
214                }
215                f_width = f_width - Strlen(Bp);
216                if (!flush_left)
217                    while (f_width-- > 0)
218                        (*addchar) ((int) (pad | attributes));
219                for (i = 0; *Bp && i < prec; i++) {
220                    if (fmt == 'Q' && *Bp & QUOTE)
221                        (*addchar) ((int) ('\\' | attributes));
222                    (*addchar) ((int) ((*Bp & TRIM) | attributes));
223                    Bp++;
224                }
225                if (flush_left)
226                    while (f_width-- > 0)
227                        (*addchar) ((int) (' ' | attributes));
228                break;
229
230            case 's':
231            case 'q':
232                bp = va_arg(ap, char *);
233lcase_s:
234                if (!bp)
235                    bp = "(nil)";
236                f_width = f_width - strlen((char *) bp);
237                if (!flush_left)
238                    while (f_width-- > 0)
239                        (*addchar) ((int) (pad | attributes));
240                for (i = 0; *bp && i < prec; i++) {
241                    if (fmt == 'q' && *bp & QUOTE)
242                        (*addchar) ((int) ('\\' | attributes));
243                    (*addchar) ((int) (((unsigned char) *bp & TRIM) |
244                                        attributes));
245                    bp++;
246                }
247                if (flush_left)
248                    while (f_width-- > 0)
249                        (*addchar) ((int) (' ' | attributes));
250                break;
251
252            case 'a':
253                attributes = va_arg(ap, int);
254                break;
255
256            case '%':
257                (*addchar) ((int) ('%' | attributes));
258                break;
259
260            default:
261                break;
262            }
263            flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
264            sign = 0;
265            pad = ' ';
266        }
267    }
268}
269
270
271static char *xstring, *xestring;
272static void
273xaddchar(c)
274    int     c;
275{
276    if (xestring == xstring)
277        *xstring = '\0';
278    else
279        *xstring++ = (char) c;
280}
281
282
283pret_t
284/*VARARGS*/
285#ifdef FUNCPROTO
286xsnprintf(char *str, size_t size, const char *fmt, ...)
287#else
288xsnprintf(va_alist)
289    va_dcl
290#endif
291{
292    va_list va;
293#ifdef FUNCPROTO
294    va_start(va, fmt);
295#else
296    char *str, *fmt;
297    size_t size;
298
299    va_start(va);
300    str = va_arg(va, char *);
301    size = va_arg(va, size_t);
302    fmt = va_arg(va, char *);
303#endif
304
305    xstring = str;
306    xestring = str + size - 1;
307    doprnt(xaddchar, fmt, va);
308    va_end(va);
309    *xstring++ = '\0';
310#ifdef PURIFY
311    return 1;
312#endif
313}
314
315pret_t
316/*VARARGS*/
317#ifdef FUNCPROTO
318xprintf(const char *fmt, ...)
319#else
320xprintf(va_alist)
321    va_dcl
322#endif
323{
324    va_list va;
325#ifdef FUNCPROTO
326    va_start(va, fmt);
327#else
328    char   *fmt;
329
330    va_start(va);
331    fmt = va_arg(va, char *);
332#endif
333    doprnt(xputchar, fmt, va);
334    va_end(va);
335#ifdef PURIFY
336    return 1;
337#endif
338}
339
340
341pret_t
342xvprintf(fmt, va)
343    const char   *fmt;
344    va_list va;
345{
346    doprnt(xputchar, fmt, va);
347#ifdef PURIFY
348    return 1;
349#endif
350}
351
352pret_t
353xvsnprintf(str, size, fmt, va)
354    char   *str;
355    size_t size;
356    const char   *fmt;
357    va_list va;
358{
359    xstring = str;
360    xestring = str + size - 1;
361    doprnt(xaddchar, fmt, va);
362    *xstring++ = '\0';
363#ifdef PURIFY
364    return 1;
365#endif
366}
367
368
369
370#ifdef PURIFY
371/* Purify uses (some of..) the following functions to output memory-use
372 * debugging info.  Given all the messing with file descriptors that
373 * tcsh does, the easiest way I could think of to get it (Purify) to
374 * print anything was by replacing some standard functions with
375 * ones that do tcsh output directly - see dumb hook in doreaddirs()
376 * (sh.dir.c) -sg
377 */
378#ifndef FILE
379#define FILE int
380#endif
381int
382#ifdef FUNCPROTO
383fprintf(FILE *fp, const char* fmt, ...)
384#else
385fprintf(va_alist)
386    va_dcl
387#endif
388{
389    va_list va;
390#ifdef FUNCPROTO
391    va_start(va, fmt);
392#else
393    FILE *fp;
394    const char   *fmt;
395
396    va_start(va);
397    fp = va_arg(va, FILE *);
398    fmt = va_arg(va, const char *);
399#endif
400    doprnt(xputchar, fmt, va);
401    va_end(va);
402    return 1;
403}
404
405int
406vfprintf(fp, fmt, va)
407    FILE *fp;
408    const char   *fmt;
409    va_list va;
410{
411    doprnt(xputchar, fmt, va);
412    return 1;
413}
414
415#endif  /* PURIFY */
Note: See TracBrowser for help on using the repository browser.