home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
pdksh-4.9-src.tgz
/
tar.out
/
contrib
/
pdksh
/
std
/
stdc
/
vprintf.c
< prev
Wrap
C/C++ Source or Header
|
1996-09-28
|
5KB
|
243 lines
#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;
}