More vsnprintf() emulation function bug fixes.

pull/193/head
Michael R Sweet 19 years ago
parent 89237c9280
commit 1bbf8b7da6
  1. 157
      mxml-string.c

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

Loading…
Cancel
Save