in CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/silent_printf.cpp [338:600]
BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, LPINT Precision, LPINT Prefix, LPINT Type)
{
BOOL Result = FALSE;
LPSTR TempStr;
LPSTR TempStrPtr;
*Width = WIDTH_DEFAULT;
*Precision = PRECISION_DEFAULT;
*Flags = PFF_NONE;
*Prefix = PFF_PREFIX_DEFAULT;
*Type = PFF_TYPE_DEFAULT;
if (*Fmt && **Fmt == '%')
{
*Out++ = *(*Fmt)++;
}
else
{
return Result;
}
/* we'll never need a temp string longer than the original */
TempStrPtr = TempStr = (LPSTR) PAL_malloc(strlen(*Fmt)+1);
if (!TempStr)
{
return Result;
}
/* parse flags */
while (**Fmt && (**Fmt == '-' || **Fmt == '+' ||
**Fmt == '0' || **Fmt == ' ' || **Fmt == '#'))
{
switch (**Fmt)
{
case '-':
*Flags |= PFF_MINUS; break;
case '+':
*Flags |= PFF_PLUS; break;
case '0':
*Flags |= PFF_ZERO; break;
case ' ':
*Flags |= PFF_SPACE; break;
case '#':
*Flags |= PFF_POUND; break;
}
*Out++ = *(*Fmt)++;
}
/* '-' flag negates '0' flag */
if ((*Flags & PFF_MINUS) && (*Flags & PFF_ZERO))
{
*Flags -= PFF_ZERO;
}
/* grab width specifier */
if (isdigit((unsigned char) **Fmt))
{
TempStrPtr = TempStr;
while (isdigit((unsigned char) **Fmt))
{
*TempStrPtr++ = **Fmt;
*Out++ = *(*Fmt)++;
}
*TempStrPtr = 0; /* end string */
*Width = atoi(TempStr);
if (*Width < 0)
{
SetLastError(ERROR_INTERNAL_ERROR);
return Result;
}
}
else if (**Fmt == '*')
{
*Width = WIDTH_STAR;
*Out++ = *(*Fmt)++;
if (isdigit((unsigned char) **Fmt))
{
/* this is an invalid width because we have a * then a number */
/* printf handles this by just printing the whole string */
*Width = WIDTH_INVALID;
while (isdigit((unsigned char) **Fmt))
{
*Out++ = *(*Fmt)++;
}
}
}
/* grab precision specifier */
if (**Fmt == '.')
{
*Out++ = *(*Fmt)++;
if (isdigit((unsigned char) **Fmt))
{
TempStrPtr = TempStr;
while (isdigit((unsigned char) **Fmt))
{
*TempStrPtr++ = **Fmt;
*Out++ = *(*Fmt)++;
}
*TempStrPtr = 0; /* end string */
*Precision = atoi(TempStr);
if (*Precision < 0)
{
SetLastError(ERROR_INTERNAL_ERROR);
return Result;
}
}
else if (**Fmt == '*')
{
*Precision = PRECISION_STAR;
*Out++ = *(*Fmt)++;
if (isdigit((unsigned char) **Fmt))
{
/* this is an invalid precision because we have a .* then a
number */
/* printf handles this by just printing the whole string */
*Precision = PRECISION_INVALID;
while (isdigit((unsigned char) **Fmt))
{
*Out++ = *(*Fmt)++;
}
}
}
else
{
*Precision = PRECISION_DOT;
}
}
#ifdef HOST_64BIT
if (**Fmt == 'p')
{
*Prefix = PFF_PREFIX_LONGLONG;
}
#endif
/* grab prefix of 'I64' for __int64 */
if ((*Fmt)[0] == 'I' && (*Fmt)[1] == '6' && (*Fmt)[2] == '4')
{
/* convert to 'll' so BSD's snprintf can handle it */
*Fmt += 3;
*Prefix = PFF_PREFIX_LONGLONG;
}
/* grab a prefix of 'h' */
else if (**Fmt == 'h')
{
*Prefix = PFF_PREFIX_SHORT;
++(*Fmt);
}
/* grab prefix of 'l' or the undocumented 'w' (at least in MSDN) */
else if (**Fmt == 'l' || **Fmt == 'w')
{
++(*Fmt);
#ifdef HOST_64BIT
// Only want to change the prefix on 64 bit when printing characters.
if (**Fmt == 'c' || **Fmt == 's')
#endif
{
*Prefix = PFF_PREFIX_LONG;
}
}
else if (**Fmt == 'L')
{
/* a prefix of 'L' seems to be ignored */
++(*Fmt);
}
/* grab type 'c' */
if (**Fmt == 'c' || **Fmt == 'C')
{
*Type = PFF_TYPE_CHAR;
if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'C')
{
*Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */
}
if (*Prefix == PFF_PREFIX_LONG)
{
*Out++ = 'l';
}
*Out++ = 'c';
++(*Fmt);
Result = TRUE;
}
/* grab type 's' */
else if (**Fmt == 's' || **Fmt == 'S')
{
*Type = PFF_TYPE_STRING;
if (*Prefix != PFF_PREFIX_SHORT && **Fmt == 'S')
{
*Prefix = PFF_PREFIX_LONG; /* give it a wide prefix */
}
if (*Prefix == PFF_PREFIX_LONG)
{
*Out++ = 'l';
}
*Out++ = 's';
++(*Fmt);
Result = TRUE;
}
/* grab int types types */
else if (**Fmt == 'd' || **Fmt == 'i' || **Fmt == 'o' ||
**Fmt == 'u' || **Fmt == 'x' || **Fmt == 'X')
{
*Type = PFF_TYPE_INT;
if (*Prefix == PFF_PREFIX_SHORT)
{
*Out++ = 'h';
}
else if (*Prefix == PFF_PREFIX_LONG)
{
*Out++ = 'l';
}
else if (*Prefix == PFF_PREFIX_LONGLONG)
{
*Out++ = 'l';
*Out++ = 'l';
}
*Out++ = *(*Fmt)++;
Result = TRUE;
}
else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' ||
**Fmt == 'g' || **Fmt == 'G')
{
/* we can safely ignore the prefixes and only add the type*/
*Type = PFF_TYPE_FLOAT;
*Out++ = *(*Fmt)++;
Result = TRUE;
}
else if (**Fmt == 'n')
{
if (*Prefix == PFF_PREFIX_SHORT)
{
*Out++ = 'h';
}
*Out++ = *(*Fmt)++;
*Type = PFF_TYPE_N;
Result = TRUE;
}
else if (**Fmt == 'p')
{
*Type = PFF_TYPE_P;
*Out++ = *(*Fmt)++;
if (*Prefix == PFF_PREFIX_LONGLONG)
{
if (*Precision == PRECISION_DEFAULT)
{
*Precision = 16;
}
}
else
{
if (*Precision == PRECISION_DEFAULT)
{
*Precision = 8;
}
}
Result = TRUE;
}
*Out = 0; /* end the string */
PAL_free(TempStr);
return Result;
}