xref: /dragonfly/contrib/tcp_wrappers/vfprintf.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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   */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#) vfprintf.c 1.2 94/03/23 17:44:46";
11 #endif
12 
13 #include <stdio.h>
14 #include <ctype.h>
15 #ifdef __STDC__
16 #include <stdarg.h>
17 #else
18 #include <varargs.h>
19 #endif
20 
21 /* vfprintf - print variable-length argument list to stream */
22 
vfprintf(fp,format,ap)23 int     vfprintf(fp, format, ap)
24 FILE   *fp;
25 char   *format;
26 va_list ap;
27 {
28     char    fmt[BUFSIZ];                /* format specifier */
29     register char *fmtp;
30     register char *cp;
31     int     count = 0;
32 
33     /*
34      * Iterate over characters in the format string, picking up arguments
35      * when format specifiers are found.
36      */
37 
38     for (cp = format; *cp; cp++) {
39           if (*cp != '%') {
40               putc(*cp, fp);                      /* ordinary character */
41               count++;
42           } else {
43 
44               /*
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:
50                *
51                * %-?0?([0-9]+|\*)?\.?([0-9]+|\*)?l?[a-z]
52                *
53                * which includes some combinations that do not make sense.
54                */
55 
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++;
69               }
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++;
79               }
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;
86 
87               /* Execute the format string - let fprintf() do the hard work. */
88 
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;
112               }
113           }
114     }
115     return (count);
116 }
117 
118 /* vprintf - print variable-length argument list to stdout */
119 
vprintf(format,ap)120 vprintf(format, ap)
121 char   *format;
122 va_list ap;
123 {
124     return (vfprintf(stdout, format, ap));
125 }
126