More vsnprintf() emulation function bug fixes.

This commit is contained in:
Michael R Sweet 2005-08-11 14:28:49 +00:00
parent 89237c9280
commit 1bbf8b7da6

View File

@ -138,10 +138,10 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
sign, /* Sign of format width */
size, /* Size character (h, l, L) */
type; /* Format type character */
const char *bufformat; /* Start of format */
int width, /* Width of field */
prec; /* Number of characters of precision */
char tformat[100], /* Temporary format string for sprintf() */
*tptr, /* Pointer into temporary format */
temp[1024]; /* Buffer for formatted numbers */
char *s; /* Pointer to string */
int slen; /* Length of string */
@ -160,30 +160,74 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
{
if (*format == '%')
{
bufformat = format;
format ++;
tptr = tformat;
*tptr++ = *format++;
if (*format == '%')
{
*bufptr++ = *format++;
if (bufptr && bufptr < bufend) *bufptr++ = *format;
bytes ++;
format ++;
continue;
}
else if (strchr(" -+#\'", *format))
{
*tptr++ = *format;
sign = *format++;
}
else
sign = 0;
width = 0;
while (isdigit(*format))
width = width * 10 + *format++ - '0';
if (*format == '*')
{
// Get width from argument...
format ++;
width = va_arg(ap, int);
snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
tptr += strlen(tptr);
}
else
{
width = 0;
while (isdigit(*format & 255))
{
if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
width = width * 10 + *format++ - '0';
}
}
if (*format == '.')
{
format ++;
prec = 0;
if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
while (isdigit(*format))
prec = prec * 10 + *format++ - '0';
format ++;
if (*format == '*')
{
// Get precision from argument...
format ++;
prec = va_arg(ap, int);
snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
tptr += strlen(tptr);
}
else
{
prec = 0;
while (isdigit(*format & 255))
{
if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
prec = prec * 10 + *format++ - '0';
}
}
}
else
prec = -1;
@ -191,15 +235,31 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
if (*format == 'l' && format[1] == 'l')
{
size = 'L';
if (tptr < (tformat + sizeof(tformat) - 2))
{
*tptr++ = 'l';
*tptr++ = 'l';
}
format += 2;
}
else if (*format == 'h' || *format == 'l' || *format == 'L')
{
if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
size = *format++;
}
if (!*format)
break;
type = *format++;
if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
type = *format++;
*tptr = '\0';
switch (type)
{
@ -208,13 +268,9 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
case 'e' :
case 'f' :
case 'g' :
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
if ((width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, double));
bytes += strlen(temp);
@ -223,9 +279,8 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
strncpy(bufptr, temp, (size_t)(bufend - bufptr));
bufptr = bufend;
break;
}
else
{
@ -243,13 +298,9 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
case 'o' :
case 'u' :
case 'x' :
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
if ((width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, int));
bytes += strlen(temp);
@ -258,9 +309,8 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
strncpy(bufptr, temp, (size_t)(bufend - bufptr));
bufptr = bufend;
break;
}
else
{
@ -269,14 +319,10 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
}
}
break;
case 'p' : /* Pointer value */
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
case 'p' : /* Pointer value */
if ((width + 2) > sizeof(temp))
break;
sprintf(temp, tformat, va_arg(ap, void *));
@ -286,9 +332,8 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
strncpy(bufptr, temp, (size_t)(bufend - bufptr));
bufptr = bufend;
break;
}
else
{
@ -304,13 +349,13 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
if (bufptr)
{
if (width <= 1)
*bufptr++ = va_arg(ap, int);
*bufptr++ = va_arg(ap, int);
else
{
if ((bufptr + width) > bufend)
width = bufend - bufptr;
width = bufend - bufptr;
memcpy(bufptr, va_arg(ap, char *), width);
memcpy(bufptr, va_arg(ap, char *), (size_t)width);
bufptr += width;
}
}
@ -329,20 +374,20 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
if (bufptr)
{
if ((bufptr + width) > bufend)
width = bufend - bufptr;
width = bufend - bufptr;
if (slen > width)
slen = width;
slen = width;
if (sign == '-')
{
strncpy(bufptr, s, slen);
memset(bufptr + slen, ' ', width - slen);
strncpy(bufptr, s, (size_t)slen);
memset(bufptr + slen, ' ', (size_t)(width - slen));
}
else
{
memset(bufptr, ' ', width - slen);
strncpy(bufptr + width - slen, s, slen);
memset(bufptr, ' ', (size_t)(width - slen));
strncpy(bufptr + width - slen, s, (size_t)slen);
}
bufptr += width;
@ -350,31 +395,7 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
break;
case 'n' : /* Output number of chars so far */
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, int));
bytes += strlen(temp);
if (bufptr)
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
}
else
{
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
*(va_arg(ap, int *)) = bytes;
break;
}
}
@ -383,7 +404,7 @@ mxml_vsnprintf(char *buffer, /* O - Output buffer */
bytes ++;
if (bufptr && bufptr < bufend)
*bufptr++ = *format;
*bufptr++ = *format;
format ++;
}