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 + -
显示快捷键?