📄 cexpr2.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: 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 + -