summaryrefslogtreecommitdiffstats
path: root/contrib/tcp_wrappers/vfprintf.c
blob: d6f37d59bfe84218985dadca7925922586af41ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 /*
  * vfprintf() and vprintf() clones. They will produce unexpected results
  * when excessive dynamic ("*") field widths are specified. To be used for
  * testing purposes only.
  * 
  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  */

#ifndef lint
static char sccsid[] = "@(#) vfprintf.c 1.2 94/03/23 17:44:46";
#endif

#include <stdio.h>
#include <ctype.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif

/* vfprintf - print variable-length argument list to stream */

int     vfprintf(fp, format, ap)
FILE   *fp;
char   *format;
va_list ap;
{
    char    fmt[BUFSIZ];		/* format specifier */
    register char *fmtp;
    register char *cp;
    int     count = 0;

    /*
     * Iterate over characters in the format string, picking up arguments
     * when format specifiers are found.
     */

    for (cp = format; *cp; cp++) {
	if (*cp != '%') {
	    putc(*cp, fp);			/* ordinary character */
	    count++;
	} else {

	    /*
	     * Format specifiers are handled one at a time, since we can only
	     * deal with arguments one at a time. Try to determine the end of
	     * the format specifier. We do not attempt to fully parse format
	     * strings, since we are ging to let fprintf() do the hard work.
	     * In regular expression notation, we recognize:
	     * 
	     * %-?0?([0-9]+|\*)?\.?([0-9]+|\*)?l?[a-z]
	     * 
	     * which includes some combinations that do not make sense.
	     */

	    fmtp = fmt;
	    *fmtp++ = *cp++;
	    if (*cp == '-')			/* left-adjusted field? */
		*fmtp++ = *cp++;
	    if (*cp == '0')			/* zero-padded field? */
		*fmtp++ = *cp++;
	    if (*cp == '*') {			/* dynamic field witdh */
		sprintf(fmtp, "%d", va_arg(ap, int));
		fmtp += strlen(fmtp);
		cp++;
	    } else {
		while (isdigit(*cp))		/* hard-coded field width */
		    *fmtp++ = *cp++;
	    }
	    if (*cp == '.')			/* width/precision separator */
		*fmtp++ = *cp++;
	    if (*cp == '*') {			/* dynamic precision */
		sprintf(fmtp, "%d", va_arg(ap, int));
		fmtp += strlen(fmtp);
		cp++;
	    } else {
		while (isdigit(*cp))		/* hard-coded precision */
		    *fmtp++ = *cp++;
	    }
	    if (*cp == 'l')			/* long whatever */
		*fmtp++ = *cp++;
	    if (*cp == 0)			/* premature end, punt */
		break;
	    *fmtp++ = *cp;			/* type (checked below) */
	    *fmtp = 0;

	    /* Execute the format string - let fprintf() do the hard work. */

	    switch (fmtp[-1]) {
	    case 's':				/* string-valued argument */
		count += fprintf(fp, fmt, va_arg(ap, char *));
		break;
	    case 'c':				/* integral-valued argument */
	    case 'd':
	    case 'u':
	    case 'o':
	    case 'x':
		if (fmtp[-2] == 'l')
		    count += fprintf(fp, fmt, va_arg(ap, long));
		else
		    count += fprintf(fp, fmt, va_arg(ap, int));
		break;
	    case 'e':				/* float-valued argument */
	    case 'f':
	    case 'g':
		count += fprintf(fp, fmt, va_arg(ap, double));
		break;
	    default:				/* anything else */
		putc(fmtp[-1], fp);
		count++;
		break;
	    }
	}
    }
    return (count);
}

/* vprintf - print variable-length argument list to stdout */

vprintf(format, ap)
char   *format;
va_list ap;
{
    return (vfprintf(stdout, format, ap));
}
OpenPOWER on IntegriCloud