can2td1.c

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

C
772
字号
STATIC void doStruct( cantype *type, type_rec *tr ) {
/*
    Assumes that caller has done tr = newType( name_hdl, size, TD_ID_STRUCT )
    but has not written any type info into the new type yet.  Does an
    endType( tr ).
*/
    struct_field    *field;
    struct_field    *field_stop;
    type_rec        *member;
    uint_8          bits;
    uint_32         offset;
    uint_8          bit_start;
    uint_32         new_offset;
    uint_8          new_bit_start;
    cantype         *member_type;

/**/myassert( type != NULL && type->class == CANT_STRUCT );

    /* write the field types and name/offset lists */
    member = tr->member;
    offset = 0;
    bit_start = 0;
    field = type->d.strct.fields;
    if( field != NULL ) {
        field_stop = field + type->d.strct.num_fields;
        while( field < field_stop ) {
            member_type = CanTFind( field->type );
/**/        myassert( member_type != NULL );
            new_offset = field->bit_offset >> 3;
            new_bit_start = field->bit_offset & 7;
            if( member_type->size >= 32 ||
                member_type->size == 16 ||
                member_type->size == 8 ) {
                bits = 0;
            } else {
                bits = member_type->size & 0x1f;
            }
            if( new_offset != offset || new_bit_start < bit_start ) {
                /* must create a NewOffset record */
                put8( member, TD_STRUCT_NEW_OFFSET );
                put32( member, new_offset );
                bit_start = 0;
            }
            if( new_bit_start > bit_start ) {
                /* must generate a padding field */
                put8( member, (new_bit_start-bit_start)<<TD_STRUCT_BITS_SHIFT );
                putName( member, NAME_NULL );
                putIndex( member, TD_ID_VOID );
            }
            if( field + 1 == field_stop ) {     /* last member */
                bits |= TD_STRUCT_LAST_MEMBER;
            }
            put8( member, bits );
            putName( member, field->name );
            putIndex( member, resolveType( field->type ) );
            offset = new_offset + ( member_type->size >> 3 );
            bit_start = new_bit_start + ( member_type->size & 7 );
            ++field;
        }
    }
    endType( tr );
}

STATIC void doEnum( cantype *type, type_rec *tr ) {
/*
    Assumes caller has done tr = newType( name, size, TD_ID_ENUM );
    Does an endType( tr ).

    FIXME there is no support for unsigned enumerated types, or for enumerated
    types of non-int size.
*/
    enum_const  *enum_c;
    enum_const  *enum_cstop;
    type_rec    *member;

/**/myassert( type != NULL && type->class == CANT_ENUM );
    putIndex( tr, resolveType( type->d.enumr.base_type ) );
    if( type->size > 16 ) {
        Fatal( MSG_ENUM_TOO_LARGE );
    }
    enum_c = type->d.enumr.consts;
    if( enum_c != NULL ) {
        enum_cstop = enum_c + type->d.enumr.num_consts;
        put16( tr, (int_16)enum_c->value );             /* low value */
        put16( tr, (int_16)(enum_cstop - 1)->value );   /* high value */
        member = tr->member;
        while( enum_c < enum_cstop ) {
            put8( member, 0 );
            putName( member, enum_c->name );
            put16( member, (int_16)enum_c->value );
            ++enum_c;
        }
    }
    endType( tr );
}

STATIC void typ2TypeDef( cantype *type ) {

    cantype     *base_type;
    type_rec    *tr;

/**/myassert( type != NULL && type->class == CANT_TYPEDEF );
    base_type = CanTFind( type->d.typdef.type );
    switch( type->d.typdef.scope ) {
    case CANT_SCOPE_NULL:
        /*
            This next line won't cause recursion because of the special
            case loop in resolveType().
        */
        type->extra = resolveType( base_type->hdl );
        break;
    case CANT_SCOPE_STRUCT:
/**/    myassert( base_type->class == CANT_STRUCT );
        tr = newLarge( type->d.typdef.name, base_type->size, TD_ID_STRUCT,
                TD_ID_VLSTRUCT );
        base_type->extra = type->extra = tr->idx;
        doStruct( base_type, tr );
        break;
    case CANT_SCOPE_UNION:
/**/    myassert( base_type->class == CANT_STRUCT );
        tr = newLarge( type->d.typdef.name, base_type->size, TD_ID_UNION,
                TD_ID_VLUNION );
        base_type->extra = type->extra = tr->idx;
        doStruct( base_type, tr );
        break;
    case CANT_SCOPE_ENUM:
/**/    myassert( base_type->class == CANT_ENUM );
        tr = newType( type->d.typdef.name, base_type->size, TD_ID_ENUM );
        base_type->extra = type->extra = tr->idx;
        doEnum( base_type, tr );
        break;
    default:
/**/    never_reach();
    }
}

STATIC void typ2SubRange( cantype *type ) {

    type_rec    *tr;
    uint_8      tid;

/**/myassert( type != NULL && type->class == CANT_SUBRANGE );
    if( type->sgned ) {
        if( type->size <= 8 ) {
            tid = TD_ID_SCHAR;
        } else if( type->size <= 16 ) {
            tid = TD_ID_SINT;
        } else if( type->size <= 32 ) {
            tid = TD_ID_SLONG;
        } else {
            Fatal( MSG_SUBR_TOO_LARGE );
        }
    } else {
        if( type->size <= 8 ) {
            tid = TD_ID_UCHAR;
        } else if( type->size <= 16 ) {
            tid = TD_ID_UINT;
        } else if( type->size <= 32 ) {
            tid = TD_ID_ULONG;
        } else {
            Fatal( MSG_SUBR_TOO_LARGE );
        }
    }
    switch( CanMisc.src_language ) {
    case CAN_LANG_C:        /* these can't use subrange types */
    case CAN_LANG_ASM:
        type->extra = tid;
        break;
    default:
        tr = newType( NAME_NULL, type->size, tid );
        type->extra = tr->idx;
        putIndex( tr, resolveType( type->d.subrng.base_type ) );
        put32( tr, type->d.subrng.low );
        put32( tr, type->d.subrng.high );
        endType( tr );
        break;
    }
}

STATIC void typ2ArrayZ( cantype *type ) {

    type_rec    *tr;

/**/myassert( type != NULL && ( type->class == CANT_ARRAY ||
        type->class == CANT_ARRAY_ZERO ) );
    tr = newLarge( NAME_NULL, type->size, TD_ID_CARRAY, TD_ID_VLARRAY );
    type->extra = tr->idx;
    putIndex( tr, resolveType( type->d.array.base_type ) );
    endType( tr );
}

STATIC void typ2Array( cantype *type ) {

    type_rec    *tr;

/**/myassert( type != NULL && type->class == CANT_ARRAY );
    switch( CanMisc.src_language ) {
    case CAN_LANG_C:        /* these can't use PARRAY */
    case CAN_LANG_ASM:
        typ2ArrayZ( type );
        break;
    default:
        tr = newType( NAME_NULL, type->size, TD_ID_PARRAY );
        type->extra = tr->idx;
        putIndex( tr, resolveType( type->d.array.base_type ) );
        putIndex( tr, resolveType( type->d.array.index_type ) );
        endType( tr );
        break;
    }
}

STATIC void typ2ArrayD( cantype *type ) {

/**/myassert( type != NULL && type->class == CANT_ARRAY_DESC );
    PrtMsg( WRN|MSG_UNS_ARRAY_DESC );
    type->extra = TD_TYPE_VOID;
}

STATIC void typ2Pointer( cantype *type ) {

    type_rec    *tr;
    uint_8      tid;

    if( type->d.pointr.class & CANT_PTR_386 ) {
        if( type->d.pointr.class & CANT_PTR_FAR ) {
            tid = TD_ID_FAR386;
        } else {
            tid = TD_ID_NEAR386;
        }
    } else {
        if( type->d.pointr.class & CANT_PTR_FAR ) {
            tid = TD_ID_FAR;
        } else {
            tid = TD_ID_NEAR;
        }
    }
    tr = newType( NAME_NULL, type->size, tid );
    type->extra = tr->idx;
    putIndex( tr, resolveType( type->d.pointr.base_type ) );
    if( type->d.pointr.class & CANT_PTR_HUGE ) {
        put8( tr, 1 );
    } else {
        put8( tr, 0 );
    }
    endType( tr );
}

STATIC void typ2Enum( cantype *type, int force ) {

    type_rec    *tr;

/**/myassert( type != NULL && type->class == CANT_ENUM );
    if( force ) {
        tr = newType( NAME_NULL, type->size, TD_ID_ENUM );
        type->extra = tr->idx;
        doEnum( type, tr );
    }
}

STATIC void typ2Struct( cantype *type, int force ) {

    type_rec    *tr;

/**/myassert( type != NULL && type->class == CANT_STRUCT );
    if( force ) {
        tr = newLarge( NAME_NULL, type->size, TD_ID_STRUCT, TD_ID_VLSTRUCT );
        type->extra = tr->idx;
        doStruct( type, tr );
    }
}

STATIC void typ2Procedure( cantype *type ) {

    type_rec    *tr;

/**/myassert( type != NULL && type->class == CANT_PROCEDURE );
    tr = newType( NAME_NULL, type->size, TD_ID_FUNCTION );
    type->extra = tr->idx;
    putIndex( tr, resolveType( type->d.proc.ret_type ) );
    if( CanMisc.src_language == CAN_LANG_PASCAL ) {
        if( type->d.proc.class & CANT_PROC_FAR ) {
            put8( tr, TD_FCN_PASCAL_FAR );
        } else {
            put8( tr, TD_FCN_PASCAL_NEAR );
        }
    } else {
        if( type->d.proc.class & CANT_PROC_FAR ) {
            put8( tr, TD_FCN_C_FAR );
        } else {
            put8( tr, TD_FCN_C_NEAR );
        }
    }
    put8( tr, 0 ); /* varargs indicator */
    endType( tr );
}

STATIC void typ2CharBlock( cantype *type ) {

/**/myassert( type != NULL && type->class == CANT_CHARBLOCK );
    type->extra = buildArray( type->size );
}

STATIC void typ2CharBlockI( cantype *type ) {

/**/myassert( type != NULL && type->class == CANT_CHARBLOCK_IND );
    PrtMsg( WRN|MSG_UNS_CHARBLOCK_IND );
    type->extra = TD_TYPE_VOID;
}

STATIC int typePass2( void *_type, void *_force ) {

    cantype *type = _type;
    int *force = _force;
/**/myassert( type != NULL );
    if( type->extra != 0 ) {    /* already processed */
        return( 0 );
    }
    switch( type->class ) {
    case CANT_TYPEDEF:      typ2TypeDef( type );            break;
    case CANT_SUBRANGE:     typ2SubRange( type );           break;
    case CANT_ARRAY:        typ2Array( type );              break;
    case CANT_ARRAY_ZERO:   typ2ArrayZ( type );             break;
    case CANT_ARRAY_DESC:   typ2ArrayD( type );             break;
    case CANT_POINTER:      typ2Pointer( type );            break;
    case CANT_ENUM:         typ2Enum( type, *force );       break;
    case CANT_STRUCT:       typ2Struct( type, *force );     break;
    case CANT_PROCEDURE:    typ2Procedure( type );          break;
    case CANT_CHARBLOCK:    typ2CharBlock( type );          break;
    case CANT_CHARBLOCK_IND:typ2CharBlockI( type );         break;
    }
    return( 0 );
}

void Can2TDT( void ) {
/******************/
    int force;

    if( CanMisc.types_present ) {
        realHdl = NameAdd( "real", 4 );
        imagHdl = NameAdd( "imag", 4 );
        nextIdx = 24;
        typeRecCarver = CarveCreate( sizeof( type_rec ), 8 );

        CanTWalk( NULL, typePass1 );
        force = 0;
        CanTWalk( &force, typePass2 );
        force = 1;
        CanTWalk( &force, typePass2 );

        CarveDestroy( typeRecCarver );
    }
}

STATIC int doTypeDef( void *_type, void *parm ) {

    cantype     *type = _type;
    obj_rec     *coment;
    const char  *name;
    size_t      name_len;

/**/myassert( type != NULL && parm == NULL );
    parm = parm;

    if( type->class == CANT_TYPEDEF &&
        type->d.typdef.scope == CANT_SCOPE_NULL ) {
        name = NameGet( type->d.typdef.name );
        name_len = strlen( name );
    /**/myassert( name_len < 256 );
        /* 1 for the name_len, 2 for the type_idx, 1 for the class */
        coment = Can2TDNewRec( TD_CMT_LOCAL_DEFN, name_len + (1+2+1) );
        ObjPutName( coment, name, name_len );
        ObjPutIndex( coment, type->extra );
        ObjPut8( coment, TD_LOCAL_TYPEDEF );
        Can2TDEndRec( coment );
    }
    return( 0 );
}

void Can2TDTypeDef( void ) {
/************************/

    if( CanMisc.types_present ) {
        CanTWalk( NULL, doTypeDef );
    }
}

⌨️ 快捷键说明

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