📄 cdinit.c
字号:
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 );
} else if( dq.opr == T_STRING ) { /* 05-jun-91 */
if( TypeSize( typ ) != DataPtrSize || CompFlags.strict_ANSI ) {
CErr1( ERR_INVALID_INITIALIZER );
}
GenDataQuad( &dq );
} else { /* dq.opr == T_ID */
if( dq.u.var.sym_handle != 0 ) {
if( TypeSize( typ ) != DataPtrSize ) {
CErr1( ERR_INVALID_INITIALIZER );
}
GenDataQuad( &dq );
} else {
StoreIValue( int_type, dq.u.var.offset );
}
}
}
local void StoreInt64( TYPEPTR typ )
{
TREEPTR tree;
auto 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 );
}
local FIELDPTR InitBitField( FIELDPTR field )
{
TYPEPTR typ;
unsigned long value;
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;
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 );
}
if( token == T_LEFT_BRACE ) {
if( CurToken == T_COMMA ) NextToken();
MustRecog( T_RIGHT_BRACE );
}
return( field );
}
local void InitArray( TYPEPTR typ )
{
unsigned long n;
unsigned long array_size;
array_size = TypeSize( typ );
n = 0;
for( ;; ) {
InitSymData( typ->object, 1 );
n++;
if( n == array_size ){
break;
}
if( CurToken == T_EOF ) break;
if( CurToken == T_RIGHT_BRACE ) break;
MustRecog( T_COMMA );
if( CurToken == T_RIGHT_BRACE ) break;
}
if( array_size == 0 ){
typ->u.array->dimension = n;
}else if( array_size > n ){
ZeroBytes( (array_size-n) * SizeOfArg( typ->object ) );
}
}
local void InitStruct( TYPEPTR typ )
{
FIELDPTR field;
unsigned long n;
unsigned offset;
n = typ->u.tag->size; /* get full size of the struct */
offset = 0;
for( field = typ->u.tag->u.field_list; field; ) {
/* The first field might not start at offset 0; 19-mar-91 */
if( field->offset != offset ) { /* 14-dec-88 */
ZeroBytes( field->offset - offset ); /* padding */
}
typ = field->field_type;
offset = field->offset + SizeOfArg( typ ); /* 19-dec-88 */
if( typ->decl_type == TYPE_FIELD ||
typ->decl_type == TYPE_UFIELD ) {
field = InitBitField( field );
} else {
InitSymData( typ, 1 );
field = field->next_field;
}
if( field == NULL ) break;
if( CurToken == T_EOF ) break;
if( CurToken != T_RIGHT_BRACE ) MustRecog( T_COMMA );
}
if( (unsigned)n > offset ) { /* 14-dec-88, 07-jun-92 */
ZeroBytes( (unsigned)n - offset ); /* padding */
}
}
local void InitUnion( TYPEPTR typ )
{
FIELDPTR field;
unsigned long n;
n = typ->u.tag->size; /* get full size of the union */
field = typ->u.tag->u.field_list;
for(;;) { // skip unnamed bit fields
if( field == NULL ) break; // 12-nov-94
typ = field->field_type;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( field->name[0] != '\0' ) break;
if( typ->decl_type == TYPE_STRUCT ) break; /* 03-feb-95 */
if( typ->decl_type == TYPE_UNION ) break;
field = field->next_field;
}
if( field != NULL ) { /* 18-oct-94 */
if( typ->decl_type == TYPE_FIELD || /* 12-nov-94 */
typ->decl_type == TYPE_UFIELD ) {
InitBitField( field );
} else {
InitSymData( typ, 1 );
}
n -= SizeOfArg( typ ); /* subtract size of the first type */
if( n != 0 ) ZeroBytes( n );/* pad the rest */
}
}
void InitSymData( TYPEPTR typ, int level )
{
int token;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
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 );
}
}
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 && level == 0 ) {
CErr1( ERR_NEED_BRACES );
}
InitArray( typ );
}
break;
case TYPE_FCOMPLEX:
case TYPE_DCOMPLEX:
case TYPE_LDCOMPLEX:
case TYPE_STRUCT:
if( token != T_LEFT_BRACE && level == 0 ) {
CErr1( ERR_NEED_BRACES );
}
InitStruct( typ );
break;
case TYPE_UNION:
if( token != T_LEFT_BRACE && level == 0 ) {
CErr1( ERR_NEED_BRACES );
}
InitUnion( typ );
break;
case TYPE_CHAR:
case TYPE_UCHAR:
StorePointer( typ, T_CHAR );
break;
case TYPE_SHORT:
case TYPE_USHORT:
StorePointer( typ, T_SHORT );
break;
case TYPE_INT:
case TYPE_UINT:
StorePointer( typ, T_INT );
break;
case TYPE_LONG:
case TYPE_ULONG:
StorePointer( typ, T_LONG );
break;
case TYPE_LONG64:
case TYPE_ULONG64:
StoreInt64( typ );
break;
case TYPE_FLOAT:
StoreFloat( T_FLOAT );
break;
case TYPE_DOUBLE:
StoreFloat( T_DOUBLE );
break;
case TYPE_LONG_DOUBLE:
//StoreFloat( T_LONG_DOUBLE );
StoreFloat( T_DOUBLE );
break;
case TYPE_POINTER:
StorePointer( typ, T_ID );
break;
case TYPE_BOOL:
StorePointer( typ, T_CHAR );
break;
case TYPE_FIMAGINARY:
StoreFloat( T_FLOAT );
break;
case TYPE_DIMAGINARY:
StoreFloat( T_DOUBLE );
break;
case TYPE_LDIMAGINARY:
//StoreFloat( T_LONG_DOUBLE );
StoreFloat( T_DOUBLE );
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 ) {
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type == TYPE_CHAR || typ->decl_type == TYPE_UCHAR ){
return( TRUE );
}
}
return( FALSE );
}
local int WCharArray( TYPEPTR typ )
{
if( CurToken == T_STRING ) {
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
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;
auto 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->dimension == 0 ) 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 = size; /* chop the string */
}
dq.opr = T_CONST;
dq.flags = Q_DATA;
dq.u.string_leaf = str_lit;
GenDataQuad( &dq );
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;
auto 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->dimension == 0 ) {
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -