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 + -
显示快捷键?