xref: /freebsd/contrib/tcp_wrappers/vfprintf.c (revision 14f102eacc8434a5a1f96466752578a4167140c9)
12aef6930SMark Murray  /*
22aef6930SMark Murray   * vfprintf() and vprintf() clones. They will produce unexpected results
32aef6930SMark Murray   * when excessive dynamic ("*") field widths are specified. To be used for
42aef6930SMark Murray   * testing purposes only.
52aef6930SMark Murray   *
62aef6930SMark Murray   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
72aef6930SMark Murray   */
82aef6930SMark Murray 
92aef6930SMark Murray #ifndef lint
102aef6930SMark Murray static char sccsid[] = "@(#) vfprintf.c 1.2 94/03/23 17:44:46";
112aef6930SMark Murray #endif
122aef6930SMark Murray 
132aef6930SMark Murray #include <stdio.h>
142aef6930SMark Murray #include <ctype.h>
152aef6930SMark Murray #ifdef __STDC__
162aef6930SMark Murray #include <stdarg.h>
172aef6930SMark Murray #else
182aef6930SMark Murray #include <varargs.h>
192aef6930SMark Murray #endif
202aef6930SMark Murray 
212aef6930SMark Murray /* vfprintf - print variable-length argument list to stream */
222aef6930SMark Murray 
vfprintf(FILE * fp,char * format,va_list ap)23*14f102eaSEd Maste int     vfprintf(FILE *fp, char *format, va_list ap)
242aef6930SMark Murray {
252aef6930SMark Murray     char    fmt[BUFSIZ];		/* format specifier */
262aef6930SMark Murray     register char *fmtp;
272aef6930SMark Murray     register char *cp;
282aef6930SMark Murray     int     count = 0;
292aef6930SMark Murray 
302aef6930SMark Murray     /*
312aef6930SMark Murray      * Iterate over characters in the format string, picking up arguments
322aef6930SMark Murray      * when format specifiers are found.
332aef6930SMark Murray      */
342aef6930SMark Murray 
352aef6930SMark Murray     for (cp = format; *cp; cp++) {
362aef6930SMark Murray 	if (*cp != '%') {
372aef6930SMark Murray 	    putc(*cp, fp);			/* ordinary character */
382aef6930SMark Murray 	    count++;
392aef6930SMark Murray 	} else {
402aef6930SMark Murray 
412aef6930SMark Murray 	    /*
422aef6930SMark Murray 	     * Format specifiers are handled one at a time, since we can only
432aef6930SMark Murray 	     * deal with arguments one at a time. Try to determine the end of
442aef6930SMark Murray 	     * the format specifier. We do not attempt to fully parse format
452aef6930SMark Murray 	     * strings, since we are ging to let fprintf() do the hard work.
462aef6930SMark Murray 	     * In regular expression notation, we recognize:
472aef6930SMark Murray 	     *
482aef6930SMark Murray 	     * %-?0?([0-9]+|\*)?\.?([0-9]+|\*)?l?[a-z]
492aef6930SMark Murray 	     *
502aef6930SMark Murray 	     * which includes some combinations that do not make sense.
512aef6930SMark Murray 	     */
522aef6930SMark Murray 
532aef6930SMark Murray 	    fmtp = fmt;
542aef6930SMark Murray 	    *fmtp++ = *cp++;
552aef6930SMark Murray 	    if (*cp == '-')			/* left-adjusted field? */
562aef6930SMark Murray 		*fmtp++ = *cp++;
572aef6930SMark Murray 	    if (*cp == '0')			/* zero-padded field? */
582aef6930SMark Murray 		*fmtp++ = *cp++;
592aef6930SMark Murray 	    if (*cp == '*') {			/* dynamic field witdh */
602aef6930SMark Murray 		sprintf(fmtp, "%d", va_arg(ap, int));
612aef6930SMark Murray 		fmtp += strlen(fmtp);
622aef6930SMark Murray 		cp++;
632aef6930SMark Murray 	    } else {
642aef6930SMark Murray 		while (isdigit(*cp))		/* hard-coded field width */
652aef6930SMark Murray 		    *fmtp++ = *cp++;
662aef6930SMark Murray 	    }
672aef6930SMark Murray 	    if (*cp == '.')			/* width/precision separator */
682aef6930SMark Murray 		*fmtp++ = *cp++;
692aef6930SMark Murray 	    if (*cp == '*') {			/* dynamic precision */
702aef6930SMark Murray 		sprintf(fmtp, "%d", va_arg(ap, int));
712aef6930SMark Murray 		fmtp += strlen(fmtp);
722aef6930SMark Murray 		cp++;
732aef6930SMark Murray 	    } else {
742aef6930SMark Murray 		while (isdigit(*cp))		/* hard-coded precision */
752aef6930SMark Murray 		    *fmtp++ = *cp++;
762aef6930SMark Murray 	    }
772aef6930SMark Murray 	    if (*cp == 'l')			/* long whatever */
782aef6930SMark Murray 		*fmtp++ = *cp++;
792aef6930SMark Murray 	    if (*cp == 0)			/* premature end, punt */
802aef6930SMark Murray 		break;
812aef6930SMark Murray 	    *fmtp++ = *cp;			/* type (checked below) */
822aef6930SMark Murray 	    *fmtp = 0;
832aef6930SMark Murray 
842aef6930SMark Murray 	    /* Execute the format string - let fprintf() do the hard work. */
852aef6930SMark Murray 
862aef6930SMark Murray 	    switch (fmtp[-1]) {
872aef6930SMark Murray 	    case 's':				/* string-valued argument */
882aef6930SMark Murray 		count += fprintf(fp, fmt, va_arg(ap, char *));
892aef6930SMark Murray 		break;
902aef6930SMark Murray 	    case 'c':				/* integral-valued argument */
912aef6930SMark Murray 	    case 'd':
922aef6930SMark Murray 	    case 'u':
932aef6930SMark Murray 	    case 'o':
942aef6930SMark Murray 	    case 'x':
952aef6930SMark Murray 		if (fmtp[-2] == 'l')
962aef6930SMark Murray 		    count += fprintf(fp, fmt, va_arg(ap, long));
972aef6930SMark Murray 		else
982aef6930SMark Murray 		    count += fprintf(fp, fmt, va_arg(ap, int));
992aef6930SMark Murray 		break;
1002aef6930SMark Murray 	    case 'e':				/* float-valued argument */
1012aef6930SMark Murray 	    case 'f':
1022aef6930SMark Murray 	    case 'g':
1032aef6930SMark Murray 		count += fprintf(fp, fmt, va_arg(ap, double));
1042aef6930SMark Murray 		break;
1052aef6930SMark Murray 	    default:				/* anything else */
1062aef6930SMark Murray 		putc(fmtp[-1], fp);
1072aef6930SMark Murray 		count++;
1082aef6930SMark Murray 		break;
1092aef6930SMark Murray 	    }
1102aef6930SMark Murray 	}
1112aef6930SMark Murray     }
1122aef6930SMark Murray     return (count);
1132aef6930SMark Murray }
1142aef6930SMark Murray 
1152aef6930SMark Murray /* vprintf - print variable-length argument list to stdout */
1162aef6930SMark Murray 
vprintf(char * format,va_list ap)117*14f102eaSEd Maste vprintf(char *format, va_list ap)
1182aef6930SMark Murray {
1192aef6930SMark Murray     return (vfprintf(stdout, format, ap));
1202aef6930SMark Murray }
121