PCCOR_SIGNATURE PrettyPrintSignature()

in CoreCLRProfiler/native/coreclr_headers/src/inc/formattype.cpp [175:419]


PCCOR_SIGNATURE PrettyPrintSignature(
    PCCOR_SIGNATURE typePtr,    // type to convert,
    unsigned typeLen,           // the lenght of 'typePtr'
    const char* name,           // can be "", the name of the method for this sig 0 means local var sig
    CQuickBytes *out,           // where to put the pretty printed string
    IMDInternalImport *pIMDI,   // ptr to IMDInternalImport class with ComSig
    const char* inlabel,        // prefix for names (NULL if no names required)
    BOOL printTyArity)
{
    CONTRACTL
    {
        THROWS;
        GC_NOTRIGGER;
    }
    CONTRACTL_END;

    unsigned numArgs;
    unsigned numTyArgs = 0;
    PCCOR_SIGNATURE typeEnd = typePtr + typeLen;
    unsigned ixArg= 0; //arg index
    char argname[1024];
    char label[MAX_PREFIX_SIZE];
    const char* openpar = "(";
    const char* closepar = ")";
    ParamDescriptor* pszArgName = NULL; // ptr to array of names (if provided by debug info)

    if(inlabel && *inlabel) // check for *inlabel is totally unnecessary, added to pacify the PREFIX
    {
        strcpy_s(label,MAX_PREFIX_SIZE,inlabel);
        ixArg = label[strlen(label)-1] - '0';
        label[strlen(label)-1] = 0;
        if(label[0] == '@') // it's pointer!
        {
#ifdef HOST_64BIT
            pszArgName = (ParamDescriptor*)_atoi64(&label[1]);
#else // !HOST_64BIT
            pszArgName = (ParamDescriptor*)(size_t)atoi(&label[1]);
#endif // HOST_64BIT
        }
    }

    // 0 means a local var sig
    if (name != 0)
    {
        // get the calling convention out
        unsigned callConv = CorSigUncompressData(typePtr);

        // should not be a local var sig
        _ASSERTE(!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG));

        if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
        {
            typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
            if (*name)
            {
                appendChar(out, ' ');
                appendStr(out, name);
            }
            return(typePtr);
        }

        if (callConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS)
            appendStr(out, KEYWORD("explicit "));

        if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS)
            appendStr(out, KEYWORD("instance "));

        if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST))
        {
          openpar = LTN();
          closepar = GTN();
        }
        else
        {
            const char* const callConvUndefined = (const char*)-1;
            static const char* const callConvNames[16] = {
                "",
                "unmanaged cdecl ",
                "unmanaged stdcall ",
                "unmanaged thiscall ",
                "unmanaged fastcall ",
                "vararg ",
                callConvUndefined, // field
                callConvUndefined, // local sig
                callConvUndefined, // property
                "unmanaged ",
                callConvUndefined,
                callConvUndefined,
                callConvUndefined,
                callConvUndefined,
                callConvUndefined,
                callConvUndefined
                };
            static_assert_no_msg(COUNTOF(callConvNames) == (IMAGE_CEE_CS_CALLCONV_MASK + 1));

            char tmp[32];
            unsigned callConvIdx = callConv & IMAGE_CEE_CS_CALLCONV_MASK;
            const char* name_cc = callConvNames[callConvIdx];
            if (name_cc == callConvUndefined)
            {
                sprintf_s(tmp, COUNTOF(tmp), "callconv(%u) ", callConvIdx);
                name_cc = tmp;
            }

            appendStr(out, KEYWORD(name_cc));
        }

        if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
        {
          numTyArgs = CorSigUncompressData(typePtr);
        }
        numArgs = CorSigUncompressData(typePtr);
        if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST))
        {
                // do return type
            if(pszArgName)
            {
                argname[0] = 0;
                DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg+numArgs].attr);
                appendStr(out,argname);
            }
            typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
            if(pszArgName)
            {
                argname[0] = ' '; argname[1] = 0;
                DumpMarshaling(pIMDI,argname,COUNTOF(argname),pszArgName[ixArg+numArgs].tok);
                appendStr(out,argname);
            }
            if(*name != 0)
            {
                appendChar(out, ' ');
                appendStr(out, name);
            }
            if((numTyArgs != 0)&&printTyArity)
            {
                appendStr(out,LTN());
                appendChar(out,'[');
                appendStrNum(out,numTyArgs);
                appendChar(out,']');
                appendStr(out,GTN());
            }
        }
    }
    else
    {
        // get the calling convention out
#ifdef _DEBUG
        unsigned callConv =
#endif
            CorSigUncompressData(typePtr);
#ifdef _DEBUG
        (void)callConv; //prevent "unused variable" warning from GCC
        // should be a local var sig
        _ASSERTE(callConv == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG);
#endif

        numArgs = CorSigUncompressData(typePtr);
    }

    appendStr(out, openpar);

    bool needComma = false;
    while(typePtr < typeEnd)
    {
        if(name) // printing the arguments
        {
            PREFIX_ASSUME(typePtr != NULL);
            if (*typePtr == ELEMENT_TYPE_SENTINEL)
            {
                if (needComma)
                    appendChar(out, ',');
                appendStr(out, "...");
                typePtr++;
            }
            else
            {
                if (numArgs <= 0)
                    break;
                if (needComma)
                    appendChar(out, ',');
                if(pszArgName)
                {
                    argname[0] = 0;
                    DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg].attr);
                    appendStr(out,argname);
                }
                typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
                if(inlabel)
                {
                    if(pszArgName)
                    {
                        argname[0] = ' '; argname[1] = 0;
                        DumpMarshaling(pIMDI,argname,COUNTOF(argname),pszArgName[ixArg].tok);
                        strcat_s(argname, COUNTOF(argname), ProperName(pszArgName[ixArg++].name));
                    }
                    else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++);
                    appendStr(out,argname);
                }
                --numArgs;
            }
        }
        else // printing local vars
        {
            if (numArgs <= 0)
                break;
            if(pszArgName)
            {
                if(pszArgName[ixArg].attr == 0xFFFFFFFF)
                {
                    CQuickBytes fake_out;
                    typePtr = PrettyPrintTypeOrDef(typePtr, &fake_out, pIMDI);
                    ixArg++;
                    numArgs--;
                    continue;
                }
            }
            if (needComma)
                appendChar(out, ',');
            if(pszArgName)
            {
                sprintf_s(argname,COUNTOF(argname),"[%d] ",pszArgName[ixArg].attr);
                appendStr(out,argname);
            }
            typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI);
            if(inlabel)
            {
                if(pszArgName)
                {
                    sprintf_s(argname,COUNTOF(argname)," %s",ProperLocalName(pszArgName[ixArg++].name));
                }
                else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++);
                appendStr(out,argname);
            }
            --numArgs;
        }
        needComma = true;
    }
        // Have we finished printing all the arguments?
    if (numArgs > 0) {
        appendStr(out, ERRORMSG(" [SIGNATURE ENDED PREMATURELY]"));
    }

    appendStr(out, closepar);
    return(typePtr);
}