⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfold2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            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 + -