home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char *RCSid = "$Id: vprintf.c,v 1.4 93/05/05 21:19:03 sjg Exp $";
- #endif
- #ifdef __STDC__
- #include <stdarg.h>
- #else
- #include <varargs.h>
- #endif
- #include <stdio.h>
-
- #define BUF 40 /* buffer for int -> string conversion */
-
- int
- #ifdef __STDC__
- vprintf(const char *fmt, va_list va) {
- #else
- vprintf(fmt, va) char *fmt; va_list va; {
- #endif
- return vfprintf(stdout, fmt, va);
- }
-
- int
- #ifdef __STDC__
- vfprintf(register FILE *f, register const char *fmt, register va_list va) {
- #else
- vfprintf(f, fmt, va) register FILE *f; register char *fmt; register va_list va; {
- #endif
- register int c;
- int pos = 0; /* todo: implement */
-
- while ((c = *fmt++))
- if (c == '%') {
- long n;
- register unsigned long u;
- char buf [BUF+1];
- register char *p = buf + BUF;
- register enum {
- FF_ALT = 0x01, /* #, alternate format */
- FF_SHORT = 0x02, /* h, short arg */
- FF_LONG = 0x04, /* l, long arg */
- FF_ZERO = 0x08, /* 0, zero fill */
- FF_LEFT = 0x10, /* -, left adjust */
- FF_PREC = 0x20, /* .*, precision */
- FF_NEG = 0x40, /* signed arg */
- FF_PUTS = 0x80, /* fputs(p, f) */
- FF_DEFAULT = 0
- } flags = FF_DEFAULT;
- int sign = '-'; /* sign: [ +-] */
- int width = 0, prec = 0; /* width, precision */
-
- *p = 0;
-
- /* scan flag characters */
- for (c = *fmt++; ; c = *fmt++) switch (c) {
- case '0':
- flags |= FF_ZERO;
- break;
-
- case '#': /* alternate format */
- flags |= FF_ALT;
- break;
-
- case ' ': /* blank sign */
- sign = ' ';
- break;
- case '+': /* +/- sign */
- sign = '+';
- break;
-
- case '-': /* left just. */
- flags |= FF_LEFT;
- break;
-
- default:
- goto Frogs;
- }
- Frogs:
-
- /* scan width */
- if (c == '*') { /* width from arg list */
- width = va_arg(va, int);
- c = *fmt++;
- } else
- while ('0' <= c && c <= '9') {
- width = width*10 + (c-'0');
- c = *fmt++;
- }
-
- if (c == '.') { /* scan precision */
- flags |= FF_PREC;
- c = *fmt++;
- if (c == '*') { /* precision from arg list */
- prec = va_arg(va, int);
- c = *fmt++;
- } else
- while ('0' <= c && c <= '9') {
- prec = prec*10 + (c-'0');
- c = *fmt++;
- }
- }
-
- /* length modifiers */
- if (c == 'h') {
- flags |= FF_SHORT;
- c = *fmt++;
- } else if (c == 'l') {
- flags |= FF_LONG;
- c = *fmt++;
- }
-
- /* do conversion */
- switch (c) {
- case '%': /* %% -> % */
- putc(c, f);
- pos ++;
- break;
-
- case 'p': /* pointer */
- *--p = '}';
- u = (unsigned long) va_arg(va, void*);
- do {
- *--p = "0123456789ABCDEF"[u%16];
- u /= 16;
- } while (u != 0);
- *--p = '{';
- flags |= FF_PUTS;
- break;
-
- case 'n': /* save position */
- *va_arg(va, int*) = pos;
- break;
-
- case 'c': /* character */
- u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
- : (flags&&FF_LONG) ? va_arg(va, unsigned long)
- : va_arg(va, unsigned int);
- *--p = u;
- flags |= FF_PUTS;
- break;
-
- case 's': /* string */
- if ((p = va_arg(va, char *)) == NULL)
- p = "";
- if ((flags&FF_PREC) && strlen(p) > prec) {
- pos += prec;
- while (--prec >= 0)
- {
- c = *p++;
- putc(c, f);
- }
- break;
- }
- flags |= FF_PUTS;
- break;
-
- case 'i': case 'd': case 'u': /* decimal */
- if (c != 'u') { /* signed */
- n = (flags&FF_SHORT) ? va_arg(va, short)
- : (flags&&FF_LONG) ? va_arg(va, long)
- : va_arg(va, int);
- if (n < 0)
- flags |= FF_NEG;
- u = (n < 0) ? -n : n;
- } else
- u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
- : (flags&&FF_LONG) ? va_arg(va, unsigned long)
- : va_arg(va, unsigned int);
- do {
- *--p = '0' + u%10;
- u /= 10;
- } while (u != 0);
- prec -= buf+BUF - p;
- while (--prec >= 0)
- *--p = '0';
- if (flags&FF_NEG)
- *--p = '-';
- else
- if (sign != '-')
- *--p = (sign == '+') ? '+' : ' ';
- flags |= FF_PUTS;
- break;
-
- case 'x': case 'X': /* hex, Hex */
- u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
- : (flags&&FF_LONG) ? va_arg(va, unsigned long)
- : va_arg(va, unsigned int);
- do {
- *--p = "0123456789ABCDEF"[u%16];
- u /= 16;
- } while (u != 0);
- prec -= buf+BUF - p;
- while (--prec >= 0)
- *--p = '0';
- if (flags&&FF_ALT)
- *--p = 'x', *--p = '0';
- flags |= FF_PUTS;
- break;
-
- case 'o': /* octal */
- u = (flags&FF_SHORT) ? va_arg(va, unsigned short)
- : (flags&&FF_LONG) ? va_arg(va, unsigned long)
- : va_arg(va, unsigned int);
- do {
- *--p = '0' + u%8;
- u /= 8;
- } while (u != 0);
- prec -= buf+BUF - p;
- while (--prec >= 0)
- *--p = '0';
- if (flags&&FF_ALT && *p != '0')
- *--p = '0';
- flags |= FF_PUTS;
- break;
-
- default: /* todo: error */
- putc('%', f);
- putc(c, f);
- pos += 2;
- break;
- }
-
- /* copy adjusted string "p" to output */
- if (flags&FF_PUTS) {
- int len = strlen(p);
- int pad = width - len;
- if (!(flags&FF_LEFT))
- while (--pad >= 0)
- putc((flags&FF_ZERO) ? '0' : ' ', f);
- while (c = *p++)
- putc(c, f);
- if ((flags&FF_LEFT))
- while (--pad >= 0)
- putc(' ', f);
- pos += (len < width) ? width : len;
- }
- } else { /* ordinary character */
- putc(c, f);
- pos ++;
- }
- return pos;
- }
-
-