]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcsh/tc.printf.c
This commit was generated by cvs2svn to compensate for changes in r71756,
[FreeBSD/FreeBSD.git] / contrib / tcsh / tc.printf.c
1 /* $Header: /src/pub/tcsh/tc.printf.c,v 3.19 1998/10/25 15:10:37 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.
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
41 RCSID("$Id: tc.printf.c,v 3.19 1998/10/25 15:10:37 christos 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
50 static char buf[128];
51
52 static  void    xaddchar        __P((int));
53 static  void    doprnt          __P((void (*) __P((int)), const char *, va_list));
54
55 static void
56 doprnt(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 - (int) (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 = (int) (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 - (int) (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 *);
233 lcase_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
271 static char *xstring, *xestring;
272 static void
273 xaddchar(c)
274     int     c;
275 {
276     if (xestring == xstring)
277         *xstring = '\0';
278     else
279         *xstring++ = (char) c;
280 }
281
282
283 pret_t
284 /*VARARGS*/
285 #ifdef FUNCPROTO
286 xsnprintf(char *str, size_t size, const char *fmt, ...)
287 #else
288 xsnprintf(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
315 pret_t
316 /*VARARGS*/
317 #ifdef FUNCPROTO
318 xprintf(const char *fmt, ...)
319 #else
320 xprintf(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
341 pret_t
342 xvprintf(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
352 pret_t
353 xvsnprintf(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
381 int 
382 #ifdef FUNCPROTO
383 fprintf(FILE *fp, const char* fmt, ...)
384 #else
385 fprintf(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
405 int 
406 vfprintf(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 */