cdinit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,580 行 · 第 1/4 页
C
1,580 行
ld = tree->op.float_value->ld;
__LDFD( (long_double near *)&ld, (double near *)&d );
info->offset = (long)d;
#else
info->offset = (long)tree->op.float_value->ld.value;
#endif
}
if( info->offset != 0 ) CompFlags.non_zero_data = 1;
break;
case OPR_PUSHSTRING:
info->state = IS_ADDR;
if( info->addr_set ) {
info->is_error = TRUE;
}
info->addr_set = TRUE;
info->is_str = TRUE;
info->str_h = tree->op.string_handle;
tree->op.string_handle->ref_count++;
CompFlags.non_zero_data = 1;
break;
case OPR_PUSHADDR:
info->state = IS_ADDR;
case OPR_PUSHSYM:
if( info->addr_set ) {
info->is_error = TRUE;
}
info->addr_set = TRUE;
info->is_str = FALSE;
SymGet( &sym, tree->op.sym_handle );
info->sym_h = tree->op.sym_handle;
CompFlags.non_zero_data = 1;
if( sym.stg_class == SC_AUTO ) {
info->is_error = TRUE;
}
break;
case OPR_INDEX:
if( tree->right->op.opr == OPR_PUSHINT ) {
AddrFold( tree->left, info );
offset = tree->right->op.long_value;
} else if( tree->left->op.opr == OPR_PUSHINT ) {
AddrFold( tree->right, info );
offset = tree->left->op.long_value;
} else {
info->is_error = TRUE;
}
if( info->state == IS_VALUE ) { // must be foldable
info->is_error = TRUE;
}
info->offset += offset * SizeOfArg( tree->expr_type );
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_ADD:
case OPR_SUB:
if( tree->right->op.opr == OPR_PUSHINT ) {
AddrFold( tree->left, info );
if( tree->op.opr == OPR_ADD ) {
info->offset = info->offset+tree->right->op.long_value;
} else {
info->offset = info->offset-tree->right->op.long_value;
}
} else if( tree->left->op.opr == OPR_PUSHINT ) {
AddrFold( tree->right, info );
if( tree->op.opr == OPR_ADD ) {
info->offset = tree->left->op.long_value+info->offset;
} else {
info->offset = tree->left->op.long_value-info->offset;
}
} else {
info->is_error = TRUE;
}
if( info->state == IS_VALUE ) { // must be foldable
info->is_error = TRUE;
}
break;
case OPR_ADDROF:
AddrFold( tree->right, info );
info->state = IS_ADDR;
CompFlags.non_zero_data = 1;
break;
case OPR_ARROW:
AddrFold( tree->left, info );
if( info->state == IS_VALUE ) { // must be foldable
info->is_error = TRUE;
}
info->offset += tree->right->op.long_value;
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_POINTS:
AddrFold( tree->left, info );
if( info->state == IS_VALUE ) { // must be foldable
info->is_error = TRUE;
}
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_DOT:
AddrFold( tree->left, info );
info->offset += tree->right->op.long_value;
CompFlags.non_zero_data = 1;
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_CONVERT: //should check for pointer to smaller
case OPR_CONVERT_PTR:
AddrFold( tree->right, info );
break;
case OPR_ERROR: // error has already been issued
break;
default:
info->is_error = TRUE;
break;
}
}
local void StorePointer( TYPEPTR typ, TOKEN int_type, unsigned long size )
{
type_modifiers flags;
TREEPTR tree;
TYPEPTR typ2;
int address_wanted;
DATA_QUAD dq;
addrfold_info info;
dq.flags = Q_DATA;
flags = FLAG_NONE;
if( CompFlags.strings_in_code_segment )
flags = FLAG_CONST; /*01-sep-89*/
if( typ->decl_type == TYPE_POINTER ) {
if( typ->u.p.decl_flags & (FLAG_FAR|FLAG_HUGE) ) {
dq.flags |= Q_FAR_POINTER;
flags = FLAG_FAR;
} else if( typ->u.p.decl_flags & FLAG_NEAR ) {
dq.flags |= Q_NEAR_POINTER;
flags = FLAG_NONE;
} else {
typ2 = typ->object;
SKIP_TYPEDEFS( typ2 );
if( typ2->decl_type == TYPE_FUNCTION ) {
dq.flags |= Q_CODE_POINTER;
} else if( TypeSize( typ ) == TARGET_FAR_POINTER ) {
dq.flags |= Q_FAR_POINTER;
}
}
}
address_wanted = 0;
if( CurToken == T_RIGHT_BRACE) { // t some x = {}
dq.opr = T_ID;
dq.u.var.sym_handle = 0;
dq.u.var.offset = 0;
} else {
tree = AddrExpr();
tree = InitAsgn( typ, tree ); // as if we are assigning
info.offset = 0;
info.sym_h = 0;
info.addr_set = FALSE;
info.state = IS_VALUE;
info.is_str = FALSE;
info.is_error = FALSE;
AddrFold( tree, &info );
FreeExprTree( tree );
if( info.state == IS_VALUE ) { // must be foldable into addr+offset
info.is_error = TRUE;
}
if( info.is_str ) { // need to fix cgen an DATAQUADS to handle str+off
if( info.offset != 0 ) {
info.is_error = TRUE;
}
}
if( info.is_error ) {
CErr1( ERR_NOT_A_CONSTANT_EXPR );
dq.opr = T_ID;
dq.u.var.sym_handle = 0;
dq.u.var.offset = 0;
} else {
if( info.is_str ) {
dq.opr = T_STRING;
dq.u.string_leaf = info.str_h;
} else {
dq.opr = T_ID;
dq.u.var.sym_handle = info.sym_h;
dq.u.var.offset = info.offset;
}
}
}
if( typ->decl_type == TYPE_POINTER ) {
GenDataQuad( &dq, size );
} else if( dq.opr == T_STRING ) { /* 05-jun-91 */
if( TypeSize( typ ) != DataPtrSize || CompFlags.strict_ANSI ) {
CErr1( ERR_INVALID_INITIALIZER );
}
GenDataQuad( &dq, size );
} else { /* dq.opr == T_ID */
if( dq.u.var.sym_handle != 0 ) {
if( TypeSize( typ ) != DataPtrSize ) {
CErr1( ERR_INVALID_INITIALIZER );
}
GenDataQuad( &dq, size );
} else {
StoreIValue( int_type, dq.u.var.offset, size );
}
}
}
local void StoreInt64( TYPEPTR typ )
{
TREEPTR tree;
DATA_QUAD dq;
dq.opr = T___INT64;
dq.flags = Q_DATA;
U32ToU64( 0, &dq.u.long64 );
if( CurToken != T_RIGHT_BRACE ) {
tree = SingleExpr();
tree = InitAsgn( typ, tree ); // as if we are assigning
if( tree->op.opr == OPR_PUSHINT || tree->op.opr == OPR_PUSHFLOAT ) {
CastConstValue( tree, typ->decl_type );
dq.u.long64 = tree->op.ulong64_value;
} else {
CErr1( ERR_NOT_A_CONSTANT_EXPR );
}
FreeExprTree( tree );
CompFlags.non_zero_data = 1;
}
GenDataQuad( &dq, sizeof( int64 ) );
}
local FIELDPTR InitBitField( FIELDPTR field )
{
TYPEPTR typ;
unsigned long value;
unsigned long size;
uint64 value64;
unsigned long bit_value;
unsigned long offset;
int token;
TOKEN int_type = T_NULL;
token = CurToken;
if( CurToken == T_LEFT_BRACE ) NextToken();
typ = field->field_type;
size = SizeOfArg( typ );
switch( typ->u.f.field_type ) {
case TYPE_CHAR:
case TYPE_UCHAR:
int_type = T_CHAR;
break;
case TYPE_SHORT:
case TYPE_USHORT:
int_type = T_SHORT;
break;
case TYPE_INT:
case TYPE_UINT:
int_type = T_INT;
break;
case TYPE_LONG:
case TYPE_ULONG:
int_type = T_LONG;
break;
case TYPE_LONG64:
case TYPE_ULONG64:
int_type = T___INT64;
U32ToU64( 0, &value64 );
break;
}
offset = field->offset;
value = 0;
while( typ->decl_type == TYPE_FIELD ||
typ->decl_type == TYPE_UFIELD ) {
bit_value = 0;
if( CurToken != T_RIGHT_BRACE ) bit_value = ConstExpr();
ChkConstant( bit_value, BitMask[ typ->u.f.field_width - 1 ] );
bit_value &= BitMask[ typ->u.f.field_width - 1 ];
if( int_type == T___INT64 ) {
uint64 tmp;
U32ToU64( bit_value, &tmp );
U64ShiftL( &tmp, typ->u.f.field_start, &tmp );
value64.u._32[L] |= tmp.u._32[L];
value64.u._32[H] |= tmp.u._32[H];
} else {
value |= bit_value << typ->u.f.field_start;
}
field = field->next_field;
if( field == NULL ) break;
if( field->offset != offset ) break; /* bit field done */
typ = field->field_type;
if( CurToken == T_EOF ) break;
if( CurToken != T_RIGHT_BRACE ) MustRecog( T_COMMA );
}
if( int_type == T___INT64 ) {
StoreIValue64( value64 );
} else {
StoreIValue( int_type, value, size );
}
if( token == T_LEFT_BRACE ) {
if( CurToken == T_COMMA ) NextToken();
MustRecog( T_RIGHT_BRACE );
}
return( field );
}
/* typ is the (perhaps subaggregate) object that is initialized.
ctyp refers to the current object which is the object
associated with the closest brace pair. It may or may not be
equal to typ */
/* Detects a C99 designated initializer */
local void *DesignatedInit( TYPEPTR typ, TYPEPTR ctyp, void *field )
{
TREEPTR tree;
unsigned long offs;
static int new_field = 1;
if( !CompFlags.extensions_enabled && !CompFlags.c99_extensions ) {
return( field );
}
if( CurToken != T_LEFT_BRACKET && CurToken != T_DOT ) {
new_field = 1;
return( field );
}
/* if designator refers to outer type: back out */
if(typ != ctyp && new_field)
return( NULL );
new_field = 0;
if( typ->decl_type == TYPE_ARRAY ) {
if( CurToken != T_LEFT_BRACKET )
return( NULL );
NextToken();
tree = SingleExpr();
if( tree->op.opr == OPR_PUSHINT || tree->op.opr == OPR_PUSHFLOAT ) {
CastConstValue( tree, typ->decl_type );
*(unsigned long *)field = tree->op.ulong_value;
} else {
CErr1( ERR_NOT_A_CONSTANT_EXPR );
}
FreeExprTree( tree );
MustRecog( T_RIGHT_BRACKET );
} else {
if( CurToken != T_DOT )
return( NULL );
NextToken();
if( CurToken != T_ID ) {
CErr1( ERR_EXPECTING_ID );
}
offs = 0;
field = SearchFields( &typ, &offs, Buffer );
if( field == NULL ) {
CErr( ERR_NAME_NOT_FOUND_IN_STRUCT, Buffer, typ->u.tag->name );
}
NextToken();
}
if( CurToken != T_LEFT_BRACKET && CurToken != T_DOT ) {
new_field = 1;
MustRecog( T_EQUAL );
}
return( field );
}
local bool DesignatedInSubAggregate( DATA_TYPE decl_type )
{
switch( decl_type ) {
case TYPE_ARRAY:
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_FCOMPLEX:
case TYPE_DCOMPLEX:
case TYPE_LDCOMPLEX:
/* A subaggregate can be stopped by a designated initializer.
in that case the comma was already eaten... */
return ( CurToken == T_DOT || CurToken == T_LEFT_BRACKET );
default:
return FALSE;
}
}
local void InitArray( TYPEPTR typ, TYPEPTR ctyp )
{
unsigned long n;
unsigned long m;
unsigned long *pm;
unsigned long array_size;
unsigned long elem_size;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?