📄 vasnprintf.c
字号:
case 's':
# ifdef HAVE_WCHAR_T
if (type == TYPE_WIDE_STRING)
{
tmp_length =
local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
# if !WIDE_CHAR_VERSION
tmp_length = xtimes (tmp_length, MB_CUR_MAX);
# endif
}
else
# endif
tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
break;
case 'p':
tmp_length =
(unsigned int) (sizeof (void *) * CHAR_BIT
* 0.25 /* binary -> hexadecimal */
)
+ 1 /* turn floor into ceil */
+ 2; /* account for leading 0x */
break;
default:
abort ();
}
if (tmp_length < width)
tmp_length = width;
tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
}
if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
tmp = tmpbuf;
else
{
size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
if (size_overflow_p (tmp_memsize))
/* Overflow, would lead to out of memory. */
goto out_of_memory;
tmp = (CHAR_T *) malloc (tmp_memsize);
if (tmp == NULL)
/* Out of memory. */
goto out_of_memory;
}
#endif
/* Construct the format string for calling snprintf or
sprintf. */
p = buf;
*p++ = '%';
if (dp->flags & FLAG_GROUP)
*p++ = '\'';
if (dp->flags & FLAG_LEFT)
*p++ = '-';
if (dp->flags & FLAG_SHOWSIGN)
*p++ = '+';
if (dp->flags & FLAG_SPACE)
*p++ = ' ';
if (dp->flags & FLAG_ALT)
*p++ = '#';
if (dp->flags & FLAG_ZERO)
*p++ = '0';
if (dp->width_start != dp->width_end)
{
size_t n = dp->width_end - dp->width_start;
memcpy (p, dp->width_start, n * sizeof (CHAR_T));
p += n;
}
if (dp->precision_start != dp->precision_end)
{
size_t n = dp->precision_end - dp->precision_start;
memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
p += n;
}
switch (type)
{
#ifdef HAVE_LONG_LONG
case TYPE_LONGLONGINT:
case TYPE_ULONGLONGINT:
*p++ = 'l';
/*FALLTHROUGH*/
#endif
case TYPE_LONGINT:
case TYPE_ULONGINT:
#ifdef HAVE_WINT_T
case TYPE_WIDE_CHAR:
#endif
#ifdef HAVE_WCHAR_T
case TYPE_WIDE_STRING:
#endif
*p++ = 'l';
break;
#ifdef HAVE_LONG_DOUBLE
case TYPE_LONGDOUBLE:
*p++ = 'L';
break;
#endif
default:
break;
}
*p = dp->conversion;
#if USE_SNPRINTF
p[1] = '%';
p[2] = 'n';
p[3] = '\0';
#else
p[1] = '\0';
#endif
/* Construct the arguments for calling snprintf or sprintf. */
prefix_count = 0;
if (dp->width_arg_index != ARG_NONE)
{
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
abort ();
prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
}
if (dp->precision_arg_index != ARG_NONE)
{
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();
prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
}
#if USE_SNPRINTF
/* Prepare checking whether snprintf returns the count
via %n. */
ENSURE_ALLOCATION (xsum (length, 1));
result[length] = '\0';
#endif
for (;;)
{
size_t maxlen;
int count;
int retcount;
maxlen = allocated - length;
count = -1;
retcount = 0;
#if USE_SNPRINTF
# define SNPRINTF_BUF(arg) \
switch (prefix_count) \
{ \
case 0: \
retcount = SNPRINTF (result + length, maxlen, buf, \
arg, &count); \
break; \
case 1: \
retcount = SNPRINTF (result + length, maxlen, buf, \
prefixes[0], arg, &count); \
break; \
case 2: \
retcount = SNPRINTF (result + length, maxlen, buf, \
prefixes[0], prefixes[1], arg, \
&count); \
break; \
default: \
abort (); \
}
#else
# define SNPRINTF_BUF(arg) \
switch (prefix_count) \
{ \
case 0: \
count = sprintf (tmp, buf, arg); \
break; \
case 1: \
count = sprintf (tmp, buf, prefixes[0], arg); \
break; \
case 2: \
count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
arg); \
break; \
default: \
abort (); \
}
#endif
switch (type)
{
case TYPE_SCHAR:
{
int arg = a.arg[dp->arg_index].a.a_schar;
SNPRINTF_BUF (arg);
}
break;
case TYPE_UCHAR:
{
unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
SNPRINTF_BUF (arg);
}
break;
case TYPE_SHORT:
{
int arg = a.arg[dp->arg_index].a.a_short;
SNPRINTF_BUF (arg);
}
break;
case TYPE_USHORT:
{
unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
SNPRINTF_BUF (arg);
}
break;
case TYPE_INT:
{
int arg = a.arg[dp->arg_index].a.a_int;
SNPRINTF_BUF (arg);
}
break;
case TYPE_UINT:
{
unsigned int arg = a.arg[dp->arg_index].a.a_uint;
SNPRINTF_BUF (arg);
}
break;
case TYPE_LONGINT:
{
long int arg = a.arg[dp->arg_index].a.a_longint;
SNPRINTF_BUF (arg);
}
break;
case TYPE_ULONGINT:
{
unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_LONG_LONG
case TYPE_LONGLONGINT:
{
long long int arg = a.arg[dp->arg_index].a.a_longlongint;
SNPRINTF_BUF (arg);
}
break;
case TYPE_ULONGLONGINT:
{
unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_DOUBLE:
{
double arg = a.arg[dp->arg_index].a.a_double;
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_LONG_DOUBLE
case TYPE_LONGDOUBLE:
{
long double arg = a.arg[dp->arg_index].a.a_longdouble;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_CHAR:
{
int arg = a.arg[dp->arg_index].a.a_char;
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_WINT_T
case TYPE_WIDE_CHAR:
{
wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_STRING:
{
const char *arg = a.arg[dp->arg_index].a.a_string;
SNPRINTF_BUF (arg);
}
break;
#ifdef HAVE_WCHAR_T
case TYPE_WIDE_STRING:
{
const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
SNPRINTF_BUF (arg);
}
break;
#endif
case TYPE_POINTER:
{
void *arg = a.arg[dp->arg_index].a.a_pointer;
SNPRINTF_BUF (arg);
}
break;
default:
abort ();
}
#if USE_SNPRINTF
/* Portability: Not all implementations of snprintf()
are ISO C 99 compliant. Determine the number of
bytes that snprintf() has produced or would have
produced. */
if (count >= 0)
{
/* Verify that snprintf() has NUL-terminated its
result. */
if (count < maxlen && result[length + count] != '\0')
abort ();
/* Portability hack. */
if (retcount > count)
count = retcount;
}
else
{
/* snprintf() doesn't understand the '%n'
directive. */
if (p[1] != '\0')
{
/* Don't use the '%n' directive; instead, look
at the snprintf() return value. */
p[1] = '\0';
continue;
}
else
{
/* Look at the snprintf() return value. */
if (retcount < 0)
{
/* HP-UX 10.20 snprintf() is doubly deficient:
It doesn't understand the '%n' directive,
*and* it returns -1 (rather than the length
that would have been required) when the
buffer is too small. */
size_t bigger_need =
xsum (xtimes (allocated, 2), 12);
ENSURE_ALLOCATION (bigger_need);
continue;
}
else
count = retcount;
}
}
#endif
/* Attempt to handle failure. */
if (count < 0)
{
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
errno = EINVAL;
return NULL;
}
#if !USE_SNPRINTF
if (count >= tmp_length)
/* tmp_length was incorrectly calculated - fix the
code above! */
abort ();
#endif
/* Make room for the result. */
if (count >= maxlen)
{
/* Need at least count bytes. But allocate
proportionally, to avoid looping eternally if
snprintf() reports a too small count. */
size_t n =
xmax (xsum (length, count), xtimes (allocated, 2));
ENSURE_ALLOCATION (n);
#if USE_SNPRINTF
continue;
#endif
}
#if USE_SNPRINTF
/* The snprintf() result did fit. */
#else
/* Append the sprintf() result. */
memcpy (result + length, tmp, count * sizeof (CHAR_T));
if (tmp != tmpbuf)
free (tmp);
#endif
length += count;
break;
}
}
}
}
/* Add the final NUL. */
ENSURE_ALLOCATION (xsum (length, 1));
result[length] = '\0';
if (result != resultbuf && length + 1 < allocated)
{
/* Shrink the allocated memory if possible. */
CHAR_T *memory;
memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
if (memory != NULL)
result = memory;
}
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
*lengthp = length;
if (length > INT_MAX)
goto length_overflow;
return result;
length_overflow:
/* We could produce such a big string, but its length doesn't fit into
an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in
this case. */
if (result != resultbuf)
free (result);
errno = EOVERFLOW;
return NULL;
out_of_memory:
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
out_of_memory_1:
CLEANUP ();
errno = ENOMEM;
return NULL;
}
}
#undef SNPRINTF
#undef USE_SNPRINTF
#undef PRINTF_PARSE
#undef DIRECTIVES
#undef DIRECTIVE
#undef CHAR_T
#undef VASNPRINTF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -