📄 cmath2.c
字号:
(newtyp->u.p.decl_flags & FLAG_FAR) ) {
opnd = BasedPtrNode( typ,opnd);
opnd->expr_type = newtyp;
opnd->op.result_type = newtyp;
return( opnd );
}
cast_op = 1; /* force a convert */
}
} else if( FuncPtr(typ) || FuncPtr(newtyp) ) {
cast_op = 1; /* force a convert */
} else if( TypeSize(typ) != TypeSize(newtyp) ) {
/* 25-apr-88*/
cast_op = 1; /* force a convert */
} else if( typ->decl_type != TYPE_POINTER ||
newtyp->decl_type != TYPE_POINTER ) {
/* 19-jan-89 */
cast_op = 1; /* force a convert */
} else if( opr == OPR_PUSHADDR &&
opnd->op.opr == OPR_ADDROF ) {
opnd->expr_type = newtyp;
return( opnd );
} else if( cast_op && CompFlags.extensions_enabled ) {
/* 15-oct-92: We know the following: */
/* - it is a cast operation */
/* - both types are pointers */
/* - extensions are enabled */
/* - both pointers are the same size */
/* - neither pointer is a function pointer */
/* So, if it is still an lvalue */
/* - then just update the type and leave it */
/* - as an lvalue. This will allow the */
/* - following statement to get through without */
/* - generating an error! */
/* (char *)p += 2; */
if( opr == OPR_PUSHADDR || IsLValue( opnd ) ) {
/* don't do it for based or far16. 27-oct-92*/
if( !Far16Pointer(opnd->op.flags) ) {
opnd->expr_type = newtyp;
opnd->op.opr = opr;
opnd->op.flags |= OPFLAG_LVALUE_CAST;
return( opnd );
}
}
}
}
if( cast_op || cnv != P2P ) {
/* convert: moved 30-aug-89 */
if( opnd->op.opr == OPR_PUSHINT ||
opnd->op.opr == OPR_PUSHFLOAT ) {
CastConstValue( opnd, newtyp->decl_type );
opnd->expr_type = newtyp;
} else {
pointer_class new_class;
pointer_class old_class;
new_class = ExprTypeClass( newtyp );
old_class = ExprTypeClass( typ );
if( new_class != old_class &&
(new_class == PTR_FAR16 || old_class == PTR_FAR16 ) ) {// foriegn pointers
opnd = ExprNode( NULL, OPR_CONVERT_PTR, opnd );
opnd->op.oldptr_class = old_class;
opnd->op.newptr_class = new_class;
} else {
opnd = ExprNode( NULL, OPR_CONVERT, opnd );
opnd->op.result_type = newtyp;
}
opnd->expr_type = newtyp;
}
}
} else if( opnd->op.opr == OPR_PUSHINT ||
opnd->op.opr == OPR_PUSHFLOAT ) {
CastConstValue( opnd, newtyp->decl_type );
opnd->expr_type = newtyp;
} else if( opnd->expr_type != newtyp ) {
opnd = ExprNode( 0, OPR_CONVERT, opnd );
opnd->expr_type = newtyp;
opnd->op.result_type = newtyp;
}else{ //NIL convert
opnd->op.flags |= flags;
}
}
return( opnd );
}
TREEPTR ParmAss( TREEPTR opnd, TYPEPTR newtyp )
{
//TODO check out base ptrs
TYPEPTR typ;
enum conv_types cnv;
DATA_TYPE decl1;
DATA_TYPE decl2;
if( opnd->op.opr == OPR_ERROR ) return( opnd );
opnd = BaseConv( newtyp, opnd );
newtyp = SkipTypeFluff( newtyp );
typ = SkipTypeFluff( opnd->expr_type );
decl1 = DataTypeOf( typ->decl_type );
decl2 = DataTypeOf( newtyp->decl_type );
if( decl1 > TYPE_POINTER || decl2 > TYPE_POINTER ){
return( opnd );
}
cnv = CnvTable[ decl1 ][ decl2 ];
if( cnv == CER ) {
return( opnd );
} else if( cnv == P2P ){
pointer_class new_class;
pointer_class old_class;
new_class = ExprTypeClass( newtyp );
old_class = ExprTypeClass( typ );
if( new_class != old_class ){
opnd = ExprNode( NULL, OPR_CONVERT_PTR, opnd );
opnd->op.oldptr_class = old_class;
opnd->op.newptr_class = new_class;
} else {
opnd = ExprNode( NULL, OPR_CONVERT, opnd );
opnd->op.result_type = newtyp;
}
}else{
if( opnd->op.opr == OPR_PUSHINT || opnd->op.opr == OPR_PUSHFLOAT ) {
CastConstValue( opnd, newtyp->decl_type );
}else{
opnd = ExprNode( NULL, OPR_CONVERT, opnd );
opnd->op.result_type = newtyp;
}
}
opnd->expr_type = newtyp;
return( opnd );
}
TREEPTR UMinus( TREEPTR opnd )
{
// FLOATVAL *flt;
DATA_TYPE t;
opnd = RValue( opnd );
if( opnd->op.opr != OPR_ERROR ){
t = DataTypeOf( TypeOf( opnd )->decl_type );
if( t != TYPE_VOID ){
if( t >= TYPE_POINTER ) {
CErr1( ERR_EXPR_MUST_BE_ARITHMETIC );
opnd = ErrorNode( opnd );
} else {
opnd = ExprNode( 0, OPR_NEG, opnd );
opnd->expr_type = GetType( SubResult[t][t] );
opnd->op.result_type = opnd->expr_type;
}
}
}
#if 0
switch( opnd->op.opr ) {
case OPR_ERROR:
break;
case OPR_PUSHINT:
switch( opnd->op.const_type ) {
case TYPE_CHAR:
case TYPE_UCHAR:
opnd->op.long_value = -(char)opnd->op.long_value;
break;
case TYPE_SHORT:
case TYPE_USHORT:
opnd->op.long_value = -(short)opnd->op.long_value;
break;
case TYPE_INT:
opnd->op.long_value = -(target_int)opnd->op.long_value;
break;
case TYPE_UINT:
opnd->op.long_value =
(target_uint)( - (target_uint)opnd->op.long_value);
break;
case TYPE_LONG:
case TYPE_ULONG:
opnd->op.long_value = - opnd->op.long_value;
break;
}
break;
case OPR_PUSHFLOAT:
flt = opnd->op.float_value;
if( flt->len != 0 ) { // if still in string form
flt->string[0] ^= '+' ^ '-';// - change '+' to '-' and vice versa
} else { // else
#ifdef _LONG_DOUBLE_
flt->ld.exponent ^= 0x8000; // - flip binary sign bit
#else
flt->ld.word[1] ^= 0x80000000; // - flip sign
#endif
}
break;
default:
t = DataTypeOf( TypeOf( opnd )->decl_type );
if( t == TYPE_VOID ) break;
if( t >= TYPE_POINTER ) {
CErr1( ERR_EXPR_MUST_BE_ARITHMETIC );
opnd = ErrorNode( opnd );
} else {
opnd = ExprNode( 0, OPR_NEG, opnd );
opnd->expr_type = GetType( SubResult[t][t] );
opnd->op.result_type = opnd->expr_type;
}
break;
}
#endif
return( opnd );
}
TREEPTR UComplement( TREEPTR opnd )
{
int t;
TYPEPTR typ;
opnd = RValue( opnd );
if( opnd->op.opr != OPR_ERROR ){
typ = opnd->expr_type;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
t = DataTypeOf( typ->decl_type );
if( t != TYPE_VOID ){
if( t >= TYPE_FLOAT ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
opnd = ErrorNode( opnd );
} else {
opnd = ExprNode( 0, OPR_COM, opnd );
opnd->expr_type = GetType( SubResult[t][t] );
opnd->op.result_type = opnd->expr_type;
}
}
}
#if 0
switch( opnd->op.opr ) {
case OPR_ERROR:
break;
case OPR_PUSHINT:
switch( opnd->op.const_type ) {
case TYPE_CHAR:
case TYPE_UCHAR:
opnd->op.long_value = (char) ~ opnd->op.long_value;
break;
case TYPE_SHORT:
case TYPE_USHORT:
opnd->op.long_value = (short) ~ opnd->op.long_value;
break;
case TYPE_INT:
opnd->op.long_value = (target_int) ~ opnd->op.long_value;
break;
case TYPE_UINT:
opnd->op.ulong_value = (target_uint) ~ opnd->op.ulong_value;
break;
case TYPE_LONG:
case TYPE_ULONG:
opnd->op.ulong_value = ~ opnd->op.ulong_value;
break;
}
break;
default:
typ = opnd->expr_type;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
t = DataTypeOf( typ->decl_type );
if( t == TYPE_VOID ) break;
if( t >= TYPE_FLOAT ) {
CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
opnd = ErrorNode( opnd );
} else {
opnd = ExprNode( 0, OPR_COM, opnd );
opnd->expr_type = GetType( SubResult[t][t] );
opnd->op.result_type = opnd->expr_type;
}
break;
}
#endif
return( opnd );
}
local TYPEPTR MergedType( TYPEPTR typ1, TYPEPTR typ2 ) /* 25-jul-90 */
{
int flags, new_flags;
TYPEPTR typ;
/*
(type huge *) : (type *) -> (type huge *)
(type *) : (type huge *) -> (type huge *)
(type far *) : (type *) -> (type far *)
(type *) : (type far *) -> (type far *)
(type const *) : (type *) -> (type const *)
(type *) : (type const *) -> (type const *)
(type volatile *) : (type *) -> (type volatile *)
(type *) : (type volatile *) -> (type volatile *)
etc.
*/
typ = typ1;
flags = typ1->u.p.decl_flags | typ2->u.p.decl_flags;
new_flags = flags & (FLAG_CONST | FLAG_VOLATILE);
if( flags & FLAG_HUGE ) {
new_flags |= FLAG_HUGE;
} else if( flags & FLAG_FAR ) {
new_flags |= FLAG_FAR;
} else if( (typ1->u.p.decl_flags & FLAG_NEAR) /* 12-may-91 */
&& (typ2->u.p.decl_flags & FLAG_NEAR) ) {
new_flags |= FLAG_NEAR;
}
if( typ1->u.p.decl_flags != typ2->u.p.decl_flags ) {
typ = PtrNode( typ1->object, new_flags, typ1->u.p.segment );
}
return( typ );
}
TYPEPTR TernType( TREEPTR true_part, TREEPTR false_part )
/*******************************************************/
{
TYPEPTR typ1;
TYPEPTR typ2;
type_modifiers dtype1, dtype2;
typ1 = true_part->expr_type;
while( typ1->decl_type == TYPE_TYPEDEF ) typ1 = typ1->object;
typ2 = false_part->expr_type;
while( typ2->decl_type == TYPE_TYPEDEF ) typ2 = typ2->object;
/*
(type1) : (type1) -> (type1)
nb. structs, unions, and identical pointers are handled here
*/
if( typ1 == typ2 ) return( typ1 );
dtype1 = DataTypeOf( typ1->decl_type );
dtype2 = DataTypeOf( typ2->decl_type );
if( dtype1 == TYPE_POINTER && false_part->op.opr == OPR_PUSHINT ){
if( false_part->op.long_value != 0 ) {
CWarn1( WARN_NONPORTABLE_PTR_CONV,
ERR_NONPORTABLE_PTR_CONV );
}
return( typ1 );
}
if( dtype2 == TYPE_POINTER && true_part->op.opr == OPR_PUSHINT ){
if( true_part->op.long_value != 0 ) {
CWarn1( WARN_NONPORTABLE_PTR_CONV,
ERR_NONPORTABLE_PTR_CONV );
}
return( typ2 );
}
/*
(arithmetic type) : (arithmetic type) -> (promoted arithmetic type)
*/
if(( dtype1 <= TYPE_DOUBLE )&&( dtype2 <= TYPE_DOUBLE )) {
return( GetType( SubResult[dtype1][dtype2] ) );
}
TernChk( typ1, typ2 );
if( dtype1 == TYPE_POINTER && dtype2 == TYPE_POINTER ) {
/*
(void *) : (anything *) -> (void *)
*/
if( typ1->object->decl_type == TYPE_VOID ) {
return( MergedType( typ1, typ2 ) );
} else if( typ2->object->decl_type == TYPE_VOID ) {
return( MergedType( typ2, typ1 ) );
} else {
return( MergedType( typ1, typ2 ) );
}
}
return( typ1 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -