📄 cfold2.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "i64.h"
#include "cvars.h"
#ifdef __WATCOMC__
extern int __Strtold(char *,long_double *,char **);
#endif
uint_32 DoOp32( uint_32 left, opr_code opr, uint_32 right, bool sign )
{
uint_32 value;
switch( opr ) {
case OPR_ADD:
value = left + right;
break;
case OPR_SUB:
value = left - right;
break;
case OPR_MUL:
value = left * right;
break;
case OPR_DIV:
if( right == 0 ) { /* 10-mar-90 */
value = 0;
} else {
if( sign ){
value = (int_32)left / (int_32)right;
}else{
value = left / right;
}
}
break;
case OPR_MOD:
if( right == 0 ) { /* 10-mar-90 */
value = 0;
} else {
if( sign ){
value = (int_32)left % (int_32)right;
}else{
value = left % right;
}
}
break;
case OPR_RSHIFT:
if( sign ){
value = (int_32)left >> (int_32)right;
}else{
value = left >> right;
}
break;
case OPR_LSHIFT:
value = left << right;
break;
case OPR_OR:
value = left | right;
break;
case OPR_OR_OR:
value = left || right;
break;
case OPR_AND:
value = left & right;
break;
case OPR_AND_AND:
value = left && right;
break;
case OPR_XOR:
value = left ^ right;
break;
case OPR_NEG:
value = - right;
break;
case OPR_COM:
value = ~ right;
break;
case OPR_NOT:
value = ! right;
break;
default:
value = 0;
}
return( value );
}
uint64 DoOp64( uint64 left, opr_code opr, uint64 right, bool sign )
{
uint64 tmp;
uint64 value;
int shift;
switch( opr ) {
case OPR_ADD:
U64Add( &left, &right, &value );
break;
case OPR_SUB:
U64Sub( &left, &right, &value );
break;
case OPR_MUL:
U64Mul( &left, &right, &value );
break;
case OPR_DIV:
U32ToU64( 0, &value );
if( U64Cmp( &right, &value ) != 0 ){
if( sign ){
I64Div( &left, &right, &value, &tmp );
}else{
U64Div( &left, &right, &value, &tmp );
}
}
break;
case OPR_MOD:
U32ToU64( 0, &value );
if( U64Cmp( &right, &value ) != 0 ){
if( sign ){
I64Div( &left, &right, &tmp, &value );
}else{
U64Div( &left, &right, &tmp, &value );
}
}
break;
case OPR_LSHIFT:
shift = right.u._32[L];
shift = -shift;
goto do_shift;
case OPR_RSHIFT:
shift = right.u._32[L];
do_shift:
if( shift > 0 ){
if( sign ){
I64ShiftR( &left, shift, &value );
}else{
U64ShiftR( &left, shift, &value );
}
}else{
shift = -shift;
U64ShiftL( &left, shift, &value );
}
break;
case OPR_OR:
value = left;
value.u._32[L] |= right.u._32[L];
value.u._32[H] |= right.u._32[H];
break;
case OPR_OR_OR:
U32ToU64( 0, &value );
if( U64Cmp( &left, &value ) || U64Cmp( &right, &value ) ){
U32ToU64( 1, &value );
}
break;
case OPR_AND:
value = left;
value.u._32[L] &= right.u._32[L];
value.u._32[H] &= right.u._32[H];
break;
case OPR_AND_AND:
U32ToU64( 0, &value );
if( U64Cmp( &left, &value ) && U64Cmp( &right, &value ) ){
U32ToU64( 1, &value );
}
break;
case OPR_XOR:
value = left;
value.u._32[L] ^= right.u._32[L];
value.u._32[H] ^= right.u._32[H];
break;
case OPR_NEG:
U64Neg( &right, &value );
// value = - right;
break;
case OPR_COM:
value.u._32[L] = ~right.u._32[L];
value.u._32[H] = ~right.u._32[H];
break;
case OPR_NOT:
U32ToU64( 0, &value );
if( U64Cmp( &right, &value ) == 0 ){
U32ToU64( 1, &value );
}
break;
default:
U32ToU64( 0, &value );
}
return( value );
}
int DoSignedOp( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/******************************************************/
{
int_32 value;
int_32 left;
int_32 right;
DATA_TYPE const_type;
const_type = tree->expr_type->decl_type;
if( op1 != NULL ){
left = op1->op.long_value;
}
right = op2->op.long_value;
if( tree->op.opr == OPR_CMP ) {
switch( tree->op.cc ) {
case CC_EQ:
value = ( left == right );
break;
case CC_NE:
value = ( left != right );
break;
case CC_GT:
value = ( left > right );
break;
case CC_GE:
value = ( left >= right );
break;
case CC_LT:
value = ( left < right );
break;
case CC_LE:
value = ( left <= right );
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)value;
}else{
value = DoOp32( left, tree->op.opr, right, TRUE );
if( const_type == TYPE_LONG ) {
tree->op.long_value = value;
} else {
tree->op.long_value = (target_int)value;
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
int DoUnSignedOp( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/********************************************************/
{
uint_32 value;
uint_32 left;
uint_32 right;
DATA_TYPE const_type;
const_type = tree->expr_type->decl_type;
if( op1 != NULL ){
left = op1->op.ulong_value;
}
right = op2->op.ulong_value;
if( tree->op.opr == OPR_CMP ) {
switch( tree->op.cc ) {
case CC_EQ:
value = ( left == right );
break;
case CC_NE:
value = ( left != right );
break;
case CC_GT:
value = ( left > right );
break;
case CC_GE:
value = ( left >= right );
break;
case CC_LT:
value = ( left < right );
break;
case CC_LE:
value = ( left <= right );
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)value;
}else{
value = DoOp32( left, tree->op.opr, right, FALSE );
if( const_type == TYPE_ULONG ) {
tree->op.long_value = value;
} else {
tree->op.long_value = (target_uint)value;
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
static int64 LongValue64( TREEPTR leaf )
{
int64 value;
int_32 val32;
FLOATVAL *flt;
char *endptr;
long_double ld;
bool sign;
switch( leaf->op.const_type ) {
case TYPE_CHAR:
sign = TRUE;
val32 = (signed char)leaf->op.ulong_value;
break;
case TYPE_UCHAR:
sign = FALSE;
val32 = (unsigned char)leaf->op.ulong_value;
break;
case TYPE_SHORT:
sign = TRUE;
val32 = (target_short)leaf->op.ulong_value;
break;
case TYPE_USHORT:
sign = FALSE;
val32 = (target_ushort)leaf->op.ulong_value;
break;
case TYPE_INT:
sign = TRUE;
val32 = (target_int)leaf->op.ulong_value;
break;
case TYPE_UINT:
sign = FALSE;
val32 = (target_uint)leaf->op.ulong_value;
break;
case TYPE_LONG:
sign = TRUE;
val32 = (target_long)leaf->op.ulong_value;
break;
case TYPE_POINTER:
case TYPE_ULONG:
sign = FALSE;
val32 = (target_ulong)leaf->op.ulong_value;
break;
case TYPE_LONG64:
case TYPE_ULONG64:
return( leaf->op.ulong64_value );
break;
case TYPE_FLOAT:
case TYPE_DOUBLE:
sign = TRUE;
flt = leaf->op.float_value;
if( flt->len == 0 ) {
ld = flt->ld;
} else {
__Strtold( flt->string, &ld, &endptr );
}
CMemFree( flt );
#ifdef _LONG_DOUBLE_
val32 = __LDI4( (long_double near *)&ld );
#else
val32 = ld.value;
#endif
break;
default:
val32 = 0;
break;
}
if( sign ){
I32ToI64( val32, &value );
}else{
U32ToU64( val32, &value );
}
return( value );
}
int DoUnSignedOp64( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/********************************************************/
{
uint64 value;
uint64 left;
uint64 right;
int tmp;
DATA_TYPE const_type;
if( op1 != NULL ){
left = LongValue64( op1 );
}
right = LongValue64( op2 );
const_type = tree->expr_type->decl_type;
if( tree->op.opr == OPR_CMP ) {
tmp = U64Cmp( &left, &right );
switch( tree->op.cc ) {
case CC_EQ:
tmp = tmp == 0;
break;
case CC_NE:
tmp = tmp != 0;
break;
case CC_GT:
tmp = tmp > 0;
break;
case CC_LE:
tmp = tmp <= 0;
break;
case CC_GE:
tmp = tmp >= 0;
break;
case CC_LT:
tmp = tmp < 0;
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)tmp;
}else{
value = DoOp64( left, tree->op.opr, right, FALSE );
if( const_type == TYPE_ULONG64 ){
tree->op.long64_value = value;
}else{
tree->op.ulong_value = value.u._32[L];
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
int DoSignedOp64( TREEPTR op1, TREEPTR tree, TREEPTR op2 )
/********************************************************/
{
int64 value;
int64 left;
int64 right;
int tmp;
DATA_TYPE const_type;
if( op1 != NULL ){
left = LongValue64( op1 );
}
right = LongValue64( op2 );
const_type = tree->expr_type->decl_type;
if( tree->op.opr == OPR_CMP ) {
tmp = I64Cmp( &left, &right );
switch( tree->op.cc ) {
case CC_EQ:
tmp = tmp == 0;
break;
case CC_NE:
tmp = tmp != 0;
break;
case CC_GT:
tmp = tmp > 0;
break;
case CC_LE:
tmp = tmp <= 0;
break;
case CC_GE:
tmp = tmp >= 0;
break;
case CC_LT:
tmp = tmp < 0;
break;
}
const_type = TYPE_INT;
tree->op.long_value = (target_int)tmp;
}else{
value = DoOp64( left, tree->op.opr, right, TRUE );
if( const_type == TYPE_LONG64 ){
tree->op.long64_value = value;
}else{
tree->op.long_value = value.u._32[L];
}
}
tree->op.opr = OPR_PUSHINT;
tree->op.const_type = const_type;
tree->left = NULL;
tree->right = NULL;
FreeExprNode( op1 );
FreeExprNode( op2 );
return( 1 );
}
void CastFloatValue( TREEPTR leaf, DATA_TYPE newtype )
{
FLOATVAL *flt;
char *endptr;
long_double ld;
#ifdef _LONG_DOUBLE_
double doubleval;
float floatval;
#endif
if( leaf->op.opr == OPR_PUSHFLOAT ) {
flt = leaf->op.float_value;
if( flt->len == 0 ) { // if contains binary value
ld = flt->ld;
} else {
__Strtold( flt->string, &ld, &endptr );
}
} else { // integer
switch( leaf->op.const_type ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -