⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctype.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
            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 + -