Fixed a buffer overflow if there is given a not null terminated string with a precision parameter.

Reduced some overhead for outputing strings.
Added handling of the precision parameter for counted strings.
Return the outputed character count (or an error) in __vf(w)printf.

svn path=/trunk/; revision=3492
This commit is contained in:
Hartmut Birr 2002-09-13 18:48:42 +00:00
parent 3f316cde99
commit eec75375c4
2 changed files with 661 additions and 252 deletions

View file

@ -20,6 +20,9 @@ vfprintf(FILE *f, const char *fmt, va_list ap)
int len; int len;
char localbuf[BUFSIZ]; char localbuf[BUFSIZ];
#if 0
__fileno_lock(fileno(f));
#endif
if (f->_flag & _IONBF) if (f->_flag & _IONBF)
{ {
f->_flag &= ~_IONBF; f->_flag &= ~_IONBF;
@ -34,6 +37,9 @@ vfprintf(FILE *f, const char *fmt, va_list ap)
} }
else else
len = __vfprintf(f,fmt, ap); len = __vfprintf(f,fmt, ap);
#if 0
__fileno_unlock(fileno(f));
#endif
return (ferror(f) ? EOF : len); return (ferror(f) ? EOF : len);
} }
@ -91,18 +97,18 @@ static int do_div(long long *n,int base)
} }
static void number(FILE * f, long long num, int base, int size, int precision ,int type) static int number(FILE * f, long long num, int base, int size, int precision ,int type)
{ {
char c,sign,tmp[66]; char c,sign,tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
int i; int i, done = 0;
if (type & LARGE) if (type & LARGE)
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (type & LEFT) if (type & LEFT)
type &= ~ZEROPAD; type &= ~ZEROPAD;
if (base < 2 || base > 36) if (base < 2 || base > 36)
return; return done;
c = (type & ZEROPAD) ? '0' : ' '; c = (type & ZEROPAD) ? '0' : ' ';
sign = 0; sign = 0;
if (type & SIGN) { if (type & SIGN) {
@ -134,32 +140,62 @@ static void number(FILE * f, long long num, int base, int size, int precision ,i
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putc(' ',f); {
if (putc(' ',f) == EOF)
return -1;
done++;
}
if (sign) if (sign)
putc(sign,f); {
if (putc(sign,f) == EOF)
return -1;
done++;
}
if (type & SPECIAL) { if (type & SPECIAL) {
if (base==8) { if (base==8) {
putc('0',f); if (putc('0',f) == EOF)
return -1;
done++;
} }
else if (base==16) { else if (base==16) {
putc('0', f); if (putc('0', f) == EOF)
putc(digits[33],f); return -1;
done++;
if (putc(digits[33],f) == EOF)
return -1;
done++;
} }
} }
if (!(type & LEFT)) if (!(type & LEFT))
while (size-- > 0) while (size-- > 0)
putc(c,f); {
if (putc(c,f) == EOF)
return -1;
done++;
}
while (i < precision--) while (i < precision--)
putc('0', f); {
if (putc('0', f) == EOF)
return -1;
done++;
}
while (i-- > 0) while (i-- > 0)
putc(tmp[i],f); {
if (putc(tmp[i],f) == EOF)
return -1;
done++;
}
while (size-- > 0) while (size-- > 0)
putc(' ', f); {
return; if (putc(' ', f) == EOF)
return -1;
done++;
}
return done;
} }
static void numberf(FILE * f, double __n, char exp_sign, int size, int precision, int type) static int numberf(FILE * f, double __n, char exp_sign, int size, int precision, int type)
{ {
double exponent = 0.0; double exponent = 0.0;
double e; double e;
@ -176,6 +212,7 @@ static void numberf(FILE * f, double __n, char exp_sign, int size, int precisio
char sign; char sign;
char c; char c;
char ro = 0; char ro = 0;
int result, done = 0;
double_t *n = (double_t *)&__n; double_t *n = (double_t *)&__n;
@ -197,16 +234,24 @@ static void numberf(FILE * f, double __n, char exp_sign, int size, int precisio
else if ( frac < -0.5 ) else if ( frac < -0.5 )
e--; e--;
numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type); result = numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type);
putc( exp_sign,f); if (result < 0)
return -1;
done += result;
if (putc( exp_sign,f) == EOF)
return -1;
done++;
size--; size--;
ie = (long)e; ie = (long)e;
type = LEFT | PLUS; type = LEFT | PLUS;
if ( ie < 0 ) if ( ie < 0 )
type |= SIGN; type |= SIGN;
number(f,ie, 10,2, 2,type ); result = number(f,ie, 10,2, 2,type );
return; if (result < 0)
return -1;
done += result;
return done;
} }
if ( exp_sign == 'f' ) { if ( exp_sign == 'f' ) {
@ -293,19 +338,35 @@ static void numberf(FILE * f, double __n, char exp_sign, int size, int precisio
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putc(' ',f); {
if (putc(' ',f) == EOF)
return -1;
done++;
}
if (sign) if (sign)
putc( sign,f); {
if (putc( sign,f) == EOF)
return -1;
done++;
}
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putc(' ',f); {
if (putc(' ',f) == EOF)
return -1;
done++;
}
if (type & SPECIAL) { if (type & SPECIAL) {
} }
if (!(type & LEFT)) if (!(type & LEFT))
while (size-- > 0) while (size-- > 0)
putc(c,f); {
if (putc(c,f) == EOF)
return -1;
done++;
}
tmp = buf; tmp = buf;
if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
@ -319,14 +380,23 @@ static void numberf(FILE * f, double __n, char exp_sign, int size, int precisio
// while (i < precision--) // while (i < precision--)
// putc('0', f); // putc('0', f);
while (i-- > 0) while (i-- > 0)
putc(tmp[i],f); {
if (putc(tmp[i],f) == EOF)
return -1;
done++;
}
while (size-- > 0) while (size-- > 0)
putc(' ', f); {
if (putc(' ', f) == EOF)
return -1;
done++;
} }
} }
return done;
}
static void numberfl(FILE * f, long double __n, char exp_sign, int size, int precision, int type) static int numberfl(FILE * f, long double __n, char exp_sign, int size, int precision, int type)
{ {
long double exponent = 0.0; long double exponent = 0.0;
long double e; long double e;
@ -344,6 +414,8 @@ static void numberfl(FILE * f, long double __n, char exp_sign, int size, int pr
char c; char c;
char ro = 0; char ro = 0;
int result, done = 0;
long_double_t *n = (long_double_t *)&__n; long_double_t *n = (long_double_t *)&__n;
if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) {
@ -364,16 +436,24 @@ static void numberfl(FILE * f, long double __n, char exp_sign, int size, int pr
else if ( frac < -0.5 ) else if ( frac < -0.5 )
e--; e--;
numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type);
putc( exp_sign,f); if (result < 0)
return -1;
done += result;
if (putc( exp_sign,f) == EOF)
return -1;
done++;
size--; size--;
ie = (long)e; ie = (long)e;
type = LEFT | PLUS; type = LEFT | PLUS;
if ( ie < 0 ) if ( ie < 0 )
type |= SIGN; type |= SIGN;
number(f,ie, 10,2, 2,type ); result = number(f,ie, 10,2, 2,type );
return; if (result < 0)
return -1;
done += result;
return done;
} }
if ( exp_sign == 'f' ) { if ( exp_sign == 'f' ) {
@ -461,20 +541,35 @@ static void numberfl(FILE * f, long double __n, char exp_sign, int size, int pr
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putc(' ',f); {
if (putc(' ',f) == EOF)
return -1;
done++;
}
if (sign) if (sign)
putc(sign,f); {
if (putc(sign,f) == EOF)
return -1;
done++;
}
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putc(' ',f); {
if (putc(' ',f) == EOF)
return -1;
done++;
}
if (type & SPECIAL) { if (type & SPECIAL) {
} }
if (!(type & LEFT)) if (!(type & LEFT))
while (size-- > 0) while (size-- > 0)
putc(c,f); {
if (putc(c,f) == EOF)
return -1;
done++;
}
tmp = buf; tmp = buf;
if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
j = 0; j = 0;
@ -487,12 +582,108 @@ static void numberfl(FILE * f, long double __n, char exp_sign, int size, int pr
// while (i < precision--) // while (i < precision--)
// putc( '0', f); // putc( '0', f);
while (i-- > 0) while (i-- > 0)
putc(tmp[i],f); {
while (size-- > 0) if ( putc(tmp[i],f) == EOF)
putc(' ', f); return -1;
done++;
} }
while (size-- > 0)
{
if (putc(' ', f) == EOF)
return -1;
done++;
}
}
return done;
} }
static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags)
{
int i, done = 0;
if (s == NULL)
{
s = "<NULL>";
len = 6;
}
else
{
if (len == -1)
{
len = 0;
while (s[len] && (unsigned int)len < (unsigned int)precision)
len++;
}
else
{
if ((unsigned int)len > (unsigned int)precision)
len = precision;
}
}
if (!(flags & LEFT))
while (len < field_width--)
{
if (putc(' ', f) == EOF)
return -1;
done++;
}
for (i = 0; i < len; ++i)
{
if (putc(*s++, f) == EOF)
return -1;
done++;
}
while (len < field_width--)
{
if (putc(' ', f) == EOF)
return -1;
done++;
}
return done;
}
static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags)
{
int i, done = 0;
if (sw == NULL)
{
sw = L"<NULL>";
len = 6;
}
else
{
if (len == -1)
{
len = 0;
while (sw[len] && (unsigned int)len < (unsigned int)precision)
len++;
}
else
{
if ((unsigned int)len > (unsigned int)precision)
len = precision;
}
}
if (!(flags & LEFT))
while (len < field_width--)
{
if (putc(' ', f) == EOF)
return -1;
done++;
}
for (i = 0; i < len; ++i)
{
if (putc((unsigned char)(*sw++), f) == EOF)
return -1;
done++;
}
while (len < field_width--)
{
if (putc(' ', f) == EOF)
return -1;
done++;
}
return done;
}
int __vfprintf(FILE *f, const char *fmt, va_list args) int __vfprintf(FILE *f, const char *fmt, va_list args)
{ {
@ -503,6 +694,7 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
double _double; double _double;
const char *s; const char *s;
const short int* sw; const short int* sw;
int result, done = 0;
int flags; /* flags to number() */ int flags; /* flags to number() */
@ -513,7 +705,9 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
for (; *fmt ; ++fmt) { for (; *fmt ; ++fmt) {
if (*fmt != '%') { if (*fmt != '%') {
putc(*fmt,f); if (putc(*fmt,f) == EOF)
return -1;
done++;
continue; continue;
} }
@ -597,101 +791,87 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
case 'c': case 'c':
if (!(flags & LEFT)) if (!(flags & LEFT))
while (--field_width > 0) while (--field_width > 0)
putc(' ', f); {
if (putc(' ', f) == EOF)
return -1;
done++;
}
if (qualifier == 'l' || qualifier == 'w') if (qualifier == 'l' || qualifier == 'w')
putc((unsigned char)(wchar_t) va_arg(args, int), f); {
if (putc((unsigned char)(wchar_t) va_arg(args, int), f) == EOF)
return -1;
done++;
}
else else
putc((unsigned char) va_arg(args, int), f); {
if (putc((unsigned char) va_arg(args, int), f) == EOF)
return -1;
done++;
}
while (--field_width > 0) while (--field_width > 0)
putc(' ', f); {
if (putc(' ', f) == EOF)
return -1;
done++;
}
continue; continue;
case 'C': case 'C':
if (!(flags & LEFT)) if (!(flags & LEFT))
while (--field_width > 0) while (--field_width > 0)
putc(' ', f); {
if (putc(' ', f) == EOF)
return -1;
done++;
}
if (qualifier == 'h') if (qualifier == 'h')
putc((unsigned char) va_arg(args, int), f); {
if (putc((unsigned char) va_arg(args, int), f) == EOF)
return -1;
done++;
}
else else
putc((unsigned char)(wchar_t) va_arg(args, int), f); {
if (putc((unsigned char)(wchar_t) va_arg(args, int), f) == EOF)
return -1;
done++;
}
while (--field_width > 0) while (--field_width > 0)
putc(' ', f); {
if (putc(' ', f) == EOF)
return -1;
done++;
}
continue; continue;
case 's': case 's':
if (qualifier == 'l' || qualifier == 'w') { if (qualifier == 'l' || qualifier == 'w') {
/* print unicode string */ /* print unicode string */
sw = va_arg(args, wchar_t *); sw = va_arg(args, wchar_t *);
if (sw == NULL) result = stringw(f, sw, -1, field_width, precision, flags);
sw = L"<NULL>";
len = wcslen (sw);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putc(' ', f);
for (i = 0; i < len; ++i)
putc((unsigned char)(*sw++), f);
while (len < field_width--)
putc(' ', f);
} else { } else {
/* print ascii string */ /* print ascii string */
s = va_arg(args, char *); s = va_arg(args, char *);
if (s == NULL) result = string(f, s, -1, field_width, precision, flags);
s = "<NULL>";
len = strlen (s);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putc(' ', f);
for (i = 0; i < len; ++i)
putc(*s++, f);
while (len < field_width--)
putc(' ', f);
} }
if (result < 0)
return -1;
done += result;
continue; continue;
case 'S': case 'S':
if (qualifier == 'h') { if (qualifier == 'h') {
/* print ascii string */ /* print ascii string */
s = va_arg(args, char *); s = va_arg(args, char *);
if (s == NULL) result = string(f, s, -1, field_width, precision, flags);
s = "<NULL>";
len = strlen (s);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putc(' ', f);
for (i = 0; i < len; ++i)
putc(*s++, f);
while (len < field_width--)
putc(' ', f);
} else { } else {
/* print unicode string */ /* print unicode string */
sw = va_arg(args, wchar_t *); sw = va_arg(args, wchar_t *);
if (sw == NULL) result = stringw(f, sw, -1, field_width, precision, flags);
sw = L"<NULL>";
len = wcslen (sw);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putc(' ', f);
for (i = 0; i < len; ++i)
putc((unsigned char)(*sw++), f);
while (len < field_width--)
putc(' ', f);
} }
if (result < 0)
return -1;
done += result;
continue; continue;
case 'Z': case 'Z':
@ -699,25 +879,28 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
/* print counted unicode string */ /* print counted unicode string */
PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) { if ((pus == NULL) || (pus->Buffer == NULL)) {
s = "<NULL>"; sw = NULL;
while ((*s) != 0) len = -1;
putc(*s++, f);
} else { } else {
for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++) sw = pus->Buffer;
putc((unsigned char)(pus->Buffer[i]), f); len = pus->Length / sizeof(WCHAR);
} }
result = stringw(f, sw, len, field_width, precision, flags);
} else { } else {
/* print counted ascii string */ /* print counted ascii string */
PANSI_STRING pus = va_arg(args, PANSI_STRING); PANSI_STRING pas = va_arg(args, PANSI_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) { if ((pas == NULL) || (pas->Buffer == NULL)) {
s = "<NULL>"; s = NULL;
while ((*s) != 0) len = -1;
putc(*s++, f);
} else { } else {
for (i = 0; pus->Buffer[i] && i < pus->Length; i++) s = pas->Buffer;
putc(pus->Buffer[i], f); len = pas->Length;
} }
result = string(f, s, -1, field_width, precision, flags);
} }
if (result < 0)
return -1;
done += result;
continue; continue;
case 'e': case 'e':
@ -732,7 +915,9 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
s = "Nan"; s = "Nan";
len = 3; len = 3;
while ( len > 0 ) { while ( len > 0 ) {
putc(*s++,f); if (putc(*s++,f) == EOF)
return -1;
done++;
len --; len --;
} }
} }
@ -740,7 +925,9 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
s = "-Inf"; s = "-Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putc(*s++,f); if (putc(*s++,f) == EOF)
return -1;
done++;
len --; len --;
} }
} }
@ -748,13 +935,18 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
s = "+Inf"; s = "+Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putc(*s++,f); if (putc(*s++,f) == EOF)
return -1;
done++;
len --; len --;
} }
} else { } else {
if ( precision == -1 ) if ( precision == -1 )
precision = 6; precision = 6;
numberfl(f,_ldouble,*fmt,field_width,precision,flags); result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
if (result < 0)
return -1;
done += result;
} }
} else { } else {
_double = (double)va_arg(args, double); _double = (double)va_arg(args, double);
@ -763,27 +955,36 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
s = "Nan"; s = "Nan";
len = 3; len = 3;
while ( len > 0 ) { while ( len > 0 ) {
putc(*s++,f); if (putc(*s++,f) == EOF)
return -1;
done++;
len --; len --;
} }
} else if ( _isinf(_double) < 0 ) { } else if ( _isinf(_double) < 0 ) {
s = "-Inf"; s = "-Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putc(*s++,f); if (putc(*s++,f) == EOF)
return -1;
done++;
len --; len --;
} }
} else if ( _isinf(_double) > 0 ) { } else if ( _isinf(_double) > 0 ) {
s = "+Inf"; s = "+Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putc(*s++,f); if (putc(*s++,f) == EOF)
return -1;
done++;
len --; len --;
} }
} else { } else {
if ( precision == -1 ) if ( precision == -1 )
precision = 6; precision = 6;
numberf(f,_double,*fmt,field_width,precision,flags); result = numberf(f,_double,*fmt,field_width,precision,flags);
if (result < 0)
return -1;
done += result;
} }
} }
continue; continue;
@ -793,9 +994,12 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
field_width = 2*sizeof(void *); field_width = 2*sizeof(void *);
flags |= ZEROPAD; flags |= ZEROPAD;
} }
number(f, result = number(f,
(unsigned long) va_arg(args, void *), 16, (unsigned long) va_arg(args, void *), 16,
field_width, precision, flags); field_width, precision, flags);
if (result < 0)
return -1;
done += result;
continue; continue;
case 'n': case 'n':
@ -831,9 +1035,17 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
default: default:
if (*fmt != '%') if (*fmt != '%')
putc('%', f); {
if (putc('%', f) == EOF)
return -1;
done++;
}
if (*fmt) if (*fmt)
putc(*fmt, f); {
if (putc(*fmt, f) == EOF)
return -1;
done++;
}
else else
--fmt; --fmt;
continue; continue;
@ -853,10 +1065,13 @@ int __vfprintf(FILE *f, const char *fmt, va_list args)
num = va_arg(args, int); num = va_arg(args, int);
else else
num = va_arg(args, unsigned int); num = va_arg(args, unsigned int);
number(f, num, base, field_width, precision, flags); result = number(f, num, base, field_width, precision, flags);
if (result < 0)
return -1;
done += result;
} }
//putc('\0',f); //putc('\0',f);
return 0; return done;
} }
/* EOF */ /* EOF */

View file

@ -20,6 +20,9 @@ vfwprintf(FILE *f, const wchar_t *fmt, va_list ap)
int len; int len;
wchar_t localbuf[BUFSIZ]; wchar_t localbuf[BUFSIZ];
#if 0
__fileno_lock(fileno(f));
#endif
if (f->_flag & _IONBF) { if (f->_flag & _IONBF) {
f->_flag &= ~_IONBF; f->_flag &= ~_IONBF;
f->_ptr = f->_base = (char *)localbuf; f->_ptr = f->_base = (char *)localbuf;
@ -32,7 +35,9 @@ vfwprintf(FILE *f, const wchar_t *fmt, va_list ap)
f->_cnt = 0; f->_cnt = 0;
} else } else
len = __vfwprintf(f,fmt,ap); len = __vfwprintf(f,fmt,ap);
#if 0
__fileno_unlock(fileno(f));
#endif
return (ferror(f) ? EOF : len); return (ferror(f) ? EOF : len);
} }
@ -91,18 +96,18 @@ static int do_div(long long *n,int base)
} }
static void number(FILE * f, long long num, int base, int size, int precision ,int type) static int number(FILE * f, long long num, int base, int size, int precision ,int type)
{ {
wchar_t c,sign,tmp[66]; wchar_t c,sign,tmp[66];
const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz"; const wchar_t *digits=L"0123456789abcdefghijklmnopqrstuvwxyz";
int i; int i, done = 0;
if (type & LARGE) if (type & LARGE)
digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (type & LEFT) if (type & LEFT)
type &= ~ZEROPAD; type &= ~ZEROPAD;
if (base < 2 || base > 36) if (base < 2 || base > 36)
return; return done;
c = (type & ZEROPAD) ? L'0' : L' '; c = (type & ZEROPAD) ? L'0' : L' ';
sign = 0; sign = 0;
if (type & SIGN) { if (type & SIGN) {
@ -134,32 +139,63 @@ static void number(FILE * f, long long num, int base, int size, int precision ,i
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putwc(L' ',f); {
if (putwc(L' ',f) == WEOF)
return -1;
done++;
}
if (sign) if (sign)
putwc(sign,f); {
if (putwc(sign,f) == WEOF)
return -1;
done++;
}
if (type & SPECIAL) { if (type & SPECIAL) {
if (base==8) { if (base==8) {
putwc(L'0',f); if (putwc(L'0',f) == WEOF)
return -1;
done++;
} }
else if (base==16) { else if (base==16) {
putwc(L'0', f); if (putwc(L'0', f) == WEOF)
putwc(digits[33],f); return -1;
done++;
if (putwc(digits[33],f) == WEOF)
return -1;
done++;
} }
} }
if (!(type & LEFT)) if (!(type & LEFT))
while (size-- > 0) while (size-- > 0)
putwc(c,f); {
if (putwc(c,f) == WEOF)
return -1;
done++;
}
while (i < precision--) while (i < precision--)
putwc(L'0', f); {
if (putwc(L'0', f) == WEOF)
return -1;
done++;
}
while (i-- > 0) while (i-- > 0)
putwc(tmp[i],f); {
if (putwc(tmp[i],f) == WEOF)
return -1;
done++;
}
while (size-- > 0) while (size-- > 0)
putwc(L' ', f); {
return; if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
return done;
} }
static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type) static int numberf(FILE * f, double __n, wchar_t exp_sign, int size, int precision, int type)
{ {
double exponent = 0.0; double exponent = 0.0;
double e; double e;
@ -176,6 +212,7 @@ static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int preci
wchar_t sign; wchar_t sign;
wchar_t c; wchar_t c;
char ro = 0; char ro = 0;
int result, done = 0;
double_t *n = (double_t *)&__n; double_t *n = (double_t *)&__n;
@ -197,16 +234,24 @@ static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int preci
else if ( frac < -0.5 ) else if ( frac < -0.5 )
e--; e--;
numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type); result = numberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type);
putwc( exp_sign,f); if (result < 0)
return -1;
done += result;
if (putwc( exp_sign,f) == WEOF)
return -1;
done++;
size--; size--;
ie = (long)e; ie = (long)e;
type = LEFT | PLUS; type = LEFT | PLUS;
if ( ie < 0 ) if ( ie < 0 )
type |= SIGN; type |= SIGN;
number(f,ie, 10,2, 2,type ); result = number(f,ie, 10,2, 2,type );
return; if (result < 0)
return -1;
done += result;
return done;
} }
if ( exp_sign == 'f' ) { if ( exp_sign == 'f' ) {
@ -293,19 +338,35 @@ static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int preci
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putwc(L' ',f); {
if (putwc(L' ',f) == WEOF)
return -1;
done++;
}
if (sign) if (sign)
putwc( sign,f); {
if (putwc( sign,f) == WEOF)
return -1;
done++;
}
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while(size-->0)
putwc(L' ',f); {
if (putwc(L' ',f) == WEOF)
return -1;
done++;
}
if (type & SPECIAL) { if (type & SPECIAL) {
} }
if (!(type & LEFT)) if (!(type & LEFT))
while (size-- > 0) while (size-- > 0)
putwc(c,f); {
if (putwc(c,f) == WEOF)
return -1;
done++;
}
tmp = buf; tmp = buf;
if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) { if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) {
@ -319,14 +380,23 @@ static void numberf(FILE * f, double __n, wchar_t exp_sign, int size, int preci
// while (i < precision--) // while (i < precision--)
// putwc(L'0', f); // putwc(L'0', f);
while (i-- > 0) while (i-- > 0)
putwc(tmp[i],f); {
if (putwc(tmp[i],f) == WEOF)
return -1;
done++;
}
while (size-- > 0) while (size-- > 0)
putwc(L' ', f); {
if (putwc(L' ', f) == WEOF)
return -1;
done++;
} }
} }
return done;
}
static void numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type) static int numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int precision, int type)
{ {
long double exponent = 0.0; long double exponent = 0.0;
long double e; long double e;
@ -344,6 +414,8 @@ static void numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int
wchar_t c; wchar_t c;
char ro = 0; char ro = 0;
int result, done = 0;
long_double_t *n = (long_double_t *)&__n; long_double_t *n = (long_double_t *)&__n;
if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) {
@ -364,16 +436,24 @@ static void numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int
else if ( frac < -0.5 ) else if ( frac < -0.5 )
e--; e--;
numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); result = numberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type);
putwc( exp_sign,f); if (result < 0)
return -1;
done += result;
if (putwc( exp_sign,f) == WEOF)
return -1;
done++;
size--; size--;
ie = (long)e; ie = (long)e;
type = LEFT | PLUS; type = LEFT | PLUS;
if ( ie < 0 ) if ( ie < 0 )
type |= SIGN; type |= SIGN;
number(f,ie, 10,2, 2,type ); result = number(f,ie, 10,2, 2,type );
return; if (result < 0)
return -1;
done += result;
return done;
} }
if ( exp_sign == L'f' ) { if ( exp_sign == L'f' ) {
@ -486,12 +566,108 @@ static void numberfl(FILE * f, long double __n, wchar_t exp_sign, int size, int
// while (i < precision--) // while (i < precision--)
// putc( '0', f); // putc( '0', f);
while (i-- > 0) while (i-- > 0)
putwc(tmp[i],f); {
while (size-- > 0) if (putwc(tmp[i],f) == WEOF)
putwc(L' ', f); return -1;
done++;
} }
while (size-- > 0)
{
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
}
return done;
} }
static int string(FILE *f, const char* s, int len, int field_width, int precision, int flags)
{
int i, done = 0;
if (s == NULL)
{
s = "<NULL>";
len = 6;
}
else
{
if (len == -1)
{
len = 0;
while (s[len] && (unsigned int)len < (unsigned int)precision)
len++;
}
else
{
if ((unsigned int)len > (unsigned int)precision)
len = precision;
}
}
if (!(flags & LEFT))
while (len < field_width--)
{
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
for (i = 0; i < len; ++i)
{
if (putwc(*s++, f) == WEOF)
return -1;
done++;
}
while (len < field_width--)
{
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
return done;
}
static int stringw(FILE *f, const wchar_t* sw, int len, int field_width, int precision, int flags)
{
int i, done = 0;
if (sw == NULL)
{
sw = L"<NULL>";
len = 6;
}
else
{
if (len == -1)
{
len = 0;
while (sw[len] && (unsigned int)len < (unsigned int)precision)
len++;
}
else
{
if ((unsigned int)len > (unsigned int)precision)
len = precision;
}
}
if (!(flags & LEFT))
while (len < field_width--)
{
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
for (i = 0; i < len; ++i)
{
if (putwc(*sw++, f) == WEOF)
return -1;
done++;
}
while (len < field_width--)
{
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
return done;
}
int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args) int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
{ {
@ -502,6 +678,7 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
double _double; double _double;
const char *s; const char *s;
const wchar_t* sw; const wchar_t* sw;
int result, done = 0;
int flags; /* flags to number() */ int flags; /* flags to number() */
@ -512,7 +689,9 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
for (; *fmt ; ++fmt) { for (; *fmt ; ++fmt) {
if (*fmt != L'%') { if (*fmt != L'%') {
putwc(*fmt,f); if (putwc(*fmt,f) == WEOF)
return -1;
done++;
continue; continue;
} }
@ -596,130 +775,113 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
case L'c': /* finished */ case L'c': /* finished */
if (!(flags & LEFT)) if (!(flags & LEFT))
while (--field_width > 0) while (--field_width > 0)
putwc(L' ', f); {
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
if (qualifier == L'h') if (qualifier == L'h')
putwc((wchar_t) va_arg(args, int), f); {
if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
return -1;
}
else else
putwc((wchar_t) va_arg(args, int), f); {
if (putwc((wchar_t) va_arg(args, int), f) == WEOF)
return -1;
}
done++;
while (--field_width > 0) while (--field_width > 0)
putwc(L' ', f); {
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
continue; continue;
case L'C': /* finished */ case L'C': /* finished */
if (!(flags & LEFT)) if (!(flags & LEFT))
while (--field_width > 0) while (--field_width > 0)
putwc(L' ', f); {
if (putwc(L' ', f) == WEOF)
return -1;
done;
}
if (qualifier == L'l' || qualifier == L'w') if (qualifier == L'l' || qualifier == L'w')
putwc((unsigned char) va_arg(args, int), f); {
if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
return -1;
}
else else
putwc((unsigned char) va_arg(args, int), f); {
if (putwc((unsigned char) va_arg(args, int), f) == WEOF)
return -1;
}
done++;
while (--field_width > 0) while (--field_width > 0)
putwc(L' ', f); {
if (putwc(L' ', f) == WEOF)
return -1;
done++;
}
continue; continue;
case L's': /* finished */ case L's': /* finished */
if (qualifier == L'h') { if (qualifier == L'h') {
/* print ascii string */ /* print ascii string */
s = va_arg(args, char *); s = va_arg(args, char *);
if (s == NULL) result = string(f, s, -1, field_width, precision, flags);
s = "<NULL>";
len = strlen (s);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putwc(L' ', f);
for (i = 0; i < len; ++i)
putwc((wchar_t)(*s++), f);
while (len < field_width--)
putwc(L' ', f);
} else { } else {
/* print unicode string */ /* print unicode string */
sw = va_arg(args, wchar_t *); sw = va_arg(args, wchar_t *);
if (sw == NULL) result = stringw(f, sw, -1, field_width, precision, flags);
sw = L"<NULL>";
len = wcslen (sw);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putwc(L' ', f);
for (i = 0; i < len; ++i)
putwc(*sw++, f);
while (len < field_width--)
putwc(L' ', f);
} }
if (result < 0)
return -1;
done += result;
continue; continue;
case L'S': case L'S':
if (qualifier == L'l' || qualifier == L'w') { if (qualifier == L'l' || qualifier == L'w') {
/* print unicode string */ /* print unicode string */
sw = va_arg(args, wchar_t *); sw = va_arg(args, wchar_t *);
if (sw == NULL) result = stringw(f, sw, -1, field_width, precision, flags);
sw = L"<NULL>";
len = wcslen (sw);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putwc(L' ', f);
for (i = 0; i < len; ++i)
putwc(*sw++, f);
while (len < field_width--)
putwc(L' ', f);
} else { } else {
/* print ascii string */ /* print ascii string */
s = va_arg(args, char *); s = va_arg(args, char *);
if (s == NULL)
s = "<NULL>";
len = strlen (s);
if ((unsigned int)len > (unsigned int)precision)
len = precision;
if (!(flags & LEFT))
while (len < field_width--)
putwc(L' ', f);
for (i = 0; i < len; ++i)
putwc((wchar_t)(*s++), f);
while (len < field_width--)
putwc(L' ', f);
} }
if (result < 0)
return -1;
done += result;
continue; continue;
#if 0
case L'Z': /* finished */ case L'Z': /* finished */
if (qualifier == L'w') { if (qualifier == L'w') {
/* print counted unicode string */ /* print counted unicode string */
PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
if ((pus == NULL) || (pus->Buffer)) { if ((pus == NULL) || (pus->Buffer)) {
sw = L"<NULL>"; sw = NULL;
while ((*sw) != 0) len = -1;
putwc(*sw++, f);
} else { } else {
for (i = 0; pus->Buffer[i] && i < pus->Length; i++) sw = pus->Buffer;
putwc(pus->Buffer[i], f);
} }
result = stringw(f, sw, len, field_width, precision, flags);
} else { } else {
/* print counted ascii string */ /* print counted ascii string */
PANSI_STRING pus = va_arg(args, PANSI_STRING); PANSI_STRING pus = va_arg(args, PANSI_STRING);
if ((pus == NULL) || (pus->Buffer)) { if ((pus == NULL) || (pus->Buffer)) {
sw = L"<NULL>"; s = NULL;
while ((*sw) != 0) len = -1;
putwc(*sw++, f);
} else { } else {
for (i = 0; pus->Buffer[i] && i < pus->Length; i++) s = pus->Buffer;
putwc((wchar_t)pus->Buffer[i], f); len = pus->Length;
} }
result = string(f, s, len, field_width, precision, flags);
} }
if (result < 0)
return -1;
done += result;
continue; continue;
#endif
case L'e': /* finished */ case L'e': /* finished */
case L'E': case L'E':
@ -733,7 +895,9 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
sw = L"Nan"; sw = L"Nan";
len = 3; len = 3;
while ( len > 0 ) { while ( len > 0 ) {
putwc(*sw++,f); if (putwc(*sw++,f) == WEOF)
return -1;
done++;
len --; len --;
} }
} }
@ -741,7 +905,9 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
sw = L"-Inf"; sw = L"-Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putwc(*sw++,f); if (putwc(*sw++,f) == WEOF)
return -1;
done++;
len --; len --;
} }
} }
@ -749,13 +915,18 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
sw = L"+Inf"; sw = L"+Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putwc(*sw++,f); if (putwc(*sw++,f) == WEOF)
return -1;
done++;
len --; len --;
} }
} else { } else {
if ( precision == -1 ) if ( precision == -1 )
precision = 6; precision = 6;
numberfl(f,_ldouble,*fmt,field_width,precision,flags); result = numberfl(f,_ldouble,*fmt,field_width,precision,flags);
if (result < 0)
return -1;
done += result;
} }
} else { } else {
_double = (double)va_arg(args, double); _double = (double)va_arg(args, double);
@ -764,27 +935,36 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
sw = L"Nan"; sw = L"Nan";
len = 3; len = 3;
while ( len > 0 ) { while ( len > 0 ) {
putwc(*sw++,f); if (putwc(*sw++,f) == WEOF)
return -1;
done++;
len --; len --;
} }
} else if ( _isinf(_double) < 0 ) { } else if ( _isinf(_double) < 0 ) {
sw = L"-Inf"; sw = L"-Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putwc(*sw++,f); if (putwc(*sw++,f) == WEOF)
return -1;
done++;
len --; len --;
} }
} else if ( _isinf(_double) > 0 ) { } else if ( _isinf(_double) > 0 ) {
sw = L"+Inf"; sw = L"+Inf";
len = 4; len = 4;
while ( len > 0 ) { while ( len > 0 ) {
putwc(*sw++,f); if (putwc(*sw++,f) == WEOF)
return -1;
done++;
len --; len --;
} }
} else { } else {
if ( precision == -1 ) if ( precision == -1 )
precision = 6; precision = 6;
numberf(f,_double,*fmt,field_width,precision,flags); result = numberf(f,_double,*fmt,field_width,precision,flags);
if (result < 0)
return -1;
done += result;
} }
} }
continue; continue;
@ -794,9 +974,12 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
field_width = 2*sizeof(void *); field_width = 2*sizeof(void *);
flags |= ZEROPAD; flags |= ZEROPAD;
} }
number(f, result = number(f,
(unsigned long) va_arg(args, void *), 16, (unsigned long) va_arg(args, void *), 16,
field_width, precision, flags); field_width, precision, flags);
if (result < 0)
return -1;
done += result;
continue; continue;
case L'n': case L'n':
@ -832,9 +1015,17 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
default: default:
if (*fmt != L'%') if (*fmt != L'%')
putwc(L'%', f); {
if (putwc(L'%', f) == WEOF)
return -1;
done++;
}
if (*fmt) if (*fmt)
putwc(*fmt, f); {
if (putwc(*fmt, f) == WEOF)
return -1;
done++;
}
else else
--fmt; --fmt;
continue; continue;
@ -854,10 +1045,13 @@ int __vfwprintf(FILE *f, const wchar_t *fmt, va_list args)
num = va_arg(args, int); num = va_arg(args, int);
else else
num = va_arg(args, unsigned int); num = va_arg(args, unsigned int);
number(f, num, base, field_width, precision, flags); result = number(f, num, base, field_width, precision, flags);
if (result < 0)
return -1;
done += result;
} }
//putwc(L'\0',f); //putwc(L'\0',f);
return 0; return done;
} }
/* EOF */ /* EOF */