demangle.c

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

C
2,208
字号
        return( assignment_function( data, state ) );
        break;
    case REL_FUN_PREFIX:
        advanceChar( data );
        return( relational_function( data, state ) );
        break;
    case OP_FUN_PREFIX:
        advanceChar( data );
        return( operator_function( data, state ) );
        break;
    case SPEC_TYPE_PREFIX:
        advanceChar( data );
        return( special_type_names( data, state ) );
        break;
    case WAT_FUN_PREFIX:
        advanceChar( data );
        return( watcom_object( data, state ) );
        break;
    }
    return( FALSE );
}

static int name( output_desc *data, state_desc *state )
{
    char c;

    c = nextChar( data );
    if( isdigit( c ) ) {
        size_t len;
        char const *id;

        c = c - '0';
        // in case C++ compiler and demangler don't match; don't crash
        if( c >= next_replicate ) {
            id = "@";
            len = 1;
        } else {
            id = replicate[c].ptr;
            len = replicate[c].len;
        }
        if( data->ctdt_pending ) {
            _output2( DM_RESET_INDEX, data->pending_loc );
            _output1( DM_CTOR_DTOR_NAME );
            _output3( DM_IDENTIFIER, len, id );
            data->ctdt_pending = FALSE;
        }
        if( data->scope_name && data->scope_index == 0 ) {
            data->scope_name = FALSE;
            data->scope_ptr = id;
            data->scope_len = len;
        }
        _output2( DM_SET_INDEX, state->prefix );
        _output3( DM_IDENTIFIER, len, id );
        _output1( DM_EMIT_SPACE );
        advanceChar( data );
        return( TRUE );
    } else {
        char const *ptr = data->input;
        size_t  len = 0;
        while( is_identifier( c ) ) {
            len++;
            advanceChar( data );
            c = nextChar( data );
        }
        if( data->scope_name && data->scope_index == 0 ) {
            data->scope_name = FALSE;
            data->scope_ptr = ptr;
            data->scope_len = len;
        }
        if( c == SYMBOL_SUFFIX ) {
            advanceChar( data );
            if( data->ctdt_pending ) {
                _output2( DM_RESET_INDEX, data->pending_loc );
                _output1( DM_CTOR_DTOR_NAME );
                _output3( DM_IDENTIFIER, len, ptr );
                data->ctdt_pending = FALSE;
            }
            _output2( DM_SET_INDEX, state->prefix );
            _output3( DM_IDENTIFIER, len, ptr );
            _output1( DM_EMIT_SPACE );
            if( next_replicate < MAX_REPLICATE ) {
                replicate[next_replicate].ptr = ptr;
                replicate[next_replicate].len = len;
                next_replicate++;
            }
            return( TRUE );
        }
    }
    return( FALSE );
}

static int sym_name( output_desc *data, state_desc *state )
{
    _output1( DM_NAME );
    if( nextChar( data ) == OPNAME_PREFIX ) {
        advanceChar( data );
        return( op_name( data, state ) );
    } else {
        return( name( data, state ) ) ;
    }
}

static int scope( output_desc *data, state_desc *state, size_t *symbol_length )
{
    char c;

    _output1( DM_SCOPE );
    if( data->scope_name && data->scope_index > 0 ) {
        data->scope_index--;
    }
    c = nextChar( data );
    if( c == PREFIX_EMBEDDED ) {
        advanceChar( data );
        if( check_recurse() ) {
            return( recursive_mangled_name( data, state ) );
        }
    } else if( c == TEMPLATE_PREFIX ) {
        auto state_desc new_state;
        advanceChar( data );
        new_state = *state;
        new_state.suffix = data->count - state->prefix - *symbol_length;
        return( template_name( data, &new_state ) );
    } else {
        int rc = sym_name( data, state );
        *symbol_length = data->index - state->prefix - 1;
        return( rc );
    }
    return( FALSE );
}

static int scoped_name( output_desc *data, state_desc *state )
{
    size_t symbol_length;

    _output1( DM_SCOPED_NAME );
    if( sym_name( data, state ) ) {
        symbol_length = data->index - state->prefix - 1;
        while( nextChar( data ) == SCOPE_PREFIX ) {
            _output2( DM_SET_INDEX, state->prefix );
            if( *(data->input + 1) != TEMPLATE_PREFIX ) {
                _output1( DM_SCOPE_SEPARATOR );
            }
            advanceChar( data );
            if( !scope( data, state, &symbol_length ) ) {
                return( FALSE );
            }
            _output1( DM_ZAP_SPACE );
        }
        return( TRUE );
    }
    return( FALSE );
}

static int mangled_name( output_desc *data )
{
    auto state_desc new_state;

    _output1( DM_MANGLED_NAME );
    new_state.prefix = 0;
    new_state.suffix = 0;
    new_state.right = FALSE;
    if( scoped_name( data, &new_state ) ) {
        _output2( DM_RESET_INDEX, 0 );
        _output1( DM_ZAP_SPACE );
        return( type_encoding( data, &new_state ) );
    }
    return( FALSE );
}

#ifndef __LIB__
static int full_mangled_name( output_desc *data )
{
    unsigned advances;

    advances = 1;
    if( strRecog( data, IMPORT_PREFIX_STR, IMPORT_PREFIX_LEN ) ) {
        data->dllimport = 1;
    }
    switch( nextChar( data ) ) {
    case TRUNCATED_PREFIX1:
        advances += TRUNCATED_HASH_LEN;
        _output1( DM_TRUNCATED_NAME );
        /* fall through */
    case MANGLE_PREFIX1:
        advanceChar( data );
        if( nextChar( data ) == MANGLE_PREFIX2 ) {
            for( ; advances != 0; --advances ) {
                advanceChar( data );
                if( nextChar( data ) == NULL_CHAR ) {
                    return( FALSE );
                }
            }
            return( mangled_name( data ) );
        }
        break;
    }
    return( FALSE );
}

static void do_demangle( output_desc *data )
{
    #if 0 || defined(TEST)
    char const *input = data->input;
    #endif

    if( !full_mangled_name( data ) ) {
        #if 0 || defined(TEST)
        if( ! no_errors ) {
            size_t terminateOutput( output_desc * );
            ++errors;
            printf( "ERROR: full_mangled_name failed\n" );
            printf( "in:-->%s<--\n", input );
            printf( "remaining:-->%s<--\n", data->input );
            terminateOutput( data );
            printf( "output:-->%s<--\n", data->output );
        }
        #endif
    } else {
        #if 0 || defined(TEST)
            if( nextChar( data ) != NULL_CHAR ) {
                ++errors;
                printf( "ERROR: full_mangled_name failed to consume all\n" );
                printf( "-->%s<--\n", input );
            }
        #endif
    }
}

static void do_copy( output_desc *data )
{
    char const *ptr;
    int len;
    char c;

    ptr = data->input;
    len = 0;
    c = nextChar( data );
    advanceChar( data );
    while( c ) {
        len++;
        c = nextChar( data );
        advanceChar( data );
    }
    _output3( DM_COPY_STRING, len, ptr );
}
#endif

static void init_globals( realloc_fn_t reallocator )
{
    next_replicate = 0;
    user_realloc = reallocator;
}

static void init_descriptor( output_desc *data,
                             outfunPtr ofn, void *cookie,
                             char const *input, size_t len,
                             char *output, size_t size )
{
    data->outfun = ofn;
    data->cookie = cookie;
    data->end = NULL;
    if( len != 0 ) {
        /* length of mangled name is known */
        data->end = input + len;
    }
    data->input = input;
    data->output = output;
    data->scope_ptr = NULL;
    data->size = size;
    data->count = 0;
    data->index = 0;
    data->pending_loc = 0;
    data->scope_len = 0;
    data->suppress_output = 1;
    data->scope_index = 0;
    data->ctdt_pending = 0;
    data->cv_pending = 0;
    data->scope_name = 0;
    data->base_name = 0;
    data->dllimport = 0;
}

static size_t terminateOutput( output_desc *data )
{
    size_t outlen;

    outlen = data->count;
    if( data->output != NULL ) {
        /* name may have been truncated */
        if( outlen >= data->size ) {
            outlen = data->size-1;
        }
        if( outlen > 0 ) {
            if( data->output[outlen-1] == ' ' ) {
                --outlen;
            }
        }
        data->output[outlen] = '\0';
    }
    /* size does not include '\0' */
    return( outlen );
}

static size_t demangle_recursive( char const *input, char *output, size_t size )
{
    realloc_fn_t save_reallocator;
    auto output_desc data;

    save_reallocator = user_realloc;
    user_realloc = NULL;
    init_descriptor( &data, &demangleEmit, &data, input, 0, output, size );
    if( !mangled_name( &data ) ) {
        #if 0 || defined(TEST)
            ++errors;
            printf( "ERROR: mangled_name failed\n" );
            printf( "-->%s<--\n", input );
        #endif
    }
    terminateOutput( &data );
    user_realloc = save_reallocator;
    return( data.input - input );
}

static int recursive_mangled_name( output_desc *data, state_desc *state )
{
    auto char buff[AUTO_BUFFER_SIZE];

    _output1( DM_RECURSE_BEGIN );
    data->input += demangle_recursive( data->input, buff, sizeof( buff ) );
    _output1( DM_RECURSE_END );
    _output2( DM_SET_INDEX, state->prefix );
    _output3( DM_COPY_STRING, 0, buff );
    return( TRUE );
}

#ifdef __LIB__
_WCRTLINK
#endif
size_t __demangle_t(                            // DEMANGLE A C++ TYPE
    char const *input,                          // - mangled C++ type
    size_t len,                                 // - length of mangled type
    char *output,                               // - for demangled C++ type
    size_t size )                               // - size of output buffer
{
    size_t outlen;
    auto output_desc data;
    auto state_desc new_state;

    init_globals( NULL );
    init_descriptor( &data, &demangleEmit, &data, input, len, output, size );
    data.suppress_output = 0;
    new_state.prefix = 0;
    new_state.suffix = 0;
    new_state.right = FALSE;
    type_encoding( &data, &new_state );
    outlen = terminateOutput( &data );
    /* size does not include '\0' */
    return( outlen );
}

#ifndef __LIB__
size_t __demangle_l(                            // DEMANGLE A C++ NAME
    char const *input,                          // - mangled C++ name
    size_t len,                                 // - length of mangled name
    char *output,                               // - for demangled C++ name
    size_t size )                               // - size of output buffer
{
    int                 mangled;
    size_t              outlen;
    auto output_desc    data;

    init_globals( NULL );
    mangled = __is_mangled( input, len );
    init_descriptor( &data, &demangleEmit, &data, input, len, output, size );
    if( mangled ) {
        do_demangle( &data );
    } else {
        do_copy( &data );
    }
    outlen = terminateOutput( &data );
    /* size does not include '\0' */
    return( outlen );
}

size_t __demangle_r(                            // DEMANGLE A C++ NAME
    char const *input,                          // - mangled C++ name
    size_t len,                                 // - length of mangled name
    char **output,                              // - for demangled C++ name
    size_t size,                                // - size of output buffer
    char * (*realloc)( char *, size_t ) )       // - size adjuster for output
{
    char                *output_buff;
    int                 mangled;
    size_t              outlen;
    auto output_desc    data;

    init_globals( realloc );
    mangled = __is_mangled( input, len );
    output_buff = NULL;
    if( output != NULL ) {
        output_buff = *output;
    }
    init_descriptor( &data, &demangleEmit, &data, input, len, output_buff, size );
    data.suppress_output = 0;
    if( mangled ) {
        do_demangle( &data );
    } else {
        do_copy( &data );
    }
    outlen = terminateOutput( &data );
    if( output != NULL ) {
        *output = data.output;
    }
    /* size does not include '\0' */
    return( outlen );
}

int __scope_name(                               // EXTRACT A C++ SCOPE
    char const *input,                          // - mangled C++ name
    size_t len,                                 // - length of mangled name
    unsigned index,                             // - scope wanted
    char const **scope,                         // - location of name
    size_t *size )                              // - size of output buffer
{                                               // returns TRUE on success
    int                 mangled;
    auto output_desc    data;

    init_globals( NULL );
    *scope = NULL;
    *size = 0;
    mangled = __is_mangled( input, len );
    if( !mangled ) {
        return( FALSE );
    }
    init_descriptor( &data, &demangleEmit, &data, input, len, NULL, 0 );
    data.scope_name = TRUE;
    data.scope_index = index;
    do_demangle( &data );
    if( data.scope_len != 0 ) {
        *scope = data.scope_ptr;
        *size = data.scope_len;
        return( TRUE );

⌨️ 快捷键说明

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