int CoreVfprintf()

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;
}