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