type.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,314 行 · 第 1/5 页

C
2,314
字号
/**********************************/
{
    return( MakeTypeOf( MakeVolatileModifier(), type ) );
}

static TYPE makeCompilerData( TYPE type, type_flag flags )
{
    if( defaultDataMemFlag & ( TF1_FAR | TF1_HUGE ) ) {
#if _CPU == 8086
        if(( flags & TF1_CONST ) == 0 ) {
            if( TargetSwitches & WINDOWS ) {
                /* R/W data must be near for 16-bit Windows */
                flags |= TF1_NEAR;
            } else {
                flags |= TF1_FAR;
            }
        } else {
            flags |= TF1_FAR;
        }
#else
        flags |= TF1_FAR;
#endif
    }
    return( MakeModifiedType( type, flags ) );
}

TYPE MakeCompilerReadWriteData( TYPE type )
/*****************************************/
{
    return( makeCompilerData( type, TF1_NULL ) );
}

TYPE MakeCompilerConstData( TYPE type )
/*************************************/
{
    return( makeCompilerData( type, TF1_CONST ) );
}

TYPE MakeCompilerConstCommonData( TYPE type )
/*******************************************/
{
    return( makeCompilerData( type, TF1_COMMON | TF1_CONST ) );
}

static TYPE makeCompilerReadWriteCommonData( TYPE type )
/******************************************************/
{
    return( makeCompilerData( type, TF1_COMMON ) );
}

static void verifyBasedRef( SEARCH_RESULT *result, SYMBOL sym )
{
    SCOPE found;

    found = result->scope;
    if( ScopeType( found, SCOPE_FILE ) ) {
        return;
    }
    if( ScopeType( found, SCOPE_BLOCK ) ) {
        return;
    }
    if( result->no_this ) {
        if( ! SymIsStaticDataMember( sym ) ) {
            CErr2p( ERR_CANNOT_ALWAYS_ACCESS, sym );
        }
    }
}

/*
  Based pointer examples:

  __segment seg_var;
  char __far *fp;

  (1) char __based(seg_var) *bp;        -- fetch segment from seg_var
      char __based((__segment)fp)) *ip; -- use of 'fp''s seg value
      char __based(fp) *pp;             -- add offset to fp to produce pointer
      char __based(void) *vp;           -- just an offset (based on nothing)
      char __based((__segment)__self) *sp; -- inherits base from expression
  (2) __based(__segname("_CODE"))       -- pre-defined segment names
      __based(__segname("_CONST"))      (^ code segment) (data segment)
      __based(__segname("_DATA"))       (data segment)
      __based(__segname("_STACK"))      (stack segment)
      __based(__segname("_MYSEG"))      (user-defined segment)
*/
TYPE MakeBasedModifier( type_flag mod, boolean seg_cast, PTREE base )
/*******************************************************************/
{
    int based_msg;
    SEARCH_RESULT *result;
    SYMBOL sym;
    SYMBOL_NAME sym_name;
    TYPE type;
    char *id;
    void *base_expr;

    base_expr = NULL;
    switch( mod ) {
    case TF1_BASED_VOID:
    case TF1_BASED_SELF:
        break;
    case TF1_BASED_STRING:
        base_expr = base->u.string;
        PTreeFree( base );
        break;
    default:
        mod = TF1_BASED_VOID;
        id = base->u.id.name;
        PTreeFree( base );
        result = ScopeFindNaked( GetCurrScope(), id );
        if( result == NULL ) {
            CErr2p( ERR_UNDECLARED_SYM, id );
        } else {
            sym_name = result->sym_name;
            sym = sym_name->name_syms;
            if( ! SymIsAnError( sym ) ) {
                if( seg_cast ) {
                    CErr2p( ERR_BASED_EXTRACT_NO_SEG, sym );
                } else {
                    type = sym->sym_type;
                    if( IntegralType( type ) != NULL ) {
                        mod = TF1_BASED_FETCH;
                        base_expr = sym;
                    } else {
                        type = PointerType( type );
                        based_msg = ERR_BASED_FETCH_NO_SEG;
                        if( type != NULL ) {
                            if( type->id != TYP_POINTER ) {
                                type = NULL;
                            } else if( type->flag & TF1_REFERENCE ) {
                                type = NULL;
                            } else if( BasedType( type->of ) != NULL ) {
                                based_msg = ERR_BASED_ON_BASED;
                                type = NULL;
                            }
                        }
                        if( type == NULL ) {
                            CErr2p( based_msg, sym );
                        } else {
                            mod = TF1_BASED_ADD;
                            base_expr = sym;
                        }
                    }
                    if( base_expr != NULL ) {
                        if( result->scope != GetCurrScope() ) {
                            verifyBasedRef( result, sym );
                        }
                    }
                }
                if( base_expr != NULL ) {
                    if( ScopeCheckSymbol( result, sym ) ) {
                        mod = TF1_BASED_VOID;
                        base_expr = NULL;
                    }
                }
            }
            ScopeFreeResult( result );
        }
    }
    return( makeFullModifier( mod, base_expr, NULL ) );
}

TYPE MakeBasedModifierOf(       // MAKE BASED MODIFIER FOR A TYPE
    TYPE type,                  // - basic type
    type_flag flags,            // - modifier flags
    void *baser )               // - baser
{
    if( flags == TF1_NULL ) {
        return( type );
    }
    return MakeTypeOf( makeFullModifier( flags, baser, NULL ), type );
}

static type_flag convertCVSpec( specifier_t spec )
{
    type_flag flag;

    flag = TF1_NULL;
    if( spec & STY_CONST ) {
        flag |= TF1_CONST;
    }
    if( spec & STY_VOLATILE ) {
        flag |= TF1_VOLATILE;
    }
    if( spec & STY_UNALIGNED ) {
        flag |= TF1_UNALIGNED;
    }
    return( flag );
}

static TYPE makeAnyPointer( type_id id, specifier_t cv_flags )
{
    TYPE ptype;
    type_flag cvflag;

    ptype = MakeType( id );
    cvflag = convertCVSpec( cv_flags );
    if( cvflag != NULL ) {
        /* build this backwards, since later processing reverses the list */
        ptype->of = MakeFlagModifier( cvflag );
    }
    return( ptype );
}

TYPE MakePointerType( type_flag ref_flag, specifier_t cv_flags )
/**************************************************************/
{
    TYPE ptype;

    ptype = makeAnyPointer( TYP_POINTER, cv_flags );
    ptype->flag |= ref_flag;
    return( ptype );
}

static TYPE makeMemberPointerType( TYPE class_type, specifier_t cv_flags )
/************************************************************************/
{
    TYPE ptype;

    ptype = makeAnyPointer( TYP_MEMBER_POINTER, cv_flags );
    ptype->u.mp.host = TypedefRemove( class_type );
    return( ptype );
}

static TYPE extractMemberType( PTREE tree )
{
    /* we have:

                        CO_INDIRECT
                            |
                        CO_COLON_COLON
                        /       \
                                <id>
    */
    TYPE type;

    type = tree->u.subtree[0]->u.subtree[1]->type;
    PTreeFreeSubtrees( tree );
    return( type );
}

TYPE MakeMemberPointer( PTREE class_tree, specifier_t cv_flags )
/**************************************************************/
{
    TYPE type;

    type = extractMemberType( class_tree );
    if( type != NULL ) {
        type = makeMemberPointerType( type, cv_flags );
    }
    return( type );
}

TYPE MakeSeg16Pointer( specifier_t cv_flags )
/*******************************************/
{
    TYPE ptr_type;
    TYPE mod_type;

    ptr_type = makeAnyPointer( TYP_POINTER, cv_flags );
    mod_type = MakeFlagModifier( TF1_SET_FAR16 );
    mod_type->of = ptr_type;
    return( mod_type );
}

TYPE MakeMemberPointerTo( TYPE class_type, TYPE base_type )
/*********************************************************/
{
    TYPE mptr_type;
    TYPE unmod_type;
    type_flag flags;
    void *base;

    class_type = StructType( class_type );
    mptr_type = makeMemberPointerType( class_type, STY_NULL );
    base_type = TypeReferenced( base_type );
    unmod_type = TypeModExtract( base_type, &flags, &base, TC1_NOT_ENUM_CHAR );
    if( flags & TF1_MPTR_REMOVE ) {
        flags &= ~TF1_MPTR_REMOVE;
        base_type = MakeBasedModifierOf( unmod_type, flags, base );
    }
    return MakeTypeOf( mptr_type, base_type );
}

static boolean newTypeIllegal( TYPE type )
{
    boolean error_occurred;
    TYPE test_type;
    type_flag flags;

    error_occurred = FALSE;
    test_type = TypeModFlags( type, &flags );
    switch( test_type->id ) {
    case TYP_FUNCTION:
        CErr1( ERR_NEW_TYPE_FUNCTION );
        error_occurred = TRUE;
        break;
    case TYP_VOID:
        CErr1( ERR_NEW_TYPE_VOID );
        error_occurred = TRUE;
        break;
    }
    if( flags & TF1_CV_MASK ) {
        CErr1( WARN_NEW_TYPE_CONST_VOLATILE );
    }
    return( error_occurred );
}

void CheckNewModifier( type_flag flags )
/**************************************/
{
    if( flags & ~TF1_MEM_MODEL ) {
        CErr1( ERR_INVALID_NEW_MODIFIER );
    } else {
        flags &= TF1_MEM_MODEL;
        if( flags != defaultDataMemFlag ) {
            CErr1( ERR_INVALID_NEW_MODIFIER );
        }
    }
}

PTREE MakeNewExpr( PTREE gbl, PTREE placement, DECL_INFO *dinfo, PTREE init )
/***************************************************************************/
{
    PTREE nelem_expr;
    PTREE new_parms1;
    PTREE new_parms2;
    PTREE new_expr;
    PTREE new_type;
    CGOP new_op;
    TYPE type;

    new_op = CO_NEW;
    if( gbl != NULL ) {
        PTreeFreeSubtrees( gbl );
        new_op = CO_NEW_G;
    }
    nelem_expr = dinfo->defarg_expr;
    if( nelem_expr != NULL ) {
        // detach from 'dinfo'
        dinfo->defarg_expr = NULL;
    }
    type = dinfo->type;
    FreeDeclInfo( dinfo );
    if( newTypeIllegal( type ) ) {
        PTreeFreeSubtrees( init );
        new_expr = PTreeErrorNode( placement );
    } else {
        new_type = PTreeType( type );
        new_parms2 = PTreeBinary( CO_NEW_PARMS2, nelem_expr, init );
        new_parms1 = PTreeBinary( CO_NEW_PARMS1, placement, new_parms2 );
        new_expr = PTreeBinary( new_op, new_type, new_parms1 );
    }
    return( new_expr );
}

DECL_INFO *MakeNewTypeId( PTREE type_id )
/***************************************/
{
    TYPE new_type;
    DECL_INFO *dinfo;

    new_type = type_id->type;
    PTreeFree( type_id );
    dinfo = makeDeclInfo( NULL );
    dinfo->type = new_type;
    return( dinfo );
}

static boolean dupCompare( TYPE test1, TYPE test2 )
{
    arg_list *args1;
    arg_list *args2;
    TYPE *p1;
    TYPE *p2;
    unsigned i;

    /* check TypedefReset if TYP_TYPEDEFs are ever checked */
    /* check typesBind/performBinding (in this module) if comparisons change */
    /* check TYPECOMP.C if comparisons change */
    switch( test1->id ) {
    case TYP_BITFIELD:
        if( test1->u.b.field_start != test2->u.b.field_start ) {
            return( FALSE );
        }
        if( test1->u.b.field_width != test2->u.b.field_width ) {
            return( FALSE );
        }
        break;
    case TYP_FUNCTION:
        if( test1->u.f.pragma != test2->u.f.pragma ) {
            return( FALSE );
        }
        args1 = test1->u.f.args;
        args2 = test2->u.f.args;
        if( args1 == args2 ) {
            return( TRUE );
        }
        if( args1->num_args != args2->num_args ) {
            return( FALSE );
        }
        if( args1->qualifier != args2->qualifier ) {
            return( FALSE );
        }
        p1 = args1->type_list;
        p2 = args2->type_list;
        for( i = args1->num_args; i != 0; --i ) {
            if( *p1 != *p2 ) {
                return( FALSE );
            }
            ++p1;
            ++p2;
        }
        p1 = args1->except_spec;
        p2 = args2->except_spec;
        if( p1 != p2 ) {
            TYPE tp1, tp2;
            if( p1 == NULL || p2 == NULL ) {
                return( FALSE );
            }
            for(;;) {
                tp1 = *p1;
                if( tp1 == NULL ) return FALSE;
                tp2 = *p2;
                if( tp2 == NULL ) return FALSE;
                if( tp1 != tp2 ) return FALSE;
                ++p1;
                ++p2;
            }
        }
        break;
    case TYP_ARRAY:
        if( test1->u.a.array_size != test2->u.a.array_size ) {
            return( FALSE );
        }
        break;
    case TYP_MODIFIER:
        if( test1->u.m.base != test2->u.m.base ) {
            return( FALSE );
        }
        if( test1->u.m.pragma != test2->u.m.pragma ) {
            return( FALSE );
        }
        break;
    case TYP_MEMBER_POINTER:
        if( test1->u.mp.host != test2->u.mp.host ) {
            return( FALSE );
        }
        break;
    case TYP_GENERIC:
        if( test1->u.g.index != test2->u.g.index ) {
            return( FALSE );
        }
        break;
    case TYP_ERROR:
        if( test1->u.e.fmt != test2->u.e.fmt ) {
            return( FALSE );
        }
        break;
    case TYP_POINTER:
        break;
    default:
#ifndef NDEBUG

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?