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:
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:
120: vprintf(format, ap)
121: char *format;
122: va_list ap;
123: {
124: return (vfprintf(stdout, format, ap));
125: }
Defined functions
Defined variables