#include "string-private.h"
#ifndef HAVE_VSNPRINTF
int
_cups_vsnprintf(char *buffer,
size_t bufsize,
const char *format,
va_list ap)
{
char *bufptr,
*bufend,
sign,
size,
type;
int width,
prec;
char tformat[100],
*tptr,
temp[1024];
size_t templen;
char *s;
int slen;
int bytes;
bufptr = buffer;
bufend = buffer + bufsize - 1;
bytes = 0;
while (*format)
{
if (*format == '%')
{
tptr = tformat;
*tptr++ = *format++;
if (*format == '%')
{
if (bufptr && bufptr < bufend) *bufptr++ = *format;
bytes ++;
format ++;
continue;
}
else if (strchr(" -+#\'", *format))
{
*tptr++ = *format;
sign = *format++;
}
else
sign = 0;
if (*format == '*')
{
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 (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
format ++;
if (*format == '*')
{
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;
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;
if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format;
type = *format++;
*tptr = '\0';
switch (type)
{
case 'E' :
case 'G' :
case 'e' :
case 'f' :
case 'g' :
if ((width + 2) > sizeof(temp))
break;
sprintf(temp, tformat, va_arg(ap, double));
templen = strlen(temp):
bytes += (int)templen;
if (bufptr)
{
if ((bufptr + templen) > bufend)
{
strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
bufptr = bufend;
}
else
{
memcpy(bufptr, temp, templen + 1);
bufptr += templen;
}
}
break;
case 'B' :
case 'X' :
case 'b' :
case 'd' :
case 'i' :
case 'o' :
case 'u' :
case 'x' :
if ((width + 2) > sizeof(temp))
break;
sprintf(temp, tformat, va_arg(ap, int));
templen = strlen(temp):
bytes += (int)templen;
if (bufptr)
{
if ((bufptr + templen) > bufend)
{
strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
bufptr = bufend;
}
else
{
memcpy(bufptr, temp, templen + 1);
bufptr += templen;
}
}
break;
case 'p' :
if ((width + 2) > sizeof(temp))
break;
sprintf(temp, tformat, va_arg(ap, void *));
templen = strlen(temp):
bytes += (int)templen;
if (bufptr)
{
if ((bufptr + templen) > bufend)
{
strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
bufptr = bufend;
}
else
{
memcpy(bufptr, temp, templen + 1);
bufptr += templen;
}
}
break;
case 'c' :
bytes += width;
if (bufptr)
{
if (width <= 1)
*bufptr++ = va_arg(ap, int);
else
{
if ((bufptr + width) > bufend)
width = (int)(bufend - bufptr);
memcpy(bufptr, va_arg(ap, char *), (size_t)width);
bufptr += width;
}
}
break;
case 's' :
if ((s = va_arg(ap, char *)) == NULL)
s = "(null)";
slen = (int)strlen(s);
if (slen > width && prec != width)
width = slen;
bytes += width;
if (bufptr)
{
if ((bufptr + width) > bufend)
width = (int)(bufend - bufptr);
if (slen > width)
slen = width;
if (sign == '-')
{
memcpy(bufptr, s, (size_t)slen);
memset(bufptr + slen, ' ', (size_t)(width - slen));
}
else
{
memset(bufptr, ' ', (size_t)(width - slen));
memcpy(bufptr + width - slen, s, (size_t)slen);
}
bufptr += width;
}
break;
case 'n' :
*(va_arg(ap, int *)) = bytes;
break;
}
}
else
{
bytes ++;
if (bufptr && bufptr < bufend)
*bufptr++ = *format;
format ++;
}
}
*bufptr = '\0';
return (bytes);
}
#endif
#ifndef HAVE_SNPRINTF
int
_cups_snprintf(char *buffer,
size_t bufsize,
const char *format,
...)
{
int bytes;
va_list ap;
va_start(ap, format);
bytes = vsnprintf(buffer, bufsize, format, ap);
va_end(ap);
return (bytes);
}
#endif