Logo Search packages:      
Sourcecode: tcp-wrappers version File versions  Download package

vfprintf.c

 /*
  * 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));
}

Generated by  Doxygen 1.6.0   Back to index