BOOL Internal_ExtractFormatW()

in CoreCLRProfiler/native/coreclr_headers/src/pal/src/cruntime/printfcpp.cpp [454:774]


BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *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++ = (CHAR) *(*Fmt)++;
    }
    else
    {
        return Result;
    }

    /* we'll never need a temp string longer than the original */
    TempStrPtr = TempStr = (LPSTR) InternalMalloc(PAL_wcslen(*Fmt)+1);
    if (!TempStr)
    {
        ERROR("InternalMalloc failed\n");
        pthrCurrent->SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        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++ = (CHAR) *(*Fmt)++;
    }
    /* '-' flag negates '0' flag */
    if ((*Flags & PFF_MINUS) && (*Flags & PFF_ZERO))
    {
        *Flags -= PFF_ZERO;
    }

    /* grab width specifier */
    if (isdigit(**Fmt))
    {
        TempStrPtr = TempStr;
        while (isdigit(**Fmt))
        {
            *TempStrPtr++ = (CHAR) **Fmt;
            *Out++ = (CHAR) *(*Fmt)++;
        }
        *TempStrPtr = 0; /* end string */
        *Width = atoi(TempStr);
        if (*Width < 0)
        {
            ERROR("atoi returned a negative value indicative of an overflow.\n");
            pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR);
            return Result;
        }
    }
    else if (**Fmt == '*')
    {
        *Width = WIDTH_STAR;
        *Out++ = (CHAR) *(*Fmt)++;
        if (isdigit(**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(**Fmt))
            {
                *Out++ = (CHAR) *(*Fmt)++;
            }
        }
    }

    /* grab precision specifier */
    if (**Fmt == '.')
    {
        *Out++ = (CHAR) *(*Fmt)++;
        if (isdigit(**Fmt))
        {
            TempStrPtr = TempStr;
            while (isdigit(**Fmt))
            {
                *TempStrPtr++ = (CHAR) **Fmt;
                *Out++ = (CHAR) *(*Fmt)++;
            }
            *TempStrPtr = 0; /* end string */
            *Precision = atoi(TempStr);
            if (*Precision < 0)
            {
                ERROR("atoi returned a negative value indicative of an overflow.\n");
                pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR);
                return Result;
            }
        }
        else if (**Fmt == '*')
        {
            *Precision = PRECISION_STAR;
            *Out++ = (CHAR) *(*Fmt)++;
            if (isdigit(**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(**Fmt))
                {
                    *Out++ = (CHAR) *(*Fmt)++;
                }
            }
        }
        else
        {
            *Precision = PRECISION_DOT;
        }
    }

#ifdef HOST_64BIT
    if (**Fmt == 'p')
    {
        *Prefix = PFF_PREFIX_LONGLONG;
    }
#endif
    if ((*Fmt)[0] == 'I')
    {
        /* grab prefix of 'I64' for __int64 */
        if ((*Fmt)[1] == '6' && (*Fmt)[2] == '4')
        {
            /* convert to 'll' so that Unix snprintf can handle it */
            *Fmt += 3;
            *Prefix = PFF_PREFIX_LONGLONG;
        }
        /* grab prefix of 'I32' for __int32 */
        else if ((*Fmt)[1] == '3' && (*Fmt)[2] == '2')
        {
            *Fmt += 3;
        }
        else
        {
            ++(*Fmt);
    #ifdef HOST_64BIT
            /* convert to 'll' so that Unix snprintf can handle it */
            *Prefix = PFF_PREFIX_LONGLONG;
    #endif
        }
    }
    /* grab a prefix of 'h' */
    else if (**Fmt == 'h')
    {
        *Prefix = PFF_PREFIX_SHORT;
        ++(*Fmt);
    }
    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_W;
        }
        if (**Fmt == 'l')
        {
            *Prefix = PFF_PREFIX_LONGLONG;
            ++(*Fmt);
        }
    }
    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 || *Prefix == PFF_PREFIX_LONG_W)
        {
            *Out++ = 'l';
            *Prefix = PFF_PREFIX_LONG;
        }
        *Out++ = 'c';
        ++(*Fmt);
        Result = TRUE;
    }
    /* grab type 's' */
    else if (**Fmt == 's' || **Fmt == 'S' )
    {
        if ( **Fmt == 'S' )
        {
           *Type = PFF_TYPE_WSTRING;
        }
        else
        {
            *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 */
    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 || *Prefix == PFF_PREFIX_LONG_W)
        {
            *Out++ = 'l';
            *Prefix = PFF_PREFIX_LONG;
        }
        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*/
        if (*Prefix == PFF_PREFIX_LONG_W)
        {
            *Prefix = PFF_PREFIX_LONG;
        }

        *Type = PFF_TYPE_FLOAT;
        *Out++ = *(*Fmt)++;
        Result = TRUE;
    }
    else if (**Fmt == 'n')
    {
        if (*Prefix == PFF_PREFIX_LONG_W)
        {
            *Prefix = PFF_PREFIX_LONG;
        }

        if (*Prefix == PFF_PREFIX_SHORT)
        {
            *Out++ = 'h';
        }
        *Out++ = *(*Fmt)++;
        *Type = PFF_TYPE_N;
        Result = TRUE;
    }
    else if (**Fmt == 'p')
    {
        *Type = PFF_TYPE_P;
        (*Fmt)++;

        if (*Prefix == PFF_PREFIX_LONGLONG)
        {
            if (*Precision == PRECISION_DEFAULT)
            {
                *Precision = 16;
                *Out++ = '.';
                *Out++ = '1';
                *Out++ = '6';
            }
            /* native *printf does not support %I64p
               (actually %llp), so we need to cheat a little bit */
            *Out++ = 'l';
            *Out++ = 'l';
        }
        else
        {
            if (*Precision == PRECISION_DEFAULT)
            {
                *Precision = 8;
                *Out++ = '.';
                *Out++ = '8';
            }
            if (*Prefix == PFF_PREFIX_LONG_W)
            {
                *Prefix = PFF_PREFIX_LONG;
            }
        }
        *Out++ = 'X';
        Result = TRUE;
    }

    *Out = 0;  /* end the string */
    free(TempStr);
    return Result;
}