📄 ctype.c
字号:
if( strcmp( field->name, new_field->name ) == 0 ) {
CErr2p( ERR_DUPLICATE_FIELD_NAME, field->name );
}
}
new_field->next_field_same_hash = FieldHash[HashValue];
FieldHash[HashValue] = new_field;
}
if( tag->u.field_list == NULL ) {
tag->u.field_list = new_field;
} else {
prev_field = tag->last_field;
prev_field->next_field = new_field;
if( SizeOfArg( prev_field->field_type ) == 0 ) { /* 05-jun-92 */
CErr( ERR_INCOMPLETE_TYPE, (SYM_NAMEPTR)(prev_field->name) );
}
}
tag->last_field = new_field;
return( new_field );
}
local TYPEPTR EnumFieldType( TYPEPTR ftyp,
char plain_int, /* 19-mar-91 */
unsigned start,
unsigned width )
{
TYPEPTR typ;
unsigned char data_type;
typ = TypeNode( TYPE_FIELD, NULL );
typ->u.f.field_start = start;
typ->u.f.field_width = width;
if( plain_int ) {
data_type = TYPE_INT; /* default to signed bit fields */
} else {
while( ftyp->decl_type == TYPE_TYPEDEF ) ftyp = ftyp->object;
if( ftyp->decl_type == TYPE_ENUM ) {
ftyp = ftyp->object;
}
data_type = ftyp->decl_type;
}
typ->u.f.field_type = data_type;
switch( data_type ) {
case TYPE_UCHAR:
case TYPE_USHORT:
case TYPE_UINT:
case TYPE_ULONG:
case TYPE_ULONG64:
typ->decl_type = TYPE_UFIELD;
break;
}
return( typ );
}
unsigned GetTypeAlignment( TYPEPTR typ )
{
unsigned size;
for(;;) {
if(( typ->decl_type == TYPE_TYPEDEF ) ||
( typ->decl_type == TYPE_ARRAY )) {
typ = typ->object;
} else {
break;
}
}
if( typ->decl_type == TYPE_STRUCT || /* 25-jul-91 */
typ->decl_type == TYPE_UNION ) {
size = typ->u.tag->alignment;
#if _MACHINE == _ALPHA
if( CompFlags.align_structs_on_qwords ) {
size = 8;
}
#endif
} else {
size = TypeSize( typ );
}
return( size );
}
local unsigned long FieldAlign( unsigned long next_offset,
FIELDPTR field,
unsigned int *worst_alignment )
{ /* 05-jan-89 */
unsigned pack_adjustment;
unsigned align;
pack_adjustment = PackAmount;
align = GetTypeAlignment( field->field_type );
if( align > pack_adjustment ){ // can't be any bigger than pack( x )
align = pack_adjustment;
}
if( align > *worst_alignment ) { /* 24-jul-91 */
*worst_alignment = align;
}
if( align != 1 ) {
unsigned long old_offset = next_offset;
next_offset += align - 1;
next_offset &= - (long)align;
if( CompFlags.slack_byte_warning && (next_offset - old_offset) ){
CWarn2( WARN_LEVEL_1,
ERR_SLACK_ADDED, (next_offset - old_offset) );
}
}
field->offset = next_offset;
return( next_offset );
}
local int UnQualifiedType( TYPEPTR typ ) /* 21-mar-91 */
{
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type == TYPE_ENUM ) {
typ = typ->object;
}
switch( typ->decl_type ) {
case TYPE_CHAR:
case TYPE_UCHAR:
return( TYPE_CHAR );
case TYPE_SHORT:
case TYPE_USHORT:
return( TYPE_SHORT );
case TYPE_INT:
case TYPE_UINT:
return( TYPE_INT );
case TYPE_LONG: /* + AFS 05-mar-91 */
case TYPE_ULONG:
return( TYPE_LONG );
case TYPE_LONG64:
case TYPE_ULONG64:
return( TYPE_LONG64 );
default:
break;
}
return( 0 );
}
/* clear the hash table of all fields that were just defined
in the struct with tag tag */
local void ClearFieldHashTable( TAGPTR tag )
{
FIELDPTR field;
FIELDPTR hash_field;
FIELDPTR prev_field;
for( field = tag->u.field_list; field; field = field->next_field ) {
prev_field = NULL;
hash_field = FieldHash[field->hash];
if( hash_field == field ) {
/* first entry: easy kick out */
FieldHash[field->hash] = field->next_field_same_hash;
} else while ( hash_field ) {
/* search for candidate to kick */
prev_field = hash_field;
hash_field = hash_field->next_field_same_hash;
if( hash_field == field ) {
hash_field = hash_field->next_field_same_hash;
prev_field->next_field_same_hash = hash_field;
}
}
}
}
local unsigned long GetFields( TYPEPTR decl )
{
unsigned long start = 0;
TYPEPTR typ;
decl_state state;
FIELDPTR field;
unsigned scalar_size;
unsigned bits_available, bits_total;
unsigned long struct_size;
unsigned long next_offset;
int width;
unsigned int worst_alignment; /* 24-jul-91 */
char unqualified_type, prev_unqualified_type;
char plain_int;
decl_info info;
static int struct_level = 0;
struct_level++;
prev_unqualified_type = TYPE_VOID; /* so it doesn't match 1st time */
worst_alignment = 1; /* 24-jul-91 */
bits_available = 1;
bits_total = 0;
/* assertion: bits_available != bits_total && bits_total >> 3 == 0 */
struct_size = start;
next_offset = start;
for(;;) {
if( CurToken == T_SEMI_COLON && CompFlags.extensions_enabled ){
NextToken();
if( CurToken == T_RIGHT_BRACE ) break;
continue;
}
GetFieldTypeSpecifier( &plain_int, &info );
typ = info.typ;
state = DECL_STATE_NONE;
if( typ == NULL ) {
state |= DECL_STATE_NOTYPE;
CErr2p( ERR_MISSING_DATA_TYPE, Buffer );
typ = TypeDefault();
if( CurToken == T_ID ) NextToken();
}
unqualified_type = UnQualifiedType( typ );
if( bits_available == bits_total ||
decl->decl_type == TYPE_UNION ) { /* 12-nov-94 */
bits_available = TypeSize( typ ) * 8;
bits_total = bits_available;
} else if( unqualified_type != prev_unqualified_type ) {
next_offset += bits_total >> 3;
bits_available = TypeSize( typ ) * 8;
bits_total = bits_available;
}
prev_unqualified_type = unqualified_type;
for( ;; ) {
field = NULL;
if( CurToken != T_COLON ) {
field = FieldDecl( typ,info.mod, state );
field->level = struct_level;
field = NewField( field, decl );
}
if( CurToken == T_COLON ) {
if( field != NULL ){
next_offset = FieldAlign( next_offset, field,
&worst_alignment );
}
CheckBitfieldType( typ );
NextToken();
width = ConstExpr();
if( width == 0 && field != NULL ) {
CErr1( ERR_WIDTH_0 );
}
if( width > TARGET_BITS ) {
CErr1( ERR_FIELD_TOO_WIDE );
width = TARGET_BITS;
} else if( width < 0 ) {
CErr1( ERR_WIDTH_NEGATIVE );
width = 0;
}
if( width > bits_available || width == 0 ) {
scalar_size = TypeSize( typ );
if( bits_available != bits_total ) {
/* some bits have been used; abandon this unit */
next_offset += bits_total >> 3;
} else if( width == 0 ) {
/* no bits have been used; align to base type */
next_offset += scalar_size - 1;
next_offset &= ~( scalar_size - 1 );
}
bits_available = scalar_size * 8;
bits_total = bits_available;
}
if( field != NULL ) {
if( unqualified_type == TYPE_LONG64 ){
int bit_offset = bits_total - bits_available;
if( bit_offset >= 32 ){
field->offset = next_offset+4;
bit_offset -= 32;
}else{
field->offset = next_offset;
}
field->field_type = EnumFieldType( GetType( TYPE_LONG ), plain_int,
bit_offset, width );
}else{
field->offset = next_offset;
field->field_type = EnumFieldType( typ, plain_int,
bits_total - bits_available, width );
}
}
bits_available -= width;
} else {
if( bits_available != bits_total ) { //changed from bit field to non
next_offset += bits_total >> 3;
field->offset = next_offset;
bits_available = TypeSize( typ ) * 8;
bits_total = bits_available;
}
next_offset = FieldAlign( next_offset, field,
&worst_alignment );
next_offset += SizeOfArg( field->field_type );
}
if( next_offset > struct_size ) struct_size = next_offset;
if( decl->decl_type == TYPE_UNION ){
next_offset = start;
bits_available = bits_total;
}
if( CurToken != T_COMMA ) break;
NextToken();
}
if( CurToken == T_RIGHT_BRACE ) {
CWarn1( WARN_MISSING_LAST_SEMICOLON,
ERR_MISSING_LAST_SEMICOLON );
} else {
MustRecog( T_SEMI_COLON );
}
if( CurToken == T_RIGHT_BRACE ) break;
}
if( bits_available != bits_total ) { /* if last field was bit field */
next_offset += bits_total >> 3;
if( next_offset > struct_size ) struct_size = next_offset;
}
ClearFieldHashTable( decl->u.tag );
decl->u.tag->alignment = worst_alignment; /* 25-jul-91 */
struct_size += worst_alignment - 1; /* 01-may-92 */
struct_size &= - (long)worst_alignment;
_CHECK_SIZE( struct_size );
NextToken();
struct_level--;
return( struct_size );
}
local TYPEPTR StructDecl( int decl_typ, int packed )
{
TYPEPTR typ;
TAGPTR tag;
int saved_packamount;
TAGPTR TagLookup();
saved_packamount = PackAmount; /* 20-nov-91 */
if( packed ) PackAmount = 1;
NextToken();
if( CurToken == T_LEFT_BRACE ) {
tag = NullTag();
NextToken();
} else {
for(;;) {
if( CurToken == T_ID ) break;
if( CurToken == T_LEFT_BRACE ) break;
if( CurToken == T_EOF ) break;
ExpectStructUnionTag();
NextToken();
}
if( CurToken == T_ID ) { /* structure or union tag */
tag = TagLookup();
NextToken();
} else {
tag = NullTag();
}
if( CurToken != T_LEFT_BRACE ) {
if( CurToken == T_SEMI_COLON ) {
if( tag->level != SymLevel ) {
tag = NewTag( tag->name, tag->hash );
}
}
typ = tag->sym_type;
if( typ == NULL ) {
typ = TypeNode( decl_typ, NULL );
} else {
if( typ->decl_type != decl_typ ) { /* 18-jan-89 */
CErr2p( ERR_DUPLICATE_TAG, tag->name );
}
}
tag->sym_type = typ;
typ->u.tag = tag; /* FWC 19-jan-87 */
PackAmount = saved_packamount;
return( typ );
}
NextToken();
tag = VfyNewTag( tag, decl_typ );
}
typ = tag->sym_type;
if( typ == NULL ) {
typ = TypeNode( decl_typ, NULL );
tag->sym_type = typ;
}
typ->u.tag = tag;
tag->u.field_list = NULL;
tag->size = GetFields( typ );
PackAmount = saved_packamount; /* 20-nov-91 */
return( typ );
}
/*
Next three functions descripe a struct that looks like
struct {
double __ow_real;
double _Imaginary __ow_imaginary;
}
*/
/*
local void GetComplexFieldTypeSpecifier( decl_info *info, DATA_TYPE data_type )
{
info->stg = SC_NULL; // indicate don't want any storage class specifiers
info->mod = FLAG_NONE;
info->decl = DECLSPEC_NONE;
info->naked = FALSE;
info->seg = 0;
info->typ = GetType( data_type );
}
local unsigned long GetComplexFields( TYPEPTR decl )
{
unsigned long start = 0;
TYPEPTR typ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -