-/* $Id: sprintf.c,v 1.8 2002/09/08 10:23:07 chorns Exp $
+/* $Id: sprintf.c,v 1.9 2002/09/12 17:50:42 guido Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROGRAMMERS: David Welch
* Eric Kohl
*
- * TODO:
- * - Implement maximum length (cnt) in _vsnprintf().
*/
/*
static char *
-number (char * str, long long num, int base, int size, int precision, int type)
+number(char * buf, char * end, long long num, int base, int size, int precision, int type)
{
char c,sign,tmp[66];
- const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ const char *digits;
+ const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i;
- if (type & LARGE)
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ digits = (type & LARGE) ? large_digits : small_digits;
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return 0;
-
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
-
if (type & SIGN) {
if (num < 0) {
sign = '-';
size--;
}
}
-
if (type & SPECIAL) {
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
-
i = 0;
if (num == 0)
tmp[i++]='0';
if (i > precision)
precision = i;
size -= precision;
- if (!(type&(ZEROPAD+LEFT)))
- while(size-->0)
- *str++ = ' ';
- if (sign)
- *str++ = sign;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
if (type & SPECIAL) {
if (base==8) {
- *str++ = '0';
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
} else if (base==16) {
- *str++ = '0';
- *str++ = digits[33];
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
}
}
- if (!(type & LEFT))
- while (size-- > 0)
- *str++ = c;
- while (i < precision--)
- *str++ = '0';
- while (i-- > 0)
- *str++ = tmp[i];
- while (size-- > 0)
- *str++ = ' ';
- return str;
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
}
int len;
unsigned long long num;
int i, base;
- char * str;
+ char *str, *end;
const char *s;
const wchar_t *sw;
number of chars for from string */
int qualifier; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */
- for (str=buf ; *fmt ; ++fmt) {
+ str = buf;
+ end = buf + cnt - 1;
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ cnt = end - buf + 1;
+ }
+
+ for ( ; *fmt ; ++fmt) {
if (*fmt != '%') {
- *str++ = *fmt;
+ if (str <= end)
+ *str = *fmt;
+ ++str;
continue;
}
switch (*fmt) {
case 'c': /* finished */
if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = ' ';
- if (qualifier == 'l' || qualifier == 'w')
- *str++ =
- (unsigned char)(wchar_t) va_arg(args, int);
- else
- *str++ = (unsigned char) va_arg(args, int);
- while (--field_width > 0)
- *str++ = ' ';
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ if (qualifier == 'l' || qualifier == 'w') {
+ if (str <= end)
+ *str = (unsigned char)(wchar_t) va_arg(args, int);
+ ++str;
+ } else {
+ if (str <= end)
+ *str = (unsigned char) va_arg(args, int);
+ ++str;
+ }
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
continue;
case 'C': /* finished */
if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = ' ';
- if (qualifier == 'h')
- *str++ = (unsigned char) va_arg(args, int);
- else
- *str++ =
- (unsigned char)(wchar_t) va_arg(args, int);
- while (--field_width > 0)
- *str++ = ' ';
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ if (qualifier == 'h') {
+ if (str <= end)
+ *str = (unsigned char) va_arg(args, int);
+ ++str;
+ } else {
+ if (str <= end)
+ *str = (unsigned char)(wchar_t) va_arg(args, int);
+ ++str;
+ }
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
continue;
case 's': /* finished */
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = (unsigned char)(*sw++);
- while (len < field_width--)
- *str++ = ' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = (unsigned char)(*sw);
+ ++str;
+ ++sw;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
} else {
/* print ascii string */
s = va_arg(args, char *);
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = *s++;
- while (len < field_width--)
- *str++ = ' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
}
continue;
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = *s++;
- while (len < field_width--)
- *str++ = ' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
} else {
/* print unicode string */
sw = va_arg(args, wchar_t *);
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = (unsigned char)(*sw++);
- while (len < field_width--)
- *str++ = ' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = (unsigned char)(*sw);
+ ++str;
+ ++sw;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = ' ';
+ ++str;
+ }
}
continue;
PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
s = "<NULL>";
- while ((*s) != 0)
- *str++ = *s++;
+ while ((*s) != 0) {
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
+ }
} else {
- for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++)
- *str++ = (unsigned char)(pus->Buffer[i]);
+ for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++) {
+ if (str <= end)
+ *str = (unsigned char)(pus->Buffer[i]);
+ ++str;
+ }
}
} else {
/* print counted ascii string */
PANSI_STRING pus = va_arg(args, PANSI_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
s = "<NULL>";
- while ((*s) != 0)
- *str++ = *s++;
+ while ((*s) != 0) {
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
+ }
} else {
- for (i = 0; pus->Buffer[i] && i < pus->Length; i++)
- *str++ = pus->Buffer[i];
+ for (i = 0; pus->Buffer[i] && i < pus->Length; i++) {
+ if (str <= end)
+ *str = pus->Buffer[i];
+ ++str;
+ }
}
}
continue;
field_width = 2 * sizeof(void *);
flags |= ZEROPAD;
}
- str = number(str,
+ str = number(str, end,
(unsigned long) va_arg(args, void *), 16,
field_width, precision, flags);
continue;
case 'n':
+ /* FIXME: What does C99 say about the overflow case here? */
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
break;
default:
- if (*fmt != '%')
- *str++ = '%';
- if (*fmt)
- *str++ = *fmt;
- else
+ if (*fmt != '%') {
+ if (str <= end)
+ *str = '%';
+ ++str;
+ }
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else
--fmt;
continue;
}
else
num = va_arg(args, unsigned int);
}
- str = number(str, num, base, field_width, precision, flags);
+ str = number(str, end, num, base, field_width, precision, flags);
}
- *str = '\0';
+ if (str <= end)
+ *str = '\0';
+ else if (cnt > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
return str-buf;
}
-/* $Id: swprintf.c,v 1.10 2002/09/08 10:23:07 chorns Exp $
+/* $Id: swprintf.c,v 1.11 2002/09/12 17:50:42 guido Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* Eric Kohl
*
* TODO:
- * - Implement maximum length (cnt) in _vsnwprintf().
* - Verify the implementation of '%Z'.
*/
static wchar_t *
-number (wchar_t *str, long long num, int base, int size, int precision,
- int type)
+number(wchar_t * buf, wchar_t * end, long long num, int base, int size, int precision, int type)
{
- wchar_t c,sign,tmp[66];
- const wchar_t *digits = L"0123456789abcdefghijklmnopqrstuvwxyz";
- int i;
-
- if (type & LARGE)
- digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (type & LEFT)
- type &= ~ZEROPAD;
- if (base < 2 || base > 36)
- return 0;
-
- c = (type & ZEROPAD) ? L'0' : L' ';
- sign = 0;
-
- if (type & SIGN)
- {
- if (num < 0)
- {
- sign = L'-';
- num = -num;
- size--;
- }
- else if (type & PLUS)
- {
- sign = L'+';
- size--;
- }
- else if (type & SPACE)
- {
- sign = L' ';
- size--;
- }
- }
-
- if (type & SPECIAL)
- {
- if (base == 16)
- size -= 2;
- else if (base == 8)
- size--;
- }
-
- i = 0;
- if (num == 0)
- tmp[i++]='0';
- else while (num != 0)
- tmp[i++] = digits[do_div(num,base)];
- if (i > precision)
- precision = i;
- size -= precision;
- if (!(type&(ZEROPAD+LEFT)))
- while(size-->0)
- *str++ = L' ';
- if (sign)
- *str++ = sign;
- if (type & SPECIAL)
- {
- if (base==8)
- {
- *str++ = L'0';
- }
- else if (base==16)
- {
- *str++ = L'0';
- *str++ = digits[33];
- }
- }
- if (!(type & LEFT))
- while (size-- > 0)
- *str++ = c;
- while (i < precision--)
- *str++ = '0';
- while (i-- > 0)
- *str++ = tmp[i];
- while (size-- > 0)
- *str++ = L' ';
- return str;
+ wchar_t c, sign, tmp[66];
+ const wchar_t *digits;
+ const wchar_t small_digits[] = L"0123456789abcdefghijklmnopqrstuvwxyz";
+ const wchar_t large_digits[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? L'0' : L' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = L'-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = L'+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++] = L'0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = L' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+ if (buf <= end)
+ *buf = L'0';
+ ++buf;
+ } else if (base==16) {
+ if (buf <= end)
+ *buf = L'0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = L'0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = L' ';
+ ++buf;
+ }
+ return buf;
}
int len;
unsigned long long num;
int i, base;
- wchar_t * str;
+ wchar_t * str, * end;
const char *s;
const wchar_t *sw;
number of chars for from string */
int qualifier; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
- for (str=buf ; *fmt ; ++fmt) {
+ str = buf;
+ end = buf + cnt - 1;
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ cnt = end - buf + 1;
+ }
+
+ for ( ; *fmt ; ++fmt) {
if (*fmt != L'%') {
- *str++ = *fmt;
+ if (str <= end)
+ *str = *fmt;
+ ++str;
continue;
}
/* get the precision */
precision = -1;
if (*fmt == L'.') {
- ++fmt;
+ ++fmt;
if (iswdigit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == L'*') {
switch (*fmt) {
case L'c':
if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = L' ';
- if (qualifier == 'h')
- *str++ = (wchar_t) va_arg(args, int);
- else
- *str++ =
- (wchar_t) va_arg(args, int);
- while (--field_width > 0)
- *str++ = L' ';
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ if (qualifier == 'h') {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ } else {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ }
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
continue;
case L'C':
if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = L' ';
- if (qualifier == 'l' || qualifier == 'w')
- *str++ = (wchar_t) va_arg(args, int);
- else
- *str++ = (wchar_t) va_arg(args, int);
- while (--field_width > 0)
- *str++ = L' ';
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ if (qualifier == 'l' || qualifier == 'w') {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ } else {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ }
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
continue;
case L's':
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = (wchar_t)(*s++);
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = (wchar_t)(*s);
+ ++str;
+ ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
} else {
/* print unicode string */
sw = va_arg(args, wchar_t *);
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = *sw++;
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
}
continue;
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = *sw++;
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
} else {
/* print ascii string */
s = va_arg(args, char *);
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = (wchar_t)(*s++);
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = (wchar_t)(*s);
+ ++str;
+ ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
}
continue;
- case 'Z':
+ case L'Z':
if (qualifier == 'h') {
/* print counted ascii string */
PANSI_STRING pus = va_arg(args, PANSI_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
sw = L"<NULL>";
- while ((*sw) != 0)
- *str++ = *sw++;
+ while ((*sw) != 0) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
} else {
- for (i = 0; pus->Buffer[i] && i < pus->Length; i++)
- *str++ = (wchar_t)(pus->Buffer[i]);
+ for (i = 0; pus->Buffer[i] && i < pus->Length; i++) {
+ if (str <= end)
+ *str = (wchar_t)(pus->Buffer[i]);
+ ++str;
+ }
}
} else {
/* print counted unicode string */
PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
sw = L"<NULL>";
- while ((*sw) != 0)
- *str++ = *sw++;
+ while ((*sw) != 0) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
} else {
- for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++)
- *str++ = pus->Buffer[i];
+ for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++) {
+ if (str <= end)
+ *str = pus->Buffer[i];
+ ++str;
+ }
}
}
continue;
field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
- str = number(str,
+ str = number(str, end,
(unsigned long) va_arg(args, void *), 16,
field_width, precision, flags);
continue;
case L'n':
+ /* FIXME: What does C99 say about the overflow case here? */
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
break;
default:
- if (*fmt != L'%')
- *str++ = L'%';
- if (*fmt)
- *str++ = *fmt;
- else
+ if (*fmt != L'%') {
+ if (str <= end)
+ *str = L'%';
+ ++str;
+ }
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else
--fmt;
continue;
}
else
num = va_arg(args, unsigned int);
}
- str = number(str, num, base, field_width, precision, flags);
+ str = number(str, end, num, base, field_width, precision, flags);
}
- *str = L'\0';
+ if (str <= end)
+ *str = L'\0';
+ else if (cnt > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = L'\0';
return str-buf;
}
-/* $Id: sprintf.c,v 1.9 2002/09/08 10:23:42 chorns Exp $
+/* $Id: sprintf.c,v 1.10 2002/09/12 17:50:05 guido Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROGRAMMERS: David Welch
* Eric Kohl
*
- * TODO:
- * - Implement maximum length (cnt) in _vsnprintf().
*/
/*
static char *
-number (char * str, long long num, int base, int size, int precision, int type)
+number(char *buf, char *end, long long num, int base, int size, int precision, int type)
{
char c,sign,tmp[66];
- const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ const char *digits;
+ const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+ const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i;
- if (type & LARGE)
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ digits = (type & LARGE) ? large_digits : small_digits;
if (type & LEFT)
type &= ~ZEROPAD;
if (base < 2 || base > 36)
return 0;
-
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
-
if (type & SIGN) {
if (num < 0) {
sign = '-';
- num = -num;
+ num = -num;
size--;
} else if (type & PLUS) {
sign = '+';
size--;
}
}
-
if (type & SPECIAL) {
if (base == 16)
size -= 2;
else if (base == 8)
size--;
}
-
i = 0;
if (num == 0)
tmp[i++]='0';
if (i > precision)
precision = i;
size -= precision;
- if (!(type&(ZEROPAD+LEFT)))
- while(size-->0)
- *str++ = ' ';
- if (sign)
- *str++ = sign;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
if (type & SPECIAL) {
if (base==8) {
- *str++ = '0';
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
} else if (base==16) {
- *str++ = '0';
- *str++ = digits[33];
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
}
}
- if (!(type & LEFT))
- while (size-- > 0)
- *str++ = c;
- while (i < precision--)
- *str++ = '0';
- while (i-- > 0)
- *str++ = tmp[i];
- while (size-- > 0)
- *str++ = ' ';
- return str;
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = ' ';
+ ++buf;
+ }
+ return buf;
}
int len;
unsigned long long num;
int i, base;
- char * str;
+ char *str, *end;
const char *s;
const wchar_t *sw;
number of chars for from string */
int qualifier; /* 'h', 'l', 'L', 'I' or 'w' for integer fields */
- for (str=buf ; *fmt ; ++fmt) {
+ str = buf;
+ end = buf + cnt - 1;
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ cnt = end - buf + 1;
+ }
+
+ for ( ; *fmt ; ++fmt) {
if (*fmt != '%') {
- *str++ = *fmt;
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = *fmt;
+ ++str;
continue;
}
/* process flags */
flags = 0;
- repeat:
+ repeat:
++fmt; /* this also skips first '%' */
switch (*fmt) {
- case '-': flags |= LEFT; goto repeat;
- case '+': flags |= PLUS; goto repeat;
- case ' ': flags |= SPACE; goto repeat;
- case '#': flags |= SPECIAL; goto repeat;
- case '0': flags |= ZEROPAD; goto repeat;
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
}
/* get field width */
if (!(flags & LEFT))
while (--field_width > 0)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
if (qualifier == 'l' || qualifier == 'w')
{
- *str++ = (unsigned char)(wchar_t) va_arg(args, int);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char)(wchar_t) va_arg(args, int);
+ ++str;
}
else
{
- *str++ = (unsigned char) va_arg(args, int);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char) va_arg(args, int);
+ ++str;
}
while (--field_width > 0)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
continue;
if (!(flags & LEFT))
while (--field_width > 0)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
if (qualifier == 'h')
{
- *str++ = (unsigned char) va_arg(args, int);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char) va_arg(args, int);
+ ++str;
}
else
{
- *str++ = (unsigned char)(wchar_t) va_arg(args, int);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char)(wchar_t) va_arg(args, int);
+ ++str;
}
while (--field_width > 0)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
continue;
case 's': /* finished */
if (qualifier == 'l' || qualifier == 'w') {
- /* print unicode string */
+ /* print unicode string */
sw = va_arg(args, wchar_t *);
if (sw == NULL)
sw = L"<NULL>";
if (!(flags & LEFT))
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
for (i = 0; i < len; ++i)
{
- *str++ = (unsigned char)(*sw++);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char)(*sw);
+ ++str;
+ ++sw;
}
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
} else {
- /* print ascii string */
+ /* print ascii string */
s = va_arg(args, char *);
if (s == NULL)
s = "<NULL>";
if (!(flags & LEFT))
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
for (i = 0; i < len; ++i)
{
- *str++ = *s++;
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
}
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
}
continue;
if (!(flags & LEFT))
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
for (i = 0; i < len; ++i)
{
- *str++ = *s++;
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
}
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
} else {
- /* print unicode string */
+ /* print unicode string */
sw = va_arg(args, wchar_t *);
if (sw == NULL)
sw = L"<NULL>";
if (!(flags & LEFT))
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
for (i = 0; i < len; ++i)
{
- *str++ = (unsigned char)(*sw++);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char)(*sw);
+ ++str;
+ ++sw;
}
while (len < field_width--)
{
- *str++ = ' ';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = ' ';
+ ++str;
}
}
continue;
case 'Z':
if (qualifier == 'w') {
- /* print counted unicode string */
+ /* print counted unicode string */
PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
s = "<NULL>";
while ((*s) != 0)
{
- *str++ = *s++;
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
}
} else {
for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++)
{
- *str++ = (unsigned char)(pus->Buffer[i]);
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = (unsigned char)(pus->Buffer[i]);
+ ++str;
}
}
} else {
- /* print counted ascii string */
+ /* print counted ascii string */
PANSI_STRING pus = va_arg(args, PANSI_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
s = "<NULL>";
while ((*s) != 0)
{
- *str++ = *s++;
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = *s;
+ ++str;
+ ++s;
}
} else {
for (i = 0; pus->Buffer[i] && i < pus->Length; i++)
{
- *str++ = pus->Buffer[i];
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = pus->Buffer[i];
+ ++str;
}
}
}
field_width = 2 * sizeof(void *);
flags |= ZEROPAD;
}
- str = number(str,
- (unsigned long) va_arg(args, void *), 16,
- field_width, precision, flags);
+ str = number(str, end,
+ (unsigned long) va_arg(args, void *),
+ 16, field_width, precision, flags);
continue;
case 'n':
+ /* FIXME: What does C99 say about the overflow case here? */
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
default:
if (*fmt != '%')
{
- *str++ = '%';
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = '%';
+ ++str;
}
if (*fmt)
{
- *str++ = *fmt;
- if( --cnt == 0 )
- goto out;
+ if (str <= end)
+ *str = *fmt;
+ ++str;
}
else
--fmt;
else
num = va_arg(args, unsigned int);
}
- str = number(str, num, base, field_width, precision, flags);
+ str = number(str, end, num, base, field_width, precision, flags);
}
- out:
- *str = '\0';
+
+ if (str <= end)
+ *str = '\0';
+ else if (cnt > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = '\0';
+
return str-buf;
}
-/* $Id: swprintf.c,v 1.7 2002/09/08 10:23:42 chorns Exp $
+/* $Id: swprintf.c,v 1.8 2002/09/12 17:50:05 guido Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* Eric Kohl
*
* TODO:
- * - Implement maximum length (cnt) in _vsnwprintf().
* - Verify the implementation of '%Z'.
*/
static wchar_t *
-number (wchar_t *str, long long num, int base, int size, int precision,
- int type)
+number(wchar_t * buf, wchar_t * end, long long num, int base, int size, int precision, int type)
{
- wchar_t c,sign,tmp[66];
- const wchar_t *digits = L"0123456789abcdefghijklmnopqrstuvwxyz";
- int i;
-
- if (type & LARGE)
- digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (type & LEFT)
- type &= ~ZEROPAD;
- if (base < 2 || base > 36)
- return 0;
-
- c = (type & ZEROPAD) ? L'0' : L' ';
- sign = 0;
-
- if (type & SIGN)
- {
- if (num < 0)
- {
- sign = L'-';
- num = -num;
- size--;
- }
- else if (type & PLUS)
- {
- sign = L'+';
- size--;
- }
- else if (type & SPACE)
- {
- sign = L' ';
- size--;
- }
- }
-
- if (type & SPECIAL)
- {
- if (base == 16)
- size -= 2;
- else if (base == 8)
- size--;
- }
-
- i = 0;
- if (num == 0)
- tmp[i++]='0';
- else while (num != 0)
- tmp[i++] = digits[do_div(num,base)];
- if (i > precision)
- precision = i;
- size -= precision;
- if (!(type&(ZEROPAD+LEFT)))
- while(size-->0)
- *str++ = L' ';
- if (sign)
- *str++ = sign;
- if (type & SPECIAL)
- {
- if (base==8)
- {
- *str++ = L'0';
- }
- else if (base==16)
- {
- *str++ = L'0';
- *str++ = digits[33];
- }
- }
- if (!(type & LEFT))
- while (size-- > 0)
- *str++ = c;
- while (i < precision--)
- *str++ = '0';
- while (i-- > 0)
- *str++ = tmp[i];
- while (size-- > 0)
- *str++ = L' ';
- return str;
+ wchar_t c,sign, tmp[66];
+ const wchar_t *digits;
+ const wchar_t small_digits[] = L"0123456789abcdefghijklmnopqrstuvwxyz";
+ const wchar_t large_digits[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ int i;
+
+ digits = (type & LARGE) ? large_digits : small_digits;
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? L'0' : L' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = L'-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = L'+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++] = L'0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+ if (buf <= end)
+ *buf = L' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+ if (buf <= end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+ if (buf <= end)
+ *buf = L'0';
+ ++buf;
+ } else if (base==16) {
+ if (buf <= end)
+ *buf = L'0';
+ ++buf;
+ if (buf <= end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+ if (buf <= end)
+ *buf = L'0';
+ ++buf;
+ }
+ while (i-- > 0) {
+ if (buf <= end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+ if (buf <= end)
+ *buf = L' ';
+ ++buf;
+ }
+ return buf;
}
int len;
unsigned long long num;
int i, base;
- wchar_t * str;
+ wchar_t * str, * end;
const char *s;
const wchar_t *sw;
number of chars for from string */
int qualifier; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
- for (str=buf ; *fmt ; ++fmt) {
+ str = buf;
+ end = buf + cnt - 1;
+ if (end < buf - 1) {
+ end = ((void *) -1);
+ cnt = end - buf + 1;
+ }
+
+ for ( ; *fmt ; ++fmt) {
if (*fmt != L'%') {
- *str++ = *fmt;
+ if (str <= end)
+ *str = *fmt;
+ ++str;
continue;
}
/* get the precision */
precision = -1;
if (*fmt == L'.') {
- ++fmt;
+ ++fmt;
if (iswdigit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == L'*') {
switch (*fmt) {
case L'c':
if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = L' ';
- if (qualifier == 'h')
- *str++ = (wchar_t) va_arg(args, int);
- else
- *str++ = (wchar_t) va_arg(args, int);
- while (--field_width > 0)
- *str++ = L' ';
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ if (qualifier == 'h') {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ } else {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ }
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
continue;
case L'C':
if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = L' ';
- if (qualifier == 'l' || qualifier == 'w')
- *str++ = (wchar_t) va_arg(args, int);
- else
- *str++ = (wchar_t) va_arg(args, int);
- while (--field_width > 0)
- *str++ = L' ';
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ if (qualifier == 'l' || qualifier == 'w') {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ } else {
+ if (str <= end)
+ *str = (wchar_t) va_arg(args, int);
+ ++str;
+ }
+ while (--field_width > 0) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
continue;
case L's':
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = (wchar_t)(*s++);
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = (wchar_t)(*s);
+ ++str;
+ ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
} else {
/* print unicode string */
sw = va_arg(args, wchar_t *);
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = *sw++;
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
}
continue;
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = *sw++;
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
} else {
/* print ascii string */
s = va_arg(args, char *);
len = precision;
if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = L' ';
- for (i = 0; i < len; ++i)
- *str++ = (wchar_t)(*s++);
- while (len < field_width--)
- *str++ = L' ';
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
+ for (i = 0; i < len; ++i) {
+ if (str <= end)
+ *str = (wchar_t)(*s);
+ ++str;
+ ++s;
+ }
+ while (len < field_width--) {
+ if (str <= end)
+ *str = L' ';
+ ++str;
+ }
}
continue;
PANSI_STRING pus = va_arg(args, PANSI_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
sw = L"<NULL>";
- while ((*sw) != 0)
- *str++ = *sw++;
+ while ((*sw) != 0) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
} else {
- for (i = 0; pus->Buffer[i] && i < pus->Length; i++)
- *str++ = (wchar_t)(pus->Buffer[i]);
+ for (i = 0; pus->Buffer[i] && i < pus->Length; i++) {
+ if (str <= end)
+ *str = (wchar_t)(pus->Buffer[i]);
+ ++str;
+ }
}
} else {
/* print counted unicode string */
PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING);
if ((pus == NULL) || (pus->Buffer == NULL)) {
sw = L"<NULL>";
- while ((*sw) != 0)
- *str++ = *sw++;
+ while ((*sw) != 0) {
+ if (str <= end)
+ *str = *sw;
+ ++str;
+ ++sw;
+ }
} else {
- for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++)
- *str++ = pus->Buffer[i];
+ for (i = 0; pus->Buffer[i] && i < pus->Length / sizeof(WCHAR); i++) {
+ if (str <= end)
+ *str = pus->Buffer[i];
+ ++str;
+ }
}
}
continue;
field_width = 2*sizeof(void *);
flags |= ZEROPAD;
}
- str = number(str,
+ str = number(str, end,
(unsigned long) va_arg(args, void *), 16,
field_width, precision, flags);
continue;
case L'n':
+ /* FIXME: What does C99 say about the overflow case here? */
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
break;
default:
- if (*fmt != L'%')
- *str++ = L'%';
- if (*fmt)
- *str++ = *fmt;
- else
+ if (*fmt != L'%') {
+ if (str <= end)
+ *str = L'%';
+ ++str;
+ }
+ if (*fmt) {
+ if (str <= end)
+ *str = *fmt;
+ ++str;
+ } else
--fmt;
continue;
}
else
num = va_arg(args, unsigned int);
}
- str = number(str, num, base, field_width, precision, flags);
+ str = number(str, end, num, base, field_width, precision, flags);
}
- *str = L'\0';
+ if (str <= end)
+ *str = L'\0';
+ else if (cnt > 0)
+ /* don't write out a null byte if the buf size is zero */
+ *end = L'\0';
return str-buf;
}