?? cmath2.c
字號(hào):
if( op1->op.long_value != 0 ) {
FreeExprNode( op1 );
return( op2 );
}
}
}
if( op2->op.opr == OPR_PUSHINT ) {
if( opr == OPR_OR_OR ) {
if( op2->op.long_value == 0 ) {
FreeExprNode( op2 );
return( op1 );
}
} else { // OPR_AND_AND
if( op2->op.long_value != 0 ) {
FreeExprNode( op2 );
return( op1 );
}
}
}
tree = ExprNode( op1, opr, op2 );
tree->expr_type = GetType( TYPE_INT );
tree->op.label_index = NextLabel();
return( tree );
}
local TREEPTR MulByConst( TREEPTR opnd, long amount )
{
TREEPTR tree;
if( opnd->op.opr == OPR_PUSHINT ) {
opnd->op.long_value *= amount;
return( opnd );
}
switch( TypeOf( opnd )->decl_type ) {
case TYPE_LONG:
case TYPE_ULONG:
tree = ExprNode( opnd, OPR_MUL, LongLeaf( amount ) );
tree->expr_type = GetType( TYPE_LONG );
break;
case TYPE_INT:
case TYPE_UINT:
default:
tree = ExprNode( opnd, OPR_MUL, IntLeaf( amount ) );
tree->expr_type = GetType( TYPE_INT );
}
tree->op.result_type = tree->expr_type;
return( tree );
}
local TREEPTR PtrSubtract( TREEPTR result, unsigned long size,int result_type)
{
int shift_count;
int n;
TREEPTR tree;
TYPEPTR typ;
typ = GetType( result_type );
result->expr_type = typ;
result->op.result_type = typ;
for( n = 2, shift_count = 1; shift_count < 8; ++shift_count ) {
if( n == size ) {
tree = ExprNode( result, OPR_RSHIFT, IntLeaf( shift_count ) );
tree->expr_type = typ;
tree->op.result_type = typ;
return( tree );
}
n *= 2;
}
if( result_type == INT ) {
tree = ExprNode( result, OPR_DIV, IntLeaf( size ) );
tree->expr_type = GetType( TYPE_INT );
} else {
tree = ExprNode( result, OPR_DIV, LongLeaf( size ) );
tree->expr_type = GetType( TYPE_LONG );
}
tree->op.result_type = tree->expr_type;
return( tree );
}
extern TREEPTR LCastAdj( TREEPTR tree ){
// Remove the OPR_CONVERT for lcast so it looks like an LVALUE
TREEPTR opnd;
TYPEPTR typ;
type_modifiers modifiers;
opnd = tree->right;
tree->right = NULL;
typ = tree->expr_type;
opnd->expr_type = typ;
FreeExprTree( tree );
CWarn1( WARN_LVALUE_CAST, ERR_LVALUE_CAST );
opnd->op.flags &= ~OPFLAG_RVALUE;
if( opnd->op.opr == OPR_PUSHSYM ){
opnd->op.opr = OPR_PUSHADDR;
} else if( opnd->op.opr == OPR_POINTS ) {
// fix up fred's screw ball pointer op
modifiers = FlagOps( opnd->op.flags );
opnd->op.result_type = PtrNode( typ, modifiers, SEG_DATA );
}
return( opnd );
}
static void CheckAddrOfArray( TREEPTR opnd )
{
TYPEPTR typ;
if( opnd->op.opr == OPR_ADDROF ) {
typ = opnd->expr_type->object;
if( typ != NULL ){
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type == TYPE_ARRAY ) {
CWarn1( WARN_ADDR_OF_ARRAY, ERR_ADDR_OF_ARRAY );
}
}
}
}
static TYPEPTR PtrofSym( SYM_HANDLE sym_handle, TYPEPTR typ ){
SYM_ENTRY sym;
SymGet( &sym, sym_handle );
typ = PtrNode( typ, sym.attrib, SEG_DATA );
return( typ );
}
static TREEPTR ArrayPlusConst( TREEPTR op1, TREEPTR op2 )
{
TREEPTR result;
TYPEPTR typ;
CheckAddrOfArray( op1 );
if( op2->op.opr == OPR_PUSHINT ) {
if( op1->op.opr == OPR_PUSHADDR ) {
typ = op1->expr_type;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type == TYPE_ARRAY ) {
op2->op.long_value *= SizeOfArg( typ->object );
typ = PtrofSym( op1->op.sym_handle, typ->object );
result = ExprNode( op1, OPR_ADD, op2 );
result->expr_type = typ;
result->op.result_type = typ;
return( result );
}
}
}
return( 0 );
}
static TREEPTR ArrayMinusConst( TREEPTR op1, TREEPTR op2 )
{
TREEPTR result;
TYPEPTR typ;
CheckAddrOfArray( op1 );
if( op2->op.opr == OPR_PUSHINT ) {
if( op1->op.opr == OPR_PUSHADDR ) {
typ = op1->expr_type;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type == TYPE_ARRAY ) {
op2->op.long_value =
(- op2->op.long_value) * SizeOfArg( typ->object );
typ = PtrofSym( op1->op.sym_handle, typ->object );
result = ExprNode( op1, OPR_ADD, op2 );
result->expr_type = typ;
result->op.result_type = typ;
return( result );
}
}
}
return( 0 );
}
TREEPTR AddOp( TREEPTR op1, TOKEN opr, TREEPTR op2 )
{
DATA_TYPE op1_type, op2_type, result_type;
TYPEPTR op1_tp, op2_tp;
TYPEPTR res_type;
unsigned long size;
TREEPTR result;
TREEPTR tree;
if( op1->op.opr == OPR_ERROR ) {
FreeExprTree( op2 );
return( op1 );
}
switch( opr ) {
case T_PLUS_EQUAL:
case T_PLUS_PLUS:
case T_MINUS_EQUAL:
case T_MINUS_MINUS:
if( (op1->op.opr == OPR_CONVERT || op1->op.opr == OPR_CONVERT_PTR)
&& CompFlags.extensions_enabled ) {
op1 = LCastAdj( op1 );
}
LValue( op1 );
break;
case T_MINUS:
result = ArrayMinusConst( op1, op2 );
if( result != 0 ) return( result );
op1 = RValue( op1 );
break;
case T_PLUS:
result = ArrayPlusConst( op1, op2 ); // check for array + const
if( result != 0 ) return( result );
result = ArrayPlusConst( op2, op1 ); // check for const + array
if( result != 0 ) return( result );
default:
op1 = RValue( op1 );
}
op2 = RValue( op2 );
if( op1->op.opr == OPR_ERROR ) {
FreeExprTree( op2 );
return( op1 );
}
if( op2->op.opr == OPR_ERROR ) {
FreeExprTree( op1 );
return( op2 );
}
op1_tp = TypeOf( op1 );
op2_tp = TypeOf( op2 );
op1_type = DataTypeOf( op1_tp->decl_type );
op2_type = DataTypeOf( op2_tp->decl_type );
result = 0;
if( op1_type == TYPE_UNION || op1_type == TYPE_STRUCT
|| op2_type == TYPE_UNION || op2_type == TYPE_STRUCT ) {
result_type = ERR;
} else if( op1_type == TYPE_VOID ||
op2_type == TYPE_VOID ||
op1_type == TYPE_ARRAY ) { /* ++array; or --array; */
result_type = INT;
} else {
switch( opr ) {
case T_PLUS:
result_type = AddResult[ op1_type ][ op2_type ];
break;
case T_PLUS_PLUS:
case T_MINUS_MINUS:
case T_PLUS_EQUAL:
case T_MINUS_EQUAL:
switch( op1_tp->decl_type ) {
case TYPE_ENUM:
result_type = op1_tp->object->decl_type;
break;
default:
result_type = op1_type;
break;
}
if( op2_type == TYPE_UNION || op2_type == TYPE_STRUCT ) {
result_type = ERR;
} else
if( op1_type == TYPE_POINTER && op2_type >= TYPE_FLOAT ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
}
break;
#if 0
result_type = op1_type;
break;
#endif
default:
result_type = SubResult[ op1_type ][ op2_type ];
if(( op1_type == PTR )&&( op2_type == PTR )) {
/* make sure both pointers are same type */
CompatiblePtrType( op1_tp, op2_tp );
if(( op1_tp->u.p.decl_flags & FLAG_HUGE ) ||
( op2_tp->u.p.decl_flags & FLAG_HUGE ) ) {
result_type = LNG;
} else if((TargetSwitches & (BIG_DATA|CHEAP_POINTER))
== BIG_DATA ) {
if(( (op1_tp->u.p.decl_flags & (FLAG_FAR|FLAG_NEAR)) == 0 )
&& ((op2_tp->u.p.decl_flags & (FLAG_FAR|FLAG_NEAR)) == 0)){
result_type = LNG;
}
}
}
}
}
if( result_type == ERR ) {
CErr1( ERR_EXPR_MUST_BE_SCALAR );
result_type = INT;
}
if( op1_type == PTR ) {
res_type = TypeOf( op1 );
size = SizeOfArg( res_type->object );
if( size == 0 ) {
CErr1( ERR_CANT_USE_VOID );
size = 1;
}
/* subtraction of 2 pointers */
if(( result_type == INT )||( result_type == LNG )) {
res_type = GetType( result_type );
}
if( size != 1 ) {
/* subtraction of 2 pointers */
if(( result_type == INT )||( result_type == LNG )) {
result = ExprNode( op1, TokenToOperator(opr), op2 );
return( PtrSubtract( result, size, result_type ) );
} else if(( op1_tp->u.p.decl_flags & FLAG_HUGE ) ||
((TargetSwitches & (BIG_DATA|CHEAP_POINTER))==BIG_DATA)){
if(( op2_type != LNG )&&( op2_type != ULN )) {
op2 = CnvOp( op2, GetType( TYPE_LONG ), 1 );
}
}
op2 = MulByConst( op2, size );
}
} else if( op2_type == PTR ) { /* && op1_type != PTR */
if( opr == T_PLUS_EQUAL || opr == T_MINUS_EQUAL || opr == T_MINUS ){
CErr2p( ERR_RIGHT_OPERAND_IS_A_POINTER, Tokens[opr] );
}
res_type = TypeOf( op2 );
size = SizeOfArg( res_type->object );
if( size == 0 ) {
CErr1( ERR_CANT_USE_VOID );
size = 1;
}
if( size != 1 ) {
if(( op2_tp->u.p.decl_flags & FLAG_HUGE ) ||
(( TargetSwitches & (BIG_DATA|CHEAP_POINTER)) == BIG_DATA )) {
if(( op1_type != LNG )&&( op1_type != ULN )) {
#if 0 /* 29-jul-88 AFS */
op1 = Convert( op1, op1_type, LNG );
#else
op2 = CnvOp( op2, GetType( TYPE_LONG ), 1 );
#endif
}
}
op1 = MulByConst( op1, size );
}
} else {
res_type = GetType( result_type );
op1 = Convert( op1, op1_type, result_type );
op2 = Convert( op2, op2_type, result_type );
}
tree = ExprNode( op1, TokenToOperator(opr), op2 );
tree->expr_type = res_type;
tree->op.result_type = res_type;
return( tree );
}
TREEPTR BinOp( TREEPTR op1, TOKEN opr, TREEPTR op2 )
{
type_modifiers op1_type, op2_type, result_type;
TREEPTR tree;
TYPEPTR typ;
if( op1->op.opr == OPR_ERROR ) {
FreeExprTree( op2 );
return( op1 );
}
op2 = RValue( op2 );
if( op2->op.opr == OPR_ERROR ) {
FreeExprTree( op1 );
return( op2 );
}
typ = TypeOf( op1 );
op1_type = DataTypeOf( typ->decl_type );
op2_type = DataTypeOf( TypeOf( op2 )->decl_type );
if( op1_type == TYPE_VOID || op2_type == TYPE_VOID ) {
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -