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

📄 cexpr2.c

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


#include "cvars.h"
#include "cg.h"
#include "cgdefs.h"
#include "cgswitch.h"
#include "pragdefn.h"

struct mathfuncs {
        char    *name;
        unsigned char parm_count;
        unsigned char mathop;
} MathFuncs[] = {                       /* 15-dec-90 */
  #define mathfunc(name,num,op) {name,num,op}
  #include "cmathfun.h"
};

local   TREEPTR GenNextParm(TREEPTR,TYPEPTR **);
local   TREEPTR StartFunc(TREEPTR,TYPEPTR **);
local   TREEPTR GetExpr(void);
local   TREEPTR ExprId(void);
local   TREEPTR ExprOpnd(void);
local   TREEPTR SizeofOp(TYPEPTR);
local   TREEPTR ScalarExpr(TREEPTR);
local   TREEPTR UnaryPlus(TREEPTR);
local   TREEPTR TernOp(TREEPTR,TREEPTR,TREEPTR);
local   TREEPTR ColonOp(TREEPTR);
local   TREEPTR StartTernary(TREEPTR);
local   TREEPTR NotOp(TREEPTR);
local   TREEPTR AndAnd(TREEPTR);
local   TREEPTR OrOr(TREEPTR);
local   TREEPTR GenFuncCall(TREEPTR);
local   TREEPTR IndexOp(TREEPTR,TREEPTR);
local   TREEPTR SegOp(TREEPTR,TREEPTR);
local      void PopNestedParms( TYPEPTR **plistptr );
local      void IncSymWeight( SYMPTR sym );
local      void AddCallNode( TREEPTR tree );

#define PTR_FLAGS  (FLAG_CONST | FLAG_VOLATILE | FLAG_UNALIGNED | FLAG_MEM_MODEL|FLAG_FAR16 | FLAG_BASED )

       call_list  *CallNodeList;
static call_list **LastCallLnk;
static call_list **FirstCallLnk;

void ExprInit()
{
    Level = 0;
    NestedParms = NULL;
    CallNodeList = NULL;
    LastCallLnk = &CallNodeList;
    FirstCallLnk = LastCallLnk;
    InitExprTree();
}

//-----------------------------CNODE-----------------------------------
TREEPTR CallNode( TREEPTR func, TREEPTR parms, TYPEPTR func_result )
{
    TREEPTR     tree;
    TYPEPTR     typ;

    tree = ExprNode( func, OPR_CALL, parms );
    tree->expr_type = func_result;
    tree->op.result_type = func_result;
    typ = func_result;
    while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
    if( typ->decl_type != TYPE_VOID && TypeSize(typ) == 0 ) {
        CErr1( ERR_INCOMPLETE_EXPR_TYPE );
    }
    return( tree );
}

TYPEPTR Far16Type( TYPEPTR typ )
{ // TODO all this stuff should be part of the func defn.
  // not some hack on for later
    TYPEPTR     typ2;

    typ2 = typ;
    while( typ2->decl_type == TYPE_TYPEDEF ) typ2 = typ2->object;
    if( typ2->decl_type == TYPE_ENUM ) typ2 = typ2->object;
    switch( typ2->decl_type ) {
    case TYPE_INT:
        typ = GetType( TYPE_SHORT );
        break;
    case TYPE_UINT:
        typ = GetType( TYPE_USHORT );
        break;
    default:
        break;
    }
    return( typ );
}

TREEPTR FarPtr16Cvt( TREEPTR newparm  )
{
    TYPEPTR         parmtyp;
    pointer_class   op1_class;
    pointer_class   op2_class;

    parmtyp =  newparm->expr_type;
    while( parmtyp->decl_type == TYPE_TYPEDEF ) parmtyp = parmtyp->object;
    if( parmtyp->decl_type == TYPE_POINTER ){
        op1_class = PTR_FAR16;
        op2_class = ExprTypeClass( newparm->expr_type  );
        newparm = ExprNode( NULL, OPR_CONVERT_PTR, newparm );
        newparm->expr_type = parmtyp;
        newparm->op.oldptr_class = op2_class;
        newparm->op.newptr_class = op1_class;
    }
    return( newparm );
}

TREEPTR ParmNode( TREEPTR parmlist, TREEPTR newparm, int far16_func )
{
    TREEPTR     tree;
    TYPEPTR     parmtyp;

    if( far16_func ){
        newparm = FarPtr16Cvt( newparm );
    }
    tree = ExprNode( parmlist, OPR_PARM, newparm );
    if( far16_func ) {
        parmtyp = Far16Type( newparm->expr_type );
    } else {
        parmtyp = newparm->expr_type;
    }
    tree->expr_type = parmtyp;
    tree->op.result_type = parmtyp;
    return( tree );
}

TREEPTR ErrorNode( TREEPTR tree )
{
    FreeExprTree( tree );
    tree =  LeafNode( OPR_ERROR );
    tree->expr_type = GetType( TYPE_INT );
    return( tree );
}

extern op_flags OpFlags( type_modifiers flags )
{
    op_flags      ops;

    ops = 0;
    if( flags & FLAG_CONST )    ops |= OPFLAG_CONST;
    if( flags & FLAG_VOLATILE ) ops |= OPFLAG_VOLATILE;
    if( flags & FLAG_UNALIGNED )ops |= OPFLAG_UNALIGNED;
#if _MACHINE == _PC
    if( flags & FLAG_NEAR )     ops |= OPFLAG_NEARPTR;
    if( flags & FLAG_FAR )      ops |= OPFLAG_FARPTR;
    if( flags & FLAG_HUGE )     ops |= OPFLAG_HUGEPTR;
    if( flags & FLAG_FAR16 )    ops |= OPFLAG_FAR16PTR;
#endif
    return( ops );
}

extern type_modifiers FlagOps( op_flags ops )
{
    type_modifiers      flags;

    flags = FLAG_NONE;
    if( ops & OPFLAG_CONST )    flags |= FLAG_CONST;
    if( ops & OPFLAG_VOLATILE ) flags |= FLAG_VOLATILE;
    if( ops & OPFLAG_UNALIGNED )    flags|= FLAG_UNALIGNED;
#if _MACHINE == _PC
    if( ops & OPFLAG_NEARPTR )     flags |= FLAG_NEAR;
    if( ops & OPFLAG_FARPTR )      flags |= FLAG_FAR;
    if( ops & OPFLAG_HUGEPTR )     flags |= FLAG_HUGE;
    if( Far16Pointer(ops)  )       flags |= FLAG_FAR16;
#endif
    return( flags );
}

TREEPTR ConstLeaf()
{
    TREEPTR     leaf;
    FLOATVAL    *flt;

    leaf = LeafNode( OPR_PUSHINT );     // assume integer value
    leaf->op.const_type = ConstType;
    switch( ConstType ) {
    case TYPE_WCHAR:
        if( sizeof( wchar_t ) == sizeof( unsigned short ) ) {
            leaf->op.const_type = TYPE_USHORT;
        } else {
            leaf->op.const_type = TYPE_CHAR;
        }
        leaf->op.long_value = Constant;
        break;
    case TYPE_CHAR:
        leaf->op.const_type = TYPE_INT;
    case TYPE_INT:
        leaf->op.long_value = Constant;
        break;
    case TYPE_UINT:
        leaf->op.ulong_value = Constant;
        break;
    case TYPE_LONG:
        leaf->op.long_value = Constant;
        break;
    case TYPE_ULONG:
        leaf->op.ulong_value = Constant;
        break;
    case TYPE_LONG64:
        leaf->op.long64_value = Const64;
        break;
    case TYPE_ULONG64:
        leaf->op.ulong64_value = Const64;
        break;
    case TYPE_FLOAT:
    case TYPE_DOUBLE:
    case TYPE_LONG_DOUBLE:
    case TYPE_FIMAGINARY:
    case TYPE_DIMAGINARY:
    case TYPE_LDIMAGINARY:
        flt = CMemAlloc( sizeof(FLOATVAL) + TokenLen );
        flt->string[0] = '+';
        strcpy( &flt->string[1], Buffer );
        flt->len = TokenLen + 1;
        flt->type = ConstType;
        flt->next = NULL;
        leaf->op.float_value = flt;
        leaf->op.opr = OPR_PUSHFLOAT;
        break;
    }
    leaf->expr_type = GetType( leaf->op.const_type );
    return( leaf );
}

TREEPTR IntLeaf( target_int value )
{
    TREEPTR     leaf;

    leaf = LeafNode( OPR_PUSHINT );
    leaf->op.const_type = TYPE_INT;
    leaf->op.long_value = value;
    leaf->expr_type = GetType( TYPE_INT );
    return( leaf );
}

TREEPTR UIntLeaf( target_uint value )
{
    TREEPTR     leaf;

    leaf = LeafNode( OPR_PUSHINT );
    leaf->op.const_type = TYPE_UINT;
    leaf->op.ulong_value = value;
    leaf->expr_type = GetType( TYPE_UINT );
    return( leaf );
}

TREEPTR LongLeaf( target_long value )
{
    TREEPTR     leaf;

    leaf = LeafNode( OPR_PUSHINT );
    leaf->op.const_type = TYPE_LONG;
    leaf->op.long_value = value;
    leaf->expr_type = GetType( TYPE_LONG );
    return( leaf );
}

TREEPTR LongLeaf64( uint64 value, DATA_TYPE decl_type )
{
    TREEPTR     leaf;

    leaf = LeafNode( OPR_PUSHINT );
    leaf->op.const_type = decl_type;
    leaf->op.long64_value = value;
    leaf->expr_type = GetType( decl_type );
    return( leaf );
}

local TREEPTR EnumLeaf( struct enum_info *eip )
{
    DATA_TYPE decl_type;
#if 0
    XREFPTR     xref;

    if( CompFlags.emit_browser_info ) {
        xref = eip->enum_entry->xref;
        xref->next_xref = NewXref( xref->next_xref );
    }
#endif
    decl_type = eip->parent->sym_type->object->decl_type;
    switch( decl_type ) {
    case TYPE_LONG64:
    case TYPE_ULONG64:
    case TYPE_LONG:
    case TYPE_ULONG:
    case TYPE_INT:
    case TYPE_UINT:
        return( LongLeaf64( eip->value , decl_type ) );
    case TYPE_UCHAR:
    case TYPE_USHORT:
        return( UIntLeaf( eip->value.u._32[L] ) );
    default:
        return( IntLeaf( eip->value.u._32[L] ) );
    }
}

TREEPTR VarLeaf( SYMPTR sym, SYM_HANDLE sym_handle )
{
    TREEPTR         leaf;
    TYPEPTR         typ;
    type_modifiers  flags;

    leaf = LeafNode( OPR_PUSHADDR );
    leaf->op.sym_handle = sym_handle;
    typ = sym->sym_type;
    leaf->expr_type = typ;
    flags = sym->attrib & PTR_FLAGS;
    leaf->op.flags = OpFlags( flags );
    return( leaf );
}


TREEPTR SymLeaf()
{
    SYM_HANDLE  sym_handle;
    SYM_HANDLE  sym0_handle;
    int         hash;
    TREEPTR     tree;
    auto SYM_ENTRY sym;
    auto struct enum_info ei;
    extern       SYM_HANDLE SymLook();
    extern       SYM_HANDLE Sym0Look();
    extern       void SymCreate();
    extern       SYM_HANDLE SymAdd(), SymAddL0();

    if( CurToken == T_SAVED_ID ) {
        CurToken = LAToken;
        hash = SavedHash;
        EnumLookup( hash, SavedId, &ei );       /* 12-sep-88 */
        sym_handle = SymLook( hash, SavedId );
        if( sym_handle == 0 ) {
            if( ei.level >= 0 ) {               /* if enum was found */
                return( EnumLeaf( &ei ) );
            }
            SymCreate( &sym, SavedId );
        } else {
            SymGet( &sym, sym_handle );
            if( ei.level > (int)sym.level )  return( EnumLeaf( &ei ) );
            /* 12-dec-88 */
            if( sym.stg_class == SC_EXTERN  &&  sym.level > 0 ) {
                sym0_handle = Sym0Look( hash, SavedId );
                if( sym0_handle != 0 ) {
                    sym_handle = sym0_handle;
                    SymGet( &sym, sym_handle );
                }
            }
            if( sym.stg_class == SC_TYPEDEF ) {
                CErr2p( ERR_CANT_USE_TYPEDEF_AS_VAR, SavedId );
                return( IntLeaf( 0 ) );
            }
        }
    } else {
        hash = HashValue;
        EnumLookup( hash, Buffer, &ei );        /* 12-sep-88 */
        sym_handle = SymLook( hash, Buffer );
        if( sym_handle == 0 ) {
            if( ei.level >= 0 ) {               /* if enum was found */
                NextToken();
                return( EnumLeaf( &ei ) );
            }
            SymCreate( &sym, Buffer );
        } else {
            SymGet( &sym, sym_handle );
            if( ei.level > (int)sym.level ) {
                NextToken();
                return( EnumLeaf( &ei ) );
            }
            /* 12-dec-88 */

⌨️ 快捷键说明

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