cdinit.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,580 行 · 第 1/4 页
C
1,580 行
array_size = TypeSize( typ );
n = 0;
pm = &m;
for( ;; ) {
m = n;
pm = DesignatedInit( typ, ctyp, pm );
if( pm == NULL ) break;
if( m != n ) {
elem_size = SizeOfArg( typ->object );
if( typ->u.array->unspecified_dim && m > array_size ) {
RelSeekBytes( ( array_size - n ) * elem_size );
ZeroBytes( (m - array_size) * elem_size );
} else {
RelSeekBytes( ( m - n ) * elem_size );
}
n = m;
}
n++;
if( n > array_size ) {
if( !typ->u.array->unspecified_dim ) break;
array_size = n;
/* clear out the new element just in case */
elem_size = SizeOfArg( typ->object );
ZeroBytes( elem_size );
RelSeekBytes( -elem_size );
}
InitSymData( typ->object, ctyp, 1 );
if( CurToken == T_EOF ) break;
if( CurToken == T_RIGHT_BRACE ) break;
if( DesignatedInSubAggregate( typ->object->decl_type ) ) continue;
if( n < array_size || typ == ctyp || typ->u.array->unspecified_dim ) {
MustRecog( T_COMMA );
}
if( CurToken == T_RIGHT_BRACE ) break;
}
if( typ->u.array->unspecified_dim ) {
typ->u.array->dimension = array_size;
}
if( array_size > n ) {
RelSeekBytes( ( array_size - n ) * SizeOfArg( typ->object ) );
}
}
/* Detects a C99 designated initializer for fields */
/* Initialize struct or union fields */
local void InitStructUnion( TYPEPTR typ, TYPEPTR ctyp, FIELDPTR field )
{
TYPEPTR ftyp;
unsigned long n;
unsigned long offset;
n = typ->u.tag->size; /* get full size of the struct or union */
offset = 0;
for( ;; ) {
field = DesignatedInit( typ, ctyp, field );
if( field == NULL ) break;
/* The first field might not start at offset 0; 19-mar-91 */
if( field->offset != offset ) { /* 14-dec-88 */
RelSeekBytes( field->offset - offset );
}
ftyp = field->field_type;
offset = field->offset + SizeOfArg( ftyp ); /* 19-dec-88 */
if( ftyp->decl_type == TYPE_FIELD ||
ftyp->decl_type == TYPE_UFIELD ) {
field = InitBitField( field );
} else {
InitSymData( ftyp, ctyp, 1 );
field = field->next_field;
}
if( typ->decl_type == TYPE_UNION ) {
if( offset != n ) {
ZeroBytes( n - offset ); /* pad the rest */
}
offset = n;
/* designated initializers may still override this field */
field = NULL;
}
if( CurToken == T_EOF ) break;
if( CurToken == T_RIGHT_BRACE ) break;
if( DesignatedInSubAggregate( ftyp->decl_type ) ) continue;
if( field != NULL || typ == ctyp ) {
MustRecog( T_COMMA );
}
if( CurToken == T_RIGHT_BRACE ) break;
}
RelSeekBytes( (unsigned)n - offset );
}
local void InitStruct( TYPEPTR typ, TYPEPTR ctyp )
{
InitStructUnion( typ, ctyp, typ->u.tag->u.field_list );
}
local void InitUnion( TYPEPTR typ, TYPEPTR ctyp )
{
FIELDPTR field;
TYPEPTR ftyp;
field = typ->u.tag->u.field_list;
for( ;; ) { // skip unnamed bit fields
if( field == NULL ) break; // 12-nov-94
ftyp = field->field_type;
SKIP_TYPEDEFS( ftyp );
if( field->name[0] != '\0' ) break;
if( ftyp->decl_type == TYPE_STRUCT ) break; /* 03-feb-95 */
if( ftyp->decl_type == TYPE_UNION ) break;
field = field->next_field;
}
InitStructUnion( typ, ctyp, field );
}
void InitSymData( TYPEPTR typ, TYPEPTR ctyp, int level )
{
int token;
unsigned long size;
SKIP_TYPEDEFS( typ );
if( typ->decl_type == TYPE_ENUM ) typ = typ->object; /* 07-nov-90 */
token = CurToken;
if( CurToken == T_LEFT_BRACE ) {
NextToken();
if( CurToken == T_RIGHT_BRACE || CurToken == T_COMMA ) {
CErr1( ERR_EMPTY_INITIALIZER_LIST );
}
}
size = SizeOfArg( typ );
switch( typ->decl_type ) {
case TYPE_ARRAY:
if( CharArray( typ->object ) ) {
InitCharArray( typ );
} else if( WCharArray( typ->object ) ) {
InitWCharArray( typ );
} else {
if( token == T_LEFT_BRACE ) {
ctyp = typ;
} else if( level == 0 ) {
CErr1( ERR_NEED_BRACES );
}
if( typ == ctyp ) { /* initialize new current type */
/* first zero out the whole array; otherwise
overlapping fields caused by designated
initializers will make life very difficult */
ZeroBytes( size );
RelSeekBytes( -size );
}
InitArray( typ, ctyp );
}
break;
case TYPE_FCOMPLEX:
case TYPE_DCOMPLEX:
case TYPE_LDCOMPLEX:
case TYPE_STRUCT:
if( token == T_LEFT_BRACE ) {
ctyp = typ;
} else if( level == 0 ) {
CErr1( ERR_NEED_BRACES );
}
if( typ == ctyp ) { /* initialize new current type */
/* zero out all fields; otherwise overlapping fields caused
by designated initializers will make life very difficult */
ZeroBytes( size );
RelSeekBytes( -size );
}
InitStruct( typ, ctyp );
break;
case TYPE_UNION:
if( token == T_LEFT_BRACE ) {
ctyp = typ;
} else if( level == 0 ) {
CErr1( ERR_NEED_BRACES );
}
InitUnion( typ, ctyp );
break;
case TYPE_CHAR:
case TYPE_UCHAR:
StorePointer( typ, T_CHAR, size );
break;
case TYPE_SHORT:
case TYPE_USHORT:
StorePointer( typ, T_SHORT, size );
break;
case TYPE_INT:
case TYPE_UINT:
StorePointer( typ, T_INT, size );
break;
case TYPE_LONG:
case TYPE_ULONG:
StorePointer( typ, T_LONG, size );
break;
case TYPE_LONG64:
case TYPE_ULONG64:
StoreInt64( typ );
break;
case TYPE_FLOAT:
StoreFloat( T_FLOAT, size );
break;
case TYPE_DOUBLE:
StoreFloat( T_DOUBLE, size );
break;
case TYPE_LONG_DOUBLE:
//StoreFloat( T_LONG_DOUBLE );
StoreFloat( T_DOUBLE, size );
break;
case TYPE_POINTER:
StorePointer( typ, T_ID, size );
break;
case TYPE_BOOL:
StorePointer( typ, T_CHAR, size );
break;
case TYPE_FIMAGINARY:
StoreFloat( T_FLOAT, size );
break;
case TYPE_DIMAGINARY:
StoreFloat( T_DOUBLE, size );
break;
case TYPE_LDIMAGINARY:
//StoreFloat( T_LONG_DOUBLE );
StoreFloat( T_DOUBLE, size );
break;
default:
break;
}
if( token == T_LEFT_BRACE ) {
if( CurToken == T_COMMA ) {
NextToken();
}
if( CurToken != T_RIGHT_BRACE ) {
CErr1( ERR_TOO_MANY_INITS );
}
while( CurToken != T_RIGHT_BRACE ) {
if( CurToken == T_EOF ) break;
if( CurToken == T_SEMI_COLON )break;
if( CurToken == T_LEFT_BRACE )break;
NextToken();
}
MustRecog( T_RIGHT_BRACE );
}
}
local int CharArray( TYPEPTR typ )
{
if( CurToken == T_STRING ) {
SKIP_TYPEDEFS( typ );
if( typ->decl_type == TYPE_CHAR || typ->decl_type == TYPE_UCHAR ) {
return( TRUE );
}
}
return( FALSE );
}
local int WCharArray( TYPEPTR typ )
{
if( CurToken == T_STRING ) {
SKIP_TYPEDEFS( typ );
if( typ->decl_type == TYPE_SHORT || typ->decl_type == TYPE_USHORT ) {
return( 1 );
}
}
return( 0 );
}
local void InitCharArray( TYPEPTR typ )
{
unsigned len;
STRING_LITERAL *str_lit;
unsigned long size;
DATA_QUAD dq;
/* This function handles the initialization of statements like: */
/* char name[4] = "abcd"; */
str_lit = GetLiteral();
if( CompFlags.wide_char_string )
CErr1( ERR_TYPE_MISMATCH );
len = str_lit->length;
if( typ->u.array->unspecified_dim ) typ->u.array->dimension = len;
size = typ->u.array->dimension;
if( len > size ) {
if( (len - size) > 1 ) {
CWarn1( WARN_LIT_TOO_LONG, ERR_LIT_TOO_LONG );
}
str_lit->length = len = size; /* chop the string */
}
dq.opr = T_CONST;
dq.flags = Q_DATA;
dq.u.string_leaf = str_lit;
GenDataQuad( &dq, len );
if( size > len ) { /* if array > len of literal */
ZeroBytes( size - len );
}
CompFlags.non_zero_data = 1;
}
local void InitWCharArray( TYPEPTR typ )
{
unsigned len;
unsigned i;
STRING_LITERAL *str_lit;
unsigned value;
unsigned short *pwc;
unsigned long size;
DATA_QUAD dq;
dq.opr = T_SHORT;
dq.flags = Q_DATA;
/* This function handles the initialization of statements like: */
/* wchar_t name[5] = L"abcd"; */
str_lit = GetLiteral();
if( !CompFlags.wide_char_string )
CErr1( ERR_TYPE_MISMATCH );
len = str_lit->length / sizeof(unsigned short);
if( typ->u.array->unspecified_dim ) {
typ->u.array->dimension = len;
}
size = typ->u.array->dimension;
if( len > size ) {
if( (len - size) > 1 ) {
CWarn1( WARN_LIT_TOO_LONG, ERR_LIT_TOO_LONG );
}
len = size;
}
pwc = (unsigned short *)str_lit->literal;
i = 0;
while( i < len ) {
value = *pwc++;
if( value != 0 ) CompFlags.non_zero_data = 1;
dq.u.long_values[0] = value;
GenDataQuad( &dq, sizeof( target_short ) );
++i;
}
if( i < size ) {
ZeroBytes( (size - i) * sizeof(unsigned short) );
}
FreeLiteral( str_lit );
}
local void StoreFloat( int float_type, unsigned long size )
{
TREEPTR tree;
DATA_QUAD dq;
dq.opr = float_type;
dq.flags = Q_DATA;
dq.u.double_value = 0.0;
if( CurToken != T_RIGHT_BRACE ) {
tree = SingleExpr();
switch( tree->op.opr ) {
case OPR_PUSHINT:
if( tree->op.const_type == TYPE_ULONG ) {
dq.u.double_value = tree->op.ulong_value;
} else {
dq.u.double_value = tree->op.long_value;
}
break;
case OPR_PUSHFLOAT:
if( tree->op.float_value->len != 0 ) {
dq.u.double_value = atof( tree->op.float_value->string );
} else {
#ifdef _LONG_DOUBLE_
long_double ld;
ld = tree->op.float_value->ld;
__LDFD( (long_double near *)&ld, (double near *)&dq.u.double_value );
#else
dq.u.double_value = tree->op.float_value->ld.value;
#endif
}
break;
default:
CErr1( ERR_NOT_A_CONSTANT_EXPR );
break;
}
FreeExprTree( tree );
if( dq.u.double_value != 0.0 ) CompFlags.non_zero_data = 1;
}
GenDataQuad( &dq, size );
}
local void GenStaticDataQuad( SYM_HANDLE sym_handle )
{
DATA_QUAD dq;
dq.opr = T_STATIC;
dq.flags = Q_DATA;
dq.u.var.sym_handle = sym_handle;
dq.u.var.offset = 0;
GenDataQuad( &dq, 0 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?