demangle.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,208 行 · 第 1/5 页

C
2,208
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  C++ name demangling.
*
****************************************************************************/


#ifdef TEST
#define __DIP__
#endif
#ifdef __DIP__
#define __NO_STACK_CHECKING__
#endif

#if 0 || defined(TEST) || defined(DUMP)
#include <stdio.h>
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "walloca.h"
#include "watcom.h"
#include "demangle.h"

#ifndef _WCI86FAR
#define _WCI86FAR
#endif

#define IMPORT_PREFIX_STR       "__imp_"
#define IMPORT_PREFIX_LEN       ( sizeof( IMPORT_PREFIX_STR ) - 1 )

#undef  TRUE
#undef  FALSE
#define TRUE                    (1)
#define FALSE                   (0)
#define RECURSE_CHECK           (100*sizeof(int))
#define AUTO_BUFFER_SIZE        80
#define SUPPRESS_LIMIT          2
#define NULL_CHAR               '\0'

#define TRUNCATED_HASH_LEN      4

#define TRUNCATED_PREFIX1       'T'
#define MANGLE_PREFIX1          'W'
#define MANGLE_PREFIX2          '?'
#define PREFIX_EMBEDDED         '?'
#define MEMBER_POINTER          'M'
#define UNDERSCORE              '_'
#define PERIOD                  '.'
#define SCOPE_PREFIX            ':'
#define TEMPLATE_PREFIX         ':'
#define TEMPLATE_INT            '0'
#define TEMPLATE_TYPE           '1'
#define POSITIVE_INT            'Z'
#define NEGATIVE_INT            'Y'
#define OPNAME_PREFIX           '$'
#define SYMBOL_SUFFIX           '$'
#define MANGLE_RECURSE_SUFFIX   '$'
#define TYPE_NAME_PREFIX        '$'
#define TYPE_NAME_SUFFIX        '$'
#define THIS_QUAL_PREFIX        '.'
#define ARRAY_PREFIX            '['
#define ARRAY_SUFFIX            ']'
#define FUNCTION_PREFIX         '('
#define FUNCTION_SUFFIX         ')'
#define OP_FUN_PREFIX           'o'
#define REL_FUN_PREFIX          'r'
#define SPEC_TYPE_PREFIX        't'
#define WAT_FUN_PREFIX          'w'
#define ASGN_FUN_PREFIX         'a'

typedef char *(*realloc_fn_t)( char *, size_t );

#define MAX_REPLICATE   10
typedef struct replicate_desc {
    char const      *ptr;
    size_t          len;
} replicate_desc;

// static R/W data
static realloc_fn_t user_realloc;
static replicate_desc replicate[MAX_REPLICATE];
static int            next_replicate;

typedef struct output_desc {
    outfunPtr       outfun;
    void            *cookie;
    char const      *input;
    char const      *end;
    char const      *scope_ptr;
    char            *output;
    size_t          size;
    size_t          count;
    size_t          index;
    size_t          pending_loc;
    size_t          scope_len;
    int             suppress_output;
    int             scope_index;
    unsigned        ctdt_pending : 1;
    unsigned        cv_pending : 1;
    unsigned        scope_name : 1;
    unsigned        base_name : 1;
    unsigned        dllimport : 1;
} output_desc;

// the simple demangler uses these to output & count chars in the output buffer
// the parser callback uses these to extract the structure of the name
#define _output1( _a         ) (data->outfun)( &(data->cookie), _a,  0,  0 )
#define _output2( _a, _b     ) (data->outfun)( &(data->cookie), _a, _b,  0 )
#define _output3( _a, _b, _c ) (data->outfun)( &(data->cookie), _a, _b, _c )

typedef struct state_desc {
    size_t          prefix;
    size_t          suffix;
    char            right : 1;
} state_desc;

static char const _WCI86FAR dtorChar = '~';
static char const _WCI86FAR openParen = '(';
static char const _WCI86FAR closeParen = ')';
static char const _WCI86FAR signedPrefix[] = "signed ";
static char const _WCI86FAR operatorName[] = "operator ";
static char const _WCI86FAR deleteFunction[] = "delete";
static char const _WCI86FAR deleteArrayFunction[] = "delete []";
static char const _WCI86FAR anonymousEnum[] = "__anonymous_enum ";
static char const _WCI86FAR newFunction[] = "new";
static char const _WCI86FAR newArrayFunction[] = "new []";
static char const _WCI86FAR scopeSeparator[] = "::";
static char const _WCI86FAR templatePrefix[] = "<";
static char const _WCI86FAR templateSuffix[] = ">";
static char const _WCI86FAR templateSeparator[] = ",";
static char const _WCI86FAR arrayPrefix[] = "[";
static char const _WCI86FAR arraySuffix[] = "]";
static char const _WCI86FAR functionPrefix[] = "( ";
static char const _WCI86FAR functionSuffix[] = ")";
static char const _WCI86FAR functionSeparator[] = ", ";
static char const _WCI86FAR basedSuffix[] = ") ";
static char const _WCI86FAR basedStrPrefix[] = "\"";
static char const _WCI86FAR basedStrSuffix[] = "\"";
static char const _WCI86FAR basedSelf[] = "__self";
static char const _WCI86FAR basedVoid[] = "void";

// mangled character translations
typedef struct table_t {
    char const _WCI86FAR        *string;    // translated string
    char                        grouping;   // flavour of character
} table_t;

#define LOWER_TABLE_LIMIT           'A'

static table_t const _WCI86FAR translate_type_encoding[] = {
#define CHAR_UNUSED         0
#define CHAR_BASIC_TYPE     1
#define CHAR_POINTER        2
#define CHAR_MODIFIER       3
    /* 'A' */   { "char ",      CHAR_BASIC_TYPE },
    /* 'B' */   { "float ",     CHAR_BASIC_TYPE },
    /* 'C' */   { "char ",      CHAR_BASIC_TYPE },
    /* 'D' */   { "double ",    CHAR_BASIC_TYPE },
    /* 'E' */   { "... ",       CHAR_BASIC_TYPE },
    /* 'F' */   { "far ",       CHAR_MODIFIER },
    /* 'G' */   { "far16 ",     CHAR_MODIFIER },
    /* 'H' */   { "huge ",      CHAR_MODIFIER },
    /* 'I' */   { "int ",       CHAR_BASIC_TYPE },
    /* 'J' */   { "__based(",   CHAR_MODIFIER },
    /* 'K' */   { NULL,         CHAR_UNUSED },
    /* 'L' */   { "long ",      CHAR_BASIC_TYPE },
    /* 'M' */   { "::* ",       CHAR_POINTER },
    /* 'N' */   { "near ",      CHAR_MODIFIER },
    /* 'O' */   { NULL,         CHAR_UNUSED },
    /* 'P' */   { "* ",         CHAR_POINTER },
    /* 'Q' */   { "bool ",      CHAR_BASIC_TYPE },
    /* 'R' */   { "& ",         CHAR_POINTER },
    /* 'S' */   { "short ",     CHAR_BASIC_TYPE },
    /* 'T' */   { "long double ",CHAR_BASIC_TYPE },
    /* 'U' */   { "unsigned ",  CHAR_MODIFIER },
    /* 'V' */   { "void ",      CHAR_BASIC_TYPE },
    /* 'W' */   { "wchar_t ",   CHAR_BASIC_TYPE },
    /* 'X' */   { "const ",     CHAR_MODIFIER },
    /* 'Y' */   { "volatile ",  CHAR_MODIFIER },
    /* 'Z' */   { "__int64 ",   CHAR_BASIC_TYPE },
    /* '[' */   { NULL,         CHAR_UNUSED },
    /* '\' */   { NULL,         CHAR_UNUSED },
    /* ']' */   { NULL,         CHAR_UNUSED },
    /* '^' */   { NULL,         CHAR_UNUSED },
    /* '_' */   { "",           CHAR_BASIC_TYPE } // for ctor/dtor return type
};

static char _WCI86FAR * const _WCI86FAR operatorFunction[] = {
    /* A */ ">>",
    /* B */ "<<",
    /* C */ "!",
    /* D */ "[]",
    /* E */ "->",
    /* F */ "*",
    /* G */ "++",
    /* H */ "--",
    /* I */ "-",
    /* J */ "+",
    /* K */ "&",
    /* L */ "->*",
    /* M */ "/",
    /* N */ "%",
    /* O */ ",",
    /* P */ "()",
    /* Q */ "~",
    /* R */ "^",
    /* S */ "|",
    /* T */ "&&",
    /* U */ "||"
};
static char const _WCI86FAR * const _WCI86FAR relationalFunction[] = {
    /* A */ "==",
    /* B */ "!=",
    /* C */ "<",
    /* D */ "<=",
    /* E */ ">",
    /* F */ ">="
};
static char const _WCI86FAR * const _WCI86FAR assignmentFunction[] = {
    /* A */ "=",
    /* B */ "*=",
    /* C */ "+=",
    /* D */ "-=",
    /* E */ "/=",
    /* F */ "%=",
    /* G */ ">>=",
    /* H */ "<<=",
    /* I */ "&=",
    /* J */ "|=",
    /* K */ "^="
};
#define num_elements( __a ) (sizeof(__a) / sizeof(__a[0]))

typedef union key_desc {
    char        str[2];
    short       val;
} key_desc;
typedef struct assoc_desc {
    key_desc            u;
    char _WCI86FAR      *name;
} assoc_desc;

static assoc_desc const _WCI86FAR watcomObject[] = {
    { {"A*"},  "__internal" },
    { {"BI"},  "__onceonly" },
    { {"DA"},  "__arrdtorblk" },
    { {"DF"},  "__defarg" },
    { {"DI"},  "__debuginfo" },
    { {"DO"},  "__dtorobjblk" },
    { {"MP"},  "__mbrptrthunk" },
    { {"SI"},  "__staticinit" },
    { {"TH"},  "__throwblk" },
    { {"TI"},  "__typeid" },
    { {"TS"},  "__typesig" },
    { {"VA"},  "__rtti" },
    { {"VB"},  "__vbtbl" },
    { {"VF"},  "__vftbl" },
    { {"VM"},  "__vmtbl" },
    { {"VT"},  "__vfthunk" },
    { {"ST"},  "__typstattab" },
    { {"CM"},  "__stattabcmd" },
    { {"UN"},  "<unique>" },
};
#define MAX_WATCOM_OBJECT       num_elements( watcomObject )

#if 0 || defined(TEST) || defined(DUMP)
int no_errors;
unsigned errors;
#endif

static int scoped_name( output_desc *data, state_desc *state );
static int type_encoding( output_desc *data, state_desc *state );
static int recursive_mangled_name( output_desc *data, state_desc *state );

static void zapSpace( output_desc *data )
{
    if( data->output == NULL ) {
        /* count the characters mode */
        return;
    }
    if( data->index > data->size ) {
        return;
    }
    if( data->output[data->index-1] != ' ' ) {
        return;
    }
    data->count--;
    if( data->index != (data->count+1) ) {
        size_t last = min( data->size, data->count );
        if( last >= data->index ) {
            memmove( &data->output[data->index-1],
                     &data->output[data->index],
                     (last - data->index) + 1 );
        }
    }
    data->index--;
}

#define START_ADJUST    ( 1 << 8 )

static void emitChar( output_desc *data, char c )
{
    size_t adjust_size;
    size_t test_size;
    char *test_realloc;

    if( data->suppress_output > SUPPRESS_LIMIT ) {
        return;
    }
    data->count++;
    if( data->output == NULL ) {
        /* count the characters mode */
        return;
    }
    if( data->count == (data->size-1) ) {
        if( user_realloc != NULL ) {
            adjust_size = START_ADJUST;
            for(;;) {
                if( adjust_size == 0 ) {
                    return;
                }
                test_size = data->size + adjust_size;
                test_realloc = user_realloc( data->output, test_size );
                if( test_realloc != NULL ) break;
                adjust_size >>= 1;
            }
            data->output = test_realloc;
            data->size = test_size;
        }
    }
    if( data->index < data->size ) {
        if( data->index < (data->count-1) ) {
            size_t last = min( data->size, data->count );
            memmove( &data->output[data->index+1],
                     &data->output[data->index],
                     (last - data->index) - 1);
        }
        data->output[data->index] = c;
        data->index++;
    }
}

static void emitStr( output_desc *data, const char _WCI86FAR *p )
{
    if( p ) {
        while( *p ) {
            emitChar( data, *p );
            ++p;
        }
    }
}

#define setEmitIndex( data, idx ) ((data)->index = (idx))

static void resetEmitIndex( output_desc *data, size_t offset_from_end )
{
    size_t index;

    index = data->count - offset_from_end;
    if( index < data->size ) {
        data->index = index;
    } else {
        data->index = data->size-1;
    }
}

static void setSuppression( output_desc *data )
{
    if( data->suppress_output ) {
        data->suppress_output++;
    }
}

static void resetSuppression( output_desc *data )
{
    if( data->suppress_output ) {
        --data->suppress_output;
    }
}

static void forceSuppression( output_desc *data )
{
    if( data->suppress_output <= SUPPRESS_LIMIT ) {
        data->suppress_output += SUPPRESS_LIMIT+1;
    }
}

static void unforceSuppression( output_desc *data )
{
    if( data->suppress_output > SUPPRESS_LIMIT ) {
        data->suppress_output -= SUPPRESS_LIMIT+1;
    }
}

static void demangleEmit( void **cookie, dm_pts dp, int value, char const *ptr )
{
    output_desc *data = *((output_desc **)cookie);

    switch( dp ) {
    case DM_BASIC_TYPE:
    case DM_POINTER:
    case DM_ARRAY:
    case DM_FUNCTION:
    case DM_THIS_FUNCTION:
    case DM_UNMODIFIED_TYPE:
    case DM_BASED_ENCODING:
    case DM_MODIFIER_LIST:
    case DM_TEMPLATE_ARG:
    case DM_RECURSE_BEGIN:
    case DM_RECURSE_END:
    case DM_TEMPLATE_NAME:
    case DM_DESTRUCTOR:
    case DM_CONSTRUCTOR:
    case DM_OPERATOR_CONVERT:
    case DM_CTOR_DTOR_NAME:
    case DM_SCOPED_NAME:

⌨️ 快捷键说明

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