in CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printfcpp.cpp [1450:1772]
int CoreVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, va_list aparg)
{
CHAR TempBuff[1024]; /* used to hold a single %<foo> format string */
LPCSTR Fmt = format;
LPCWSTR TempWStr;
LPSTR TempStr;
WCHAR TempWChar;
INT Flags;
INT Width;
INT Precision;
INT Prefix;
INT Type;
INT Length;
INT TempInt;
int wctombResult;
int written = 0;
int paddingReturnValue;
va_list ap;
PERF_ENTRY(vfprintf);
va_copy(ap, aparg);
while (*Fmt)
{
if (*Fmt == '%' &&
TRUE == Internal_ExtractFormatA(pthrCurrent, &Fmt, TempBuff, &Flags,
&Width, &Precision,
&Prefix, &Type))
{
if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_STRING)
{
if (WIDTH_STAR == Width)
{
Width = va_arg(ap, INT);
}
else if (WIDTH_INVALID == Width)
{
/* both a '*' and a number, ignore, but remove arg */
TempInt = va_arg(ap, INT); /* value not used */
}
if (PRECISION_STAR == Precision)
{
Precision = va_arg(ap, INT);
}
else if (PRECISION_INVALID == Precision)
{
/* both a '*' and a number, ignore, but remove arg */
TempInt = va_arg(ap, INT); /* value not used */
}
TempWStr = va_arg(ap, LPWSTR);
if (TempWStr == NULL)\
{
TempWStr = __wnullstring;
}
Length = WideCharToMultiByte(CP_ACP, 0, TempWStr, -1, 0,
0, 0, 0);
if (!Length)
{
ASSERT("WideCharToMultiByte failed. Error is %d\n",
GetLastError());
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
TempStr = (LPSTR) InternalMalloc(Length);
if (!TempStr)
{
ERROR("InternalMalloc failed\n");
pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY);
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
if (PRECISION_DOT == Precision)
{
/* copy nothing */
*TempStr = 0;
Length = 0;
}
else if (Precision > 0 && Precision < Length - 1)
{
Length = WideCharToMultiByte(CP_ACP, 0, TempWStr,
Precision, TempStr, Length,
0, 0);
if (!Length)
{
ASSERT("WideCharToMultiByte failed. Error is %d\n",
GetLastError());
free(TempStr);
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
TempStr[Length] = 0;
Length = Precision;
}
/* copy everything */
else
{
wctombResult = WideCharToMultiByte(CP_ACP, 0, TempWStr, -1,
TempStr, Length, 0, 0);
if (!wctombResult)
{
ASSERT("WideCharToMultiByte failed. Error is %d\n",
GetLastError());
free(TempStr);
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
--Length; /* exclude null char */
}
/* do the padding (if needed)*/
paddingReturnValue =
Internal_AddPaddingVfprintf(pthrCurrent, stream, TempStr,
Width - Length, Flags);
if (-1 == paddingReturnValue)
{
ERROR("Internal_AddPaddingVfprintf failed\n");
free(TempStr);
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
written += paddingReturnValue;
free(TempStr);
}
else if (Prefix == PFF_PREFIX_LONG && Type == PFF_TYPE_CHAR)
{
CHAR TempBuffer[5];
if (WIDTH_STAR == Width ||
WIDTH_INVALID == Width)
{
/* ignore (because it's a char), and remove arg */
TempInt = va_arg(ap, INT); /* value not used */
}
if (PRECISION_STAR == Precision ||
PRECISION_INVALID == Precision)
{
/* ignore (because it's a char), and remove arg */
TempInt = va_arg(ap, INT); /* value not used */
}
TempWChar = va_arg(ap, int);
Length = WideCharToMultiByte(CP_ACP, 0, &TempWChar, 1,
TempBuffer, sizeof(TempBuffer),
0, 0);
if (!Length)
{
ASSERT("WideCharToMultiByte failed. Error is %d\n",
GetLastError());
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
TempBuffer[Length] = 0;
/* do the padding (if needed)*/
paddingReturnValue =
Internal_AddPaddingVfprintf(pthrCurrent, stream, TempBuffer,
Width - Length, Flags);
if (-1 == paddingReturnValue)
{
ERROR("Internal_AddPaddingVfprintf failed\n");
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
written += paddingReturnValue;
}
/* this places the number of bytes written to the buffer in the
next arg */
else if (Type == PFF_TYPE_N)
{
if (WIDTH_STAR == Width)
{
Width = va_arg(ap, INT);
}
if (PRECISION_STAR == Precision)
{
Precision = va_arg(ap, INT);
}
if (Prefix == PFF_PREFIX_SHORT)
{
*(va_arg(ap, short *)) = written;
}
else
{
*(va_arg(ap, LPLONG)) = written;
}
}
else if (Type == PFF_TYPE_CHAR && (Flags & PFF_ZERO) != 0)
{
// Some versions of fprintf don't support 0-padded chars,
// so we handle them here.
char ch[2];
ch[0] = (char) va_arg(ap, int);
ch[1] = '\0';
Length = 1;
paddingReturnValue = Internal_AddPaddingVfprintf(
pthrCurrent,
stream,
ch,
Width - Length,
Flags);
if (-1 == paddingReturnValue)
{
ERROR("Internal_AddPaddingVfprintf failed\n");
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
written += paddingReturnValue;
}
else if (Type == PFF_TYPE_STRING && (Flags & PFF_ZERO) != 0)
{
// Some versions of fprintf don't support 0-padded strings,
// so we handle them here.
const char *tempStr;
tempStr = va_arg(ap, char *);
if (tempStr == NULL)
{
tempStr = __nullstring;
}
Length = strlen(tempStr);
paddingReturnValue = Internal_AddPaddingVfprintf(
pthrCurrent,
stream,
tempStr,
Width - Length,
Flags);
if (-1 == paddingReturnValue)
{
ERROR("Internal_AddPaddingVfprintf failed\n");
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
written += paddingReturnValue;
}
else
{
// Types that fprintf can handle.
TempInt = 0;
// %h (short) doesn't seem to be handled properly by local sprintf,
// so we do the truncation ourselves for some cases.
if (Type == PFF_TYPE_P && Prefix == PFF_PREFIX_SHORT)
{
// Convert from pointer -> int -> short to avoid warnings.
long trunc1;
short trunc2;
trunc1 = va_arg(ap, LONG);
trunc2 = (short)trunc1;
trunc1 = trunc2;
TempInt = fprintf(stream->bsdFilePtr, TempBuff, trunc1);
}
else if (Type == PFF_TYPE_INT && Prefix == PFF_PREFIX_SHORT)
{
// Convert explicitly from int to short to get
// correct sign extension for shorts on all systems.
int n;
short s;
n = va_arg(ap, int);
s = (short) n;
TempInt = fprintf( stream->bsdFilePtr, TempBuff, s);
}
else
{
va_list apcopy;
va_copy(apcopy, ap);
TempInt = vfprintf(stream->bsdFilePtr, TempBuff, apcopy);
va_end(apcopy);
PAL_printf_arg_remover(&ap, Width, Precision, Type, Prefix);
}
if (-1 == TempInt)
{
ERROR("vfprintf returned an error\n");
}
else
{
written += TempInt;
}
}
}
else
{
#if FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL
clearerr (stream->bsdFilePtr);
#endif
InternalFwrite(Fmt++, 1, 1, stream->bsdFilePtr, &stream->PALferrorCode); /* copy regular chars into buffer */
if (stream->PALferrorCode == PAL_FILE_ERROR)
{
ERROR("fwrite() failed with errno == %d\n", errno);
PERF_EXIT(vfprintf);
va_end(ap);
return -1;
}
++written;
}
}
va_end(ap);
PERF_EXIT(vfprintf);
return written;
}