⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 undname.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
    return ret;
}

/******************************************************************
 *		get_class
 * Parses class as a list of parent-classes, separated by '@', terminated by '@@'
 * and stores the result in 'a' array. Each parent-classes, as well as the inner
 * element (either field/method name or class name), are stored as allocated
 * strings in the array.
 */
static BOOL get_class(struct parsed_symbol* sym)
{
    const char* ptr;

    while (*sym->current != '@')
    {
        switch (*sym->current)
        {
        case '\0': return FALSE;

        case '0': case '1': case '2': case '3':
        case '4': case '5': case '6': case '7':
        case '8': case '9':
            ptr = str_array_get_ref(&sym->stack, *sym->current++ - '0');
            if (!ptr) return FALSE;
            str_array_push(sym, ptr, -1, &sym->stack);
            break;
        case '?':
            if (*++sym->current == '$') 
            {
                const char*     name = ++sym->current;
                char*           full = NULL;
                char*           args = NULL;
                unsigned        num_mark = sym->stack.num;
                unsigned        start_mark = sym->stack.start;

                while (*sym->current++ != '@');

                sym->stack.start = sym->stack.num;
                str_array_push(sym, name, sym->current - name -1, &sym->stack);
                args = get_args(sym, NULL, FALSE, '<', '>');
                if (args != NULL)
                {
                    full = str_printf(sym, "%s%s", sym->stack.elts[num_mark], args);
                }
                if (!full) return FALSE;
                sym->stack.elts[num_mark] = full;
                sym->stack.num = num_mark + 1;
                sym->stack.start = start_mark;
            }
            break;
        default:
            ptr = sym->current;
            while (*sym->current++ != '@');
            str_array_push(sym, ptr, sym->current - 1 - ptr, &sym->stack);
            break;
        }
    }
    sym->current++;
    return TRUE;
}

/******************************************************************
 *		get_class_string
 * From an array collected by get_class, constructs the corresponding (allocated) 
 * string
 */
static char* get_class_string(struct parsed_symbol* sym, /*const struct array* a, */int start)
{
    int         i;
    size_t      len, sz;
    char*       ret;
    struct array *a = &sym->stack;
    for (len = 0, i = start; i < a->num; i++)
    {
        assert(a->elts[i]);
        len += 2 + strlen(a->elts[i]);
    }
    if (!(ret = und_alloc(sym, len - 1))) return NULL;
    for (len = 0, i = a->num - 1; i >= start; i--)
    {
        sz = strlen(a->elts[i]);
        memcpy(ret + len, a->elts[i], sz);
        len += sz;
        if (i > start)
        {
            ret[len++] = ':';
            ret[len++] = ':';
        }
    }
    ret[len] = '\0';
    return ret;
}

/******************************************************************
 *		get_calling_convention
 * Returns a static string corresponding to the calling convention described
 * by char 'ch'. Sets export to TRUE iff the calling convention is exported.
 */
static BOOL get_calling_convention(struct parsed_symbol* sym, char ch, 
                                   const char** call_conv, const char** exported,
                                   unsigned flags)
{
    *call_conv = *exported = NULL;

    if (!(flags & (UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ALLOCATION_LANGUAGE)))
    {
        if (flags & UNDNAME_NO_LEADING_UNDERSCORES)
        {
            if (((ch - 'A') % 2) == 1) *exported = "dll_export ";
            switch (ch)
            {
            case 'A': case 'B': *call_conv = "cdecl"; break;
            case 'C': case 'D': *call_conv = "pascal"; break;
            case 'E': case 'F': *call_conv = "thiscall"; break;
            case 'G': case 'H': *call_conv = "stdcall"; break;
            case 'I': case 'J': *call_conv = "fastcall"; break;
            case 'K': break;
            default: ERR("Unknown calling convention %c\n", ch); return FALSE;
            }
        }
        else
        {
            if (((ch - 'A') % 2) == 1) *exported = "__dll_export ";
            switch (ch)
            {
            case 'A': case 'B': *call_conv = "__cdecl"; break;
            case 'C': case 'D': *call_conv = "__pascal"; break;
            case 'E': case 'F': *call_conv = "__thiscall"; break;
            case 'G': case 'H': *call_conv = "__stdcall"; break;
            case 'I': case 'J': *call_conv = "__fastcall"; break;
            case 'K': break;
            default: ERR("Unknown calling convention %c\n", ch); return FALSE;
            }
        }
    }
    return TRUE;
}

/*******************************************************************
 *         get_simple_type
 * Return a string containing an allocated string for a simple data type
 */
static const char* get_simple_type(struct parsed_symbol* sym, char c)
{
    const char* type_string;
    
    switch (c)
    {
    case 'C': type_string = "signed char"; break;
    case 'D': type_string = "char"; break;
    case 'E': type_string = "unsigned char"; break;
    case 'F': type_string = "short"; break;
    case 'G': type_string = "unsigned short"; break;
    case 'H': type_string = "int"; break;
    case 'I': type_string = "unsigned int"; break;
    case 'J': type_string = "long"; break;
    case 'K': type_string = "unsigned long"; break;
    case 'M': type_string = "float"; break;
    case 'N': type_string = "double"; break;
    case 'O': type_string = "long double"; break;
    case 'X': type_string = "void"; break;
    case 'Z': type_string = "..."; break;
    default:  type_string = NULL; break;
    }
    return type_string;
}
/*******************************************************************
 *         get_extented_type
 * Return a string containing an allocated string for a simple data type
 */
static const char* get_extended_type(struct parsed_symbol* sym, char c)
{
    const char* type_string;
    
    switch (c)
    {
    case 'D': type_string = "__int8"; break;
    case 'E': type_string = "unsigned __int8"; break;
    case 'F': type_string = "__int16"; break;
    case 'G': type_string = "unsigned __int16"; break;
    case 'H': type_string = "__int32"; break;
    case 'I': type_string = "unsigned __int32"; break;
    case 'J': type_string = "__int64"; break;
    case 'K': type_string = "unsigned __int64"; break;
    case 'L': type_string = "__int128"; break;
    case 'M': type_string = "unsigned __int128"; break;
    case 'N': type_string = "bool"; break;
    case 'W': type_string = "wchar_t"; break;
    default:  type_string = NULL; break;
    }
    return type_string;
}

/*******************************************************************
 *         demangle_datatype
 *
 * Attempt to demangle a C++ data type, which may be datatype.
 * a datatype type is made up of a number of simple types. e.g:
 * char** = (pointer to (pointer to (char)))
 */
static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
                              struct array* pmt_ref, BOOL in_args)
{
    char                dt;
    BOOL                add_pmt = TRUE;

    assert(ct);
    ct->left = ct->right = NULL;
    
    switch (dt = *sym->current++)
    {
    case '_':
        /* MS type: __int8,__int16 etc */
        ct->left = get_extended_type(sym, *sym->current++);
        break;
    case 'C': case 'D': case 'E': case 'F': case 'G':
    case 'H': case 'I': case 'J': case 'K': case 'M':
    case 'N': case 'O': case 'X': case 'Z':
        /* Simple data types */
        ct->left = get_simple_type(sym, dt);
        add_pmt = FALSE;
        break;
    case 'T': /* union */
    case 'U': /* struct */
    case 'V': /* class */
        /* Class/struct/union */
        {
            unsigned    mark = sym->stack.num;
            const char* struct_name = NULL;
            const char* type_name = NULL;

            if (!get_class(sym) ||
                !(struct_name = get_class_string(sym, mark))) goto done;
            sym->stack.num = mark;
            if (!(sym->flags & UNDNAME_NO_COMPLEX_TYPE)) 
            {
                switch (dt)
                {
                case 'T': type_name = "union ";  break;
                case 'U': type_name = "struct "; break;
                case 'V': type_name = "class ";  break;
                }
            }
            ct->left = str_printf(sym, "%s%s", type_name, struct_name);
        }
        break;
    case '?':
        /* not all the time is seems */
        if (!(ct->left = get_modified_type(sym, '?'))) goto done;
        break;
    case 'A':
        if (!(ct->left = get_modified_type(sym, 'A'))) goto done;
        break;
    case 'Q':
        if (!(ct->left = get_modified_type(sym, in_args ? 'Q' : 'P'))) goto done;
        break;
    case 'P': /* Pointer */
        if (isdigit(*sym->current))
	{
            /* FIXME: P6 = Function pointer, others who knows.. */
            if (*sym->current++ == '6')
            {
                char*                   args = NULL;
                const char*             call_conv;
                const char*             exported;
                struct datatype_t       sub_ct;
                unsigned                mark = sym->stack.num;

                if (!get_calling_convention(sym, *sym->current++, 
                                            &call_conv, &exported, 
                                            sym->flags & ~UNDNAME_NO_ALLOCATION_LANGUAGE) ||
                    !demangle_datatype(sym, &sub_ct, pmt_ref, FALSE))
                    goto done;

                args = get_args(sym, pmt_ref, TRUE, '(', ')');
                if (!args) goto done;
                sym->stack.num = mark;

                ct->left  = str_printf(sym, "%s%s (%s*", 
                                       sub_ct.left, sub_ct.right, call_conv);
                ct->right = str_printf(sym, ")%s", args);
            }
            else goto done;
	}
	else if (!(ct->left = get_modified_type(sym, 'P'))) goto done;
        break;
    case 'W':
        if (*sym->current == '4')
        {
            char*               enum_name;
            unsigned            mark = sym->stack.num;
            sym->current++;
            if (!get_class(sym) ||
                !(enum_name = get_class_string(sym, mark))) goto done;
            sym->stack.num = mark;
            if (sym->flags & UNDNAME_NO_COMPLEX_TYPE)
                ct->left = enum_name;
            else
                ct->left = str_printf(sym, "enum %s", enum_name);
        }
        else goto done;
        break;
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
        /* Referring back to previously parsed type */
        ct->left = str_array_get_ref(pmt_ref, dt - '0');
        if (!ct->left) goto done;
        add_pmt = FALSE;
        break;
    case '$':
        if (sym->current[0] != '0') goto done;
        if (sym->current[1] >= '0' && sym->current[1] <= '9')
        {
            char*       ptr;
            ptr = und_alloc(sym, 2);
            ptr[0] = sym->current[1] + 1;
            ptr[1] = 0;
            ct->left = ptr;
            sym->current += 2;
        }
        else if ((sym->current[1] >= 'A' && sym->current[1] <= 'P') &&
                 sym->current[2] == '@')
        {
            char* ptr;
            ptr = und_alloc(sym, 3);
            if (sym->current[1] <= 'J')
            {
                ptr[0] = '0' + sym->current[1] - 'A';
                ptr[1] = 0;
            }
            else
            {
                ptr[0] = '1';
                ptr[1] = sym->current[1] - 'K' + '0';
                ptr[2] = 0;
            }
            ct->left = ptr;
            sym->current += 3;
        }
        else goto done;
        break;
    default :
        ERR("Unknown type %c\n", dt);
        break;
    }
    if (add_pmt && pmt_ref && in_args)
        str_array_push(sym, str_printf(sym, "%s%s", ct->left, ct->right), 
                       -1, pmt_ref);
done:
    
    return ct->left != NULL;
}

/******************************************************************
 *		handle_data
 * Does the final parsing and handling for a variable or a field in
 * a class.
 */
static BOOL handle_data(struct parsed_symbol* sym)
{
    const char*         access = NULL;
    const char*         member_type = NULL;
    const char*         modifier = NULL;
    struct datatype_t   ct;
    char*               name = NULL;
    BOOL                ret = FALSE;
    char                dt;

    /* 0 private static
     * 1 protected static
     * 2 public static
     * 3 private non-static
     * 4 protected non-static
     * 5 public non-static
     * 6 ?? static
     * 7 ?? static
     */

    if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS))
    {
        /* we only print the access for static members */
        switch (*sym->current)
        {
        case '0': access = "private: "; break;
        case '1': access = "protected: "; break;
        case '2': access = "public: "; break;
        } 
    }

    if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE))
    {
        if (*sym->current >= '0' && *sym->current <= '2')
            member_type = "static ";
    }

    name = get_class_string(sym, 0);

    switch (dt = *sym->current++)
    {
    case '0': case '1': case '2':
    case '3': case '4': case '5':
        {
            unsigned mark = sym->stack.num;
            if (!demangle_datatype(sym, &ct, NULL, FALSE)) goto done;
            if (!get_modifier(*sym->current++, &modifier)) goto done;
            sym->stack.num = mark;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -