wattype.c

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

C
1,874
字号
}

dip_status FindTypeHandle( imp_image_handle *ii, imp_mod_handle im,
                unsigned index, imp_type_handle *it )
{
    typeinfo            typeld;
    dip_status          ret;

    PushLoad( &typeld );
    ret = DoFindTypeHandle( ii, im, index, it );
    PopLoad();
    return( ret );
}

typedef enum { ET_ENUM = 1, ET_TYPE = 2 } type_or_enum;

enum { STRUCT_IDX, CLASS_IDX, UNION_IDX, ENUM_IDX, NUM_IDX };
static const char *Scopes[] = { "struct", "class", "union", "enum", NULL };


struct name_state {
    unsigned    scope_idx[NUM_IDX];
    unsigned    curr_idx;
    unsigned    hit_eof         : 1;
    byte        *header;
};

static void InitNameState( struct name_state *state )
{
    memset( state, 0, sizeof( *state ) );
}

static byte *FindAName( struct name_state *state, byte *p,
                        type_or_enum which, lookup_item *li )
{
    byte        *name;
    unsigned    len;
    int         (*comp)();
    unsigned    index;
    unsigned    i;
    unsigned    type;

    if( li->case_sensitive ) {
        comp = memcmp;
    } else {
        comp = memicmp;
    }
    for( ; p < Type->end; p = NEXT_TYPE( p ) ) {
        state->curr_idx++;
        switch( p[1] & CLASS_MASK ) {
        case ENUM_TYPE:
            if( p[1] == ENUM_TYPE+ENUM_LIST ) {
                state->header = p;
            } else {
                state->curr_idx--;
            }
            if( (which & ET_ENUM) == 0 ) continue;
            break;
        case NAME_TYPE:
            if( ( p[1] & SUBCLASS_MASK ) == TYPE_EOF ) {
                state->hit_eof = 1;
                return( NULL );
            }
            if( (which & ET_TYPE) == 0 ) continue;
            switch( p[1] & SUBCLASS_MASK ) {
            case TYPE_SCALAR:
                type = ST_TYPE;
                break;
            case TYPE_SCOPE:
                name = NamePtr( p );
                len = *p - (name-p);
                for( i = 0; i < NUM_IDX; ++i ) {
                    if( memcmp( name, Scopes[i], len ) == 0 ) {
                        state->scope_idx[i] = state->curr_idx;
                        break;
                    }
                }
                continue;
            case TYPE_NAME:
                GetIndex( p + 2, &index );
                if( index == 0 ) {
                    type = ST_TYPE;
                } else {
                    for( i = 0; i < NUM_IDX; ++i ) {
                        if( state->scope_idx[i] == index ) break;
                    }
                    type = ST_STRUCT_TAG+i;
                }
                break;
            default:
                continue;
            }
            if( type == ST_TYPE && li->type == ST_NONE ) break;
            if( type == li->type ) break;
            continue;
        case STRUCT_TYPE:
            if( p[1] == STRUCT_TYPE+STRUCT_LIST ) {
                state->header = p;
            } else {
                state->curr_idx--;
            }
            continue;
        default:
            continue;
        }
        name = NamePtr( p );
        len = *p - (name-p);
        if( len != li->name.len ) continue;
        if( comp( name, li->name.start, len ) != 0 ) continue;
        return( p );
    }
    return( NULL );
}

search_result LookupTypeName( imp_image_handle *ii, imp_mod_handle im,
                lookup_item *li, imp_type_handle *it )
{
    unsigned            entry;
    struct name_state   state;
    byte                *p;
    typeinfo            typeld;
    search_result       sr;

    PushLoad( &typeld );
    InitNameState( &state );
    sr = SR_NONE;
    entry = 0;
    for( ;; ) {
        if( LoadType( ii, im, entry ) != DS_OK ) break;
        p = FindAName( &state, Type->start, ET_TYPE, li );
        if( p != NULL ) {
            it->im = im;
            it->f.all = 0;
            it->t.entry = entry;
            it->t.offset = p - Type->start;
            sr = SR_EXACT;
            break;
        }
        if( state.hit_eof ) break;
        ++entry;
    }
    PopLoad();
    return( sr );
}

static search_result SearchEnumTypeName( imp_image_handle *ii, imp_mod_handle im,
                         lookup_item *li, void *d, type_or_enum which )
{
    unsigned            entry;
    struct name_state   state;
    search_result       sr;
    imp_sym_handle      *is;
    byte                *p;
    typeinfo            typeld;

    PushLoad( &typeld );
    sr = SR_NONE;
    InitNameState( &state );
    entry = 0;
    for( ;; ) {
        if( LoadType( ii, im, entry ) != DS_OK ) break;
        p = Type->start;
        for( ;; ) {
            p = FindAName( &state, p, which, li );
            if( p == NULL ) break;
            is = DCSymCreate( ii, d );
            is->im = im;
            is->name_off = NamePtr( p ) - p;
            is->u.typ.t.entry = entry;
            is->u.typ.t.offset = p - Type->start;
            if( (p[1] & CLASS_MASK) == ENUM_TYPE ) {
                is->type = SH_CST;
                is->u.typ.h.offset = state.header - Type->start;
                is->u.typ.h.entry = entry;
            } else {
                is->type = SH_TYP;
            }
            sr = SR_EXACT;
            /* we really should continue searching for more names that
               match, but we're going to early out because I know that
               the symbolic info format is too weak to have more than
               one type name or enum const that will match */
            PopLoad();
            return( sr );
        }
        if( state.hit_eof ) break;
        ++entry;
    }
    PopLoad();
    return( sr );
}

search_result SearchEnumName( imp_image_handle *ii, imp_mod_handle im,
                         lookup_item *li, void *d )
{
    return( SearchEnumTypeName( ii, im, li, d, ET_ENUM ) );
}

search_result SearchTypeName( imp_image_handle *ii, imp_mod_handle im,
                         lookup_item *li, void *d )
{
    return( SearchEnumTypeName( ii, im, li, d, ET_TYPE ) );
}

walk_result DIPENTRY DIPImpWalkTypeList( imp_image_handle *ii, imp_mod_handle im,
                        IMP_TYPE_WKR *wk, imp_type_handle *it, void *d )
{
    byte        *p;
    byte        kind;
    typeinfo    typeld;
    walk_result wr;

    PushLoad( &typeld );
    it->im = im;
    it->f.all = 0;
    it->t.entry = 0;
    for( ;; ) {
        if( LoadType( ii, im, it->t.entry ) != DS_OK ) break;
        for( p = Type->start; p < Type->end; p = NEXT_TYPE( p ) ) {
            kind = p[1];
            switch( kind & CLASS_MASK ) {
            case NAME_TYPE:
                switch( kind & SUBCLASS_MASK ) {
                case TYPE_SCOPE:
                case TYPE_CUE_TABLE:
                    continue;
                case TYPE_EOF:
                    goto done;
                }
                break;
            case ENUM_TYPE :
                if( (kind & SUBCLASS_MASK) != ENUM_LIST ) {
                    continue;
                }
                break;
            case STRUCT_TYPE :
                if( (kind & SUBCLASS_MASK) != STRUCT_LIST ) {
                    continue;
                }
                break;
            case PROC_TYPE:
                if( (kind & SUBCLASS_MASK) == PROC_EXT_PARMS ) {
                    continue;
                }
                break;
            }
            it->t.offset = p - Type->start;
            wr = wk( ii, it, d );
            if( wr != WR_CONTINUE ) {
                PopLoad();
                return( wr );
            }
        }
        it->t.entry++;
    }
done:
    PopLoad();
    return( WR_CONTINUE );
}

static void ScalarInfo( unsigned info, type_info *ti )
{
    ti->size = (info & SCLR_LEN_MASK) + 1;
    switch( info & SCLR_CLASS_MASK ) {
    case SCLR_INTEGER:
        ti->modifier = TM_SIGNED;
        ti->kind = TK_INTEGER;
        break;
    case SCLR_UNSIGNED:
        ti->modifier = TM_UNSIGNED;
        ti->kind = TK_INTEGER;
        break;
    case SCLR_FLOAT:
        ti->kind = TK_REAL;
        break;
    case SCLR_VOID:
        ti->kind = TK_VOID;
        break;
    case SCLR_COMPLEX:
        ti->kind = TK_COMPLEX;
        break;
    }
}


static dip_status GetTypeInfo(imp_image_handle *ii, imp_type_handle *it,
                    location_context *lc, type_info *ti, unsigned *ndims )
{
    byte                *p;
    byte                subkind;
    imp_type_handle     tmp;
    address             addr;
    array_info          info;
    byte                is_char;
    byte                save_major;
    dip_status          ret;
    unsigned            index;
    unsigned            count;
    unsigned long       max;
    addr_off            offset;
    unsigned            skip;
    typeinfo            typeld;
    location_list       ll;

    PushLoad( &typeld );
    ti->kind = TK_NONE;
    ti->modifier = TM_NONE;
    ti->size = 0;
    if( it->f.s.gbl ) {
        ti->kind = GblTypeClassify( it->t.offset );
    } else if( it->f.s.sclr ) {
        ScalarInfo( it->t.offset, ti );
    } else {
        is_char = it->f.s.chr;
        ret = LoadType( ii, it->im, it->t.entry );
        if( ret != DS_OK ) {
            PopLoad();
            return( ret );
        }
        if( !GetRealTypeHandle( ii, it ) ) {
            PopLoad();
            return( DS_FAIL );
        }
        p = it->t.offset + Type->start;
        subkind = p[1] & SUBCLASS_MASK;
        switch( p[1] & CLASS_MASK ) {
        case NAME_TYPE:
            if( subkind == TYPE_SCALAR ) {
                ScalarInfo( p[2], ti );
                if( is_char && ti->kind == TK_INTEGER && ti->size == 1 ) {
                    ti->kind = TK_CHAR;
                }
            }
            break;
        case ARRAY_TYPE:
            FreeLoad();
            save_major = it->f.s.col_major;
            it->f.s.col_major = 0;
            ImpInterface.type_array_info( ii, it, lc, &info, NULL );
            ImpInterface.type_base( ii, it, &tmp, NULL, NULL );
            GetTypeInfo( ii, &tmp, lc, ti, ndims );
            it->f.s.col_major = save_major;
            if( ndims != NULL ) ++*ndims;
            ti->size *= info.num_elts;
            ti->modifier = TM_NONE;
            ti->kind = TK_ARRAY;
            Type->start = NULL;
            break;
        case SUBRANGE_TYPE:
            ImpInterface.type_base( ii, it, &tmp, NULL, NULL );
            ImpInterface.tipe_info( ii, &tmp, lc, ti );
            break;
        case POINTER_TYPE:
            {
                static const char PSize[] = {2,4,4,2,4,4,4,6,4,6};
                #define N TM_NEAR
                #define F TM_FAR
                #define H TM_HUGE
                #define D TM_FLAG_DEREF
                static const char PMods[] = {N,F,H,N|D,F|D,H|D,N,F,N|D,F|D};

                ti->size = PSize[subkind];
                ti->modifier = PMods[subkind];
                ti->kind = TK_POINTER;
            }
            break;
        case ENUM_TYPE:
            ScalarInfo( p[4], ti );
            ti->kind = TK_ENUM;
            break;
        case STRUCT_TYPE:
            if( *p > 4 ) {
                ti->size = *(unsigned_32 *)(p+4);
            } else {
                max = 0;
                count = *(unsigned_16 *)(p+2);
                while( count != 0 ) {
                    skip = 2;
                    p = NEXT_TYPE( p );
                    switch( p[1] ) {
                    case STRUCT_TYPE+ST_BIT_BYTE:
                        skip += 2;
                        /* fall through */
                    case STRUCT_TYPE+ST_FIELD_BYTE:
                        skip += 1;
                        offset = *(unsigned_8 *)(p+2);
                        break;
                    case STRUCT_TYPE+ST_BIT_WORD:
                        skip += 2;
                        /* fall through */
                    case STRUCT_TYPE+ST_FIELD_WORD:
                        skip += 2;
                        offset = *(unsigned_16 *)(p+2);
                        break;
                    case STRUCT_TYPE+ST_BIT_LONG:
                        skip += 2;
                        /* fall through */
                    case STRUCT_TYPE+ST_FIELD_LONG:
                        skip += 4;
                        offset = *(unsigned_32 *)(p+2);
                        break;
                    case STRUCT_TYPE+ST_FIELD_LOC:
                    case STRUCT_TYPE+ST_BIT_LOC:
                    case STRUCT_TYPE+ST_INHERIT:
                        skip = 0;
                        break;
                    }
                    if( skip > 0 ) {
                        GetIndex( p + skip, &index );
                        /* Pulling a trick. We know that the size
                           field will only be absent in older objects,
                           and thus will only have one type section per
                           module. */
                        FindTypeHandle( ii, it->im, index, &tmp );
                        GetTypeInfo( ii, &tmp, lc, ti, NULL );
                        offset += ti->size;
                        if( offset > max ) max = offset;
                    }
                    --count;
                }
                ti->size = max;
            }
            ti->kind = TK_STRUCT;
            break;
        case PROC_TYPE:
            {
                static const char FMods[] = {
                    TM_NEAR,TM_FAR,TM_NEAR,TM_FAR
                };

                ti->modifier = FMods[subkind];
                ti->kind = TK_FUNCTION;
            }
            break;
        case CHAR_TYPE:
            switch( subkind ) {
            case CHAR_BYTE_LEN:
                ti->size = *(unsigned_8 *)(p+2);
                break;
            case CHAR_WORD_LEN:
                ti->size = *(unsigned_16 *)(p+2);
                break;
            case CHAR_LONG_LEN:
                ti->size = *(unsigned_32 *)(p+2);
                break;
            case CHAR_DESC_LEN:
                GetAddress( ii, p + 3, &addr, 0 );
                ti->size = GetScalar( addr, p[2] );
                break;
            case CHAR_DESC386_LEN:
                GetAddress( ii, p + 3, &addr, 1 );
                ti->size = GetScalar( addr, p[2] );
                break;
            case CHAR_DESC_LOC:
                EvalLocation( ii, lc, p + 3, &ll );
                ti->size = GetScalar( ll.e[0].u.addr, p[2] );
                break;
            }
            ti->kind = TK_STRING;
        }
    }
    PopLoad();
    return( DS_OK );
}

dip_status DIPENTRY DIPImpTypeInfo(imp_image_handle *ii, imp_type_handle *it,
                        location_context *lc, type_info *ti )
{
    return( GetTypeInfo( ii, it, lc, ti, NULL ) );

⌨️ 快捷键说明

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