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