144743Smarkm /* 244743Smarkm * vfprintf() and vprintf() clones. They will produce unexpected results 344743Smarkm * when excessive dynamic ("*") field widths are specified. To be used for 444743Smarkm * testing purposes only. 544743Smarkm * 644743Smarkm * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 744743Smarkm */ 844743Smarkm 944743Smarkm#ifndef lint 1044743Smarkmstatic char sccsid[] = "@(#) vfprintf.c 1.2 94/03/23 17:44:46"; 1144743Smarkm#endif 1244743Smarkm 1344743Smarkm#include <stdio.h> 1444743Smarkm#include <ctype.h> 1544743Smarkm#ifdef __STDC__ 1644743Smarkm#include <stdarg.h> 1744743Smarkm#else 1844743Smarkm#include <varargs.h> 1944743Smarkm#endif 2044743Smarkm 2144743Smarkm/* vfprintf - print variable-length argument list to stream */ 2244743Smarkm 2344743Smarkmint vfprintf(fp, format, ap) 2444743SmarkmFILE *fp; 2544743Smarkmchar *format; 2644743Smarkmva_list ap; 2744743Smarkm{ 2844743Smarkm char fmt[BUFSIZ]; /* format specifier */ 2944743Smarkm register char *fmtp; 3044743Smarkm register char *cp; 3144743Smarkm int count = 0; 3244743Smarkm 3344743Smarkm /* 3444743Smarkm * Iterate over characters in the format string, picking up arguments 3544743Smarkm * when format specifiers are found. 3644743Smarkm */ 3744743Smarkm 3844743Smarkm for (cp = format; *cp; cp++) { 3944743Smarkm if (*cp != '%') { 4044743Smarkm putc(*cp, fp); /* ordinary character */ 4144743Smarkm count++; 4244743Smarkm } else { 4344743Smarkm 4444743Smarkm /* 4544743Smarkm * Format specifiers are handled one at a time, since we can only 4644743Smarkm * deal with arguments one at a time. Try to determine the end of 4744743Smarkm * the format specifier. We do not attempt to fully parse format 4844743Smarkm * strings, since we are ging to let fprintf() do the hard work. 4944743Smarkm * In regular expression notation, we recognize: 5044743Smarkm * 5144743Smarkm * %-?0?([0-9]+|\*)?\.?([0-9]+|\*)?l?[a-z] 5244743Smarkm * 5344743Smarkm * which includes some combinations that do not make sense. 5444743Smarkm */ 5544743Smarkm 5644743Smarkm fmtp = fmt; 5744743Smarkm *fmtp++ = *cp++; 5844743Smarkm if (*cp == '-') /* left-adjusted field? */ 5944743Smarkm *fmtp++ = *cp++; 6044743Smarkm if (*cp == '0') /* zero-padded field? */ 6144743Smarkm *fmtp++ = *cp++; 6244743Smarkm if (*cp == '*') { /* dynamic field witdh */ 6344743Smarkm sprintf(fmtp, "%d", va_arg(ap, int)); 6444743Smarkm fmtp += strlen(fmtp); 6544743Smarkm cp++; 6644743Smarkm } else { 6744743Smarkm while (isdigit(*cp)) /* hard-coded field width */ 6844743Smarkm *fmtp++ = *cp++; 6944743Smarkm } 7044743Smarkm if (*cp == '.') /* width/precision separator */ 7144743Smarkm *fmtp++ = *cp++; 7244743Smarkm if (*cp == '*') { /* dynamic precision */ 7344743Smarkm sprintf(fmtp, "%d", va_arg(ap, int)); 7444743Smarkm fmtp += strlen(fmtp); 7544743Smarkm cp++; 7644743Smarkm } else { 7744743Smarkm while (isdigit(*cp)) /* hard-coded precision */ 7844743Smarkm *fmtp++ = *cp++; 7944743Smarkm } 8044743Smarkm if (*cp == 'l') /* long whatever */ 8144743Smarkm *fmtp++ = *cp++; 8244743Smarkm if (*cp == 0) /* premature end, punt */ 8344743Smarkm break; 8444743Smarkm *fmtp++ = *cp; /* type (checked below) */ 8544743Smarkm *fmtp = 0; 8644743Smarkm 8744743Smarkm /* Execute the format string - let fprintf() do the hard work. */ 8844743Smarkm 8944743Smarkm switch (fmtp[-1]) { 9044743Smarkm case 's': /* string-valued argument */ 9144743Smarkm count += fprintf(fp, fmt, va_arg(ap, char *)); 9244743Smarkm break; 9344743Smarkm case 'c': /* integral-valued argument */ 9444743Smarkm case 'd': 9544743Smarkm case 'u': 9644743Smarkm case 'o': 9744743Smarkm case 'x': 9844743Smarkm if (fmtp[-2] == 'l') 9944743Smarkm count += fprintf(fp, fmt, va_arg(ap, long)); 10044743Smarkm else 10144743Smarkm count += fprintf(fp, fmt, va_arg(ap, int)); 10244743Smarkm break; 10344743Smarkm case 'e': /* float-valued argument */ 10444743Smarkm case 'f': 10544743Smarkm case 'g': 10644743Smarkm count += fprintf(fp, fmt, va_arg(ap, double)); 10744743Smarkm break; 10844743Smarkm default: /* anything else */ 10944743Smarkm putc(fmtp[-1], fp); 11044743Smarkm count++; 11144743Smarkm break; 11244743Smarkm } 11344743Smarkm } 11444743Smarkm } 11544743Smarkm return (count); 11644743Smarkm} 11744743Smarkm 11844743Smarkm/* vprintf - print variable-length argument list to stdout */ 11944743Smarkm 12044743Smarkmvprintf(format, ap) 12144743Smarkmchar *format; 12244743Smarkmva_list ap; 12344743Smarkm{ 12444743Smarkm return (vfprintf(stdout, format, ap)); 12544743Smarkm} 126