xref: /onnv-gate/usr/src/cmd/tcpd/vfprintf.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate  /*
2*0Sstevel@tonic-gate   * vfprintf() and vprintf() clones. They will produce unexpected results
3*0Sstevel@tonic-gate   * when excessive dynamic ("*") field widths are specified. To be used for
4*0Sstevel@tonic-gate   * testing purposes only.
5*0Sstevel@tonic-gate   *
6*0Sstevel@tonic-gate   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
7*0Sstevel@tonic-gate   */
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate #ifndef lint
10*0Sstevel@tonic-gate static char sccsid[] = "@(#) vfprintf.c 1.2 94/03/23 17:44:46";
11*0Sstevel@tonic-gate #endif
12*0Sstevel@tonic-gate 
13*0Sstevel@tonic-gate #include <stdio.h>
14*0Sstevel@tonic-gate #include <ctype.h>
15*0Sstevel@tonic-gate #ifdef __STDC__
16*0Sstevel@tonic-gate #include <stdarg.h>
17*0Sstevel@tonic-gate #else
18*0Sstevel@tonic-gate #include <varargs.h>
19*0Sstevel@tonic-gate #endif
20*0Sstevel@tonic-gate 
21*0Sstevel@tonic-gate /* vfprintf - print variable-length argument list to stream */
22*0Sstevel@tonic-gate 
vfprintf(fp,format,ap)23*0Sstevel@tonic-gate int     vfprintf(fp, format, ap)
24*0Sstevel@tonic-gate FILE   *fp;
25*0Sstevel@tonic-gate char   *format;
26*0Sstevel@tonic-gate va_list ap;
27*0Sstevel@tonic-gate {
28*0Sstevel@tonic-gate     char    fmt[BUFSIZ];		/* format specifier */
29*0Sstevel@tonic-gate     register char *fmtp;
30*0Sstevel@tonic-gate     register char *cp;
31*0Sstevel@tonic-gate     int     count = 0;
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate     /*
34*0Sstevel@tonic-gate      * Iterate over characters in the format string, picking up arguments
35*0Sstevel@tonic-gate      * when format specifiers are found.
36*0Sstevel@tonic-gate      */
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate     for (cp = format; *cp; cp++) {
39*0Sstevel@tonic-gate 	if (*cp != '%') {
40*0Sstevel@tonic-gate 	    putc(*cp, fp);			/* ordinary character */
41*0Sstevel@tonic-gate 	    count++;
42*0Sstevel@tonic-gate 	} else {
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate 	    /*
45*0Sstevel@tonic-gate 	     * Format specifiers are handled one at a time, since we can only
46*0Sstevel@tonic-gate 	     * deal with arguments one at a time. Try to determine the end of
47*0Sstevel@tonic-gate 	     * the format specifier. We do not attempt to fully parse format
48*0Sstevel@tonic-gate 	     * strings, since we are ging to let fprintf() do the hard work.
49*0Sstevel@tonic-gate 	     * In regular expression notation, we recognize:
50*0Sstevel@tonic-gate 	     *
51*0Sstevel@tonic-gate 	     * %-?0?([0-9]+|\*)?\.?([0-9]+|\*)?l?[a-z]
52*0Sstevel@tonic-gate 	     *
53*0Sstevel@tonic-gate 	     * which includes some combinations that do not make sense.
54*0Sstevel@tonic-gate 	     */
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	    fmtp = fmt;
57*0Sstevel@tonic-gate 	    *fmtp++ = *cp++;
58*0Sstevel@tonic-gate 	    if (*cp == '-')			/* left-adjusted field? */
59*0Sstevel@tonic-gate 		*fmtp++ = *cp++;
60*0Sstevel@tonic-gate 	    if (*cp == '0')			/* zero-padded field? */
61*0Sstevel@tonic-gate 		*fmtp++ = *cp++;
62*0Sstevel@tonic-gate 	    if (*cp == '*') {			/* dynamic field witdh */
63*0Sstevel@tonic-gate 		sprintf(fmtp, "%d", va_arg(ap, int));
64*0Sstevel@tonic-gate 		fmtp += strlen(fmtp);
65*0Sstevel@tonic-gate 		cp++;
66*0Sstevel@tonic-gate 	    } else {
67*0Sstevel@tonic-gate 		while (isdigit(*cp))		/* hard-coded field width */
68*0Sstevel@tonic-gate 		    *fmtp++ = *cp++;
69*0Sstevel@tonic-gate 	    }
70*0Sstevel@tonic-gate 	    if (*cp == '.')			/* width/precision separator */
71*0Sstevel@tonic-gate 		*fmtp++ = *cp++;
72*0Sstevel@tonic-gate 	    if (*cp == '*') {			/* dynamic precision */
73*0Sstevel@tonic-gate 		sprintf(fmtp, "%d", va_arg(ap, int));
74*0Sstevel@tonic-gate 		fmtp += strlen(fmtp);
75*0Sstevel@tonic-gate 		cp++;
76*0Sstevel@tonic-gate 	    } else {
77*0Sstevel@tonic-gate 		while (isdigit(*cp))		/* hard-coded precision */
78*0Sstevel@tonic-gate 		    *fmtp++ = *cp++;
79*0Sstevel@tonic-gate 	    }
80*0Sstevel@tonic-gate 	    if (*cp == 'l')			/* long whatever */
81*0Sstevel@tonic-gate 		*fmtp++ = *cp++;
82*0Sstevel@tonic-gate 	    if (*cp == 0)			/* premature end, punt */
83*0Sstevel@tonic-gate 		break;
84*0Sstevel@tonic-gate 	    *fmtp++ = *cp;			/* type (checked below) */
85*0Sstevel@tonic-gate 	    *fmtp = 0;
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 	    /* Execute the format string - let fprintf() do the hard work. */
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate 	    switch (fmtp[-1]) {
90*0Sstevel@tonic-gate 	    case 's':				/* string-valued argument */
91*0Sstevel@tonic-gate 		count += fprintf(fp, fmt, va_arg(ap, char *));
92*0Sstevel@tonic-gate 		break;
93*0Sstevel@tonic-gate 	    case 'c':				/* integral-valued argument */
94*0Sstevel@tonic-gate 	    case 'd':
95*0Sstevel@tonic-gate 	    case 'u':
96*0Sstevel@tonic-gate 	    case 'o':
97*0Sstevel@tonic-gate 	    case 'x':
98*0Sstevel@tonic-gate 		if (fmtp[-2] == 'l')
99*0Sstevel@tonic-gate 		    count += fprintf(fp, fmt, va_arg(ap, long));
100*0Sstevel@tonic-gate 		else
101*0Sstevel@tonic-gate 		    count += fprintf(fp, fmt, va_arg(ap, int));
102*0Sstevel@tonic-gate 		break;
103*0Sstevel@tonic-gate 	    case 'e':				/* float-valued argument */
104*0Sstevel@tonic-gate 	    case 'f':
105*0Sstevel@tonic-gate 	    case 'g':
106*0Sstevel@tonic-gate 		count += fprintf(fp, fmt, va_arg(ap, double));
107*0Sstevel@tonic-gate 		break;
108*0Sstevel@tonic-gate 	    default:				/* anything else */
109*0Sstevel@tonic-gate 		putc(fmtp[-1], fp);
110*0Sstevel@tonic-gate 		count++;
111*0Sstevel@tonic-gate 		break;
112*0Sstevel@tonic-gate 	    }
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate     }
115*0Sstevel@tonic-gate     return (count);
116*0Sstevel@tonic-gate }
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate /* vprintf - print variable-length argument list to stdout */
119*0Sstevel@tonic-gate 
vprintf(format,ap)120*0Sstevel@tonic-gate vprintf(format, ap)
121*0Sstevel@tonic-gate char   *format;
122*0Sstevel@tonic-gate va_list ap;
123*0Sstevel@tonic-gate {
124*0Sstevel@tonic-gate     return (vfprintf(stdout, format, ap));
125*0Sstevel@tonic-gate }
126