mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3174 lines
62 KiB
3174 lines
62 KiB
/*****************************************************************************/
|
|
/** Microsoft LAN Manager **/
|
|
/** Copyright(c) Microsoft Corp., 1987-1990 **/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************
|
|
File : newexpr.cxx
|
|
Title : new expression handler
|
|
Description : handles expressions
|
|
History :
|
|
04-May-1991 Vibhasc Created
|
|
*****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* local defines
|
|
****************************************************************************/
|
|
|
|
|
|
/****************************************************************************
|
|
* include files
|
|
****************************************************************************/
|
|
#include "nulldefs.h"
|
|
extern "C" {
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <malloc.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
}
|
|
|
|
#include "buffer.hxx"
|
|
#include "nodeskl.hxx"
|
|
#include "miscnode.hxx"
|
|
#include "ptrarray.hxx"
|
|
#include "gramutil.hxx"
|
|
#include "newexpr.hxx" /* my provate include file */
|
|
#include "compnode.hxx"
|
|
#include "cmdana.hxx"
|
|
#include "ctxt.hxx"
|
|
#include "tlnmgr.hxx"
|
|
|
|
|
|
/****************************************************************************
|
|
* extern data
|
|
****************************************************************************/
|
|
|
|
extern gstate * pGState;
|
|
extern SymTable * pBaseSymTbl,
|
|
* pCurSymTbl;
|
|
extern short CompileMode;
|
|
extern CMD_ARG * pCommand;
|
|
extern CTXTMGR * pGlobalContext;
|
|
|
|
/****************************************************************************
|
|
* extern procedures
|
|
****************************************************************************/
|
|
extern STATUS_T GetBaseTypeNode( node_skl**, short, short, short );
|
|
extern unsigned short XLateToInternalType( ETYPE Type );
|
|
extern BOOL IsIntegralType( ETYPE );
|
|
extern BOOL IsNumeric( ETYPE );
|
|
extern ETYPE XLateToType( unsigned short );
|
|
extern char * GetOperatorString( OPERATOR );
|
|
extern ETYPE TrueType( ETYPE );
|
|
extern BOOL IsEvaluatable( expr_node * );
|
|
extern SymTable * InScope( node_skl *, char *);
|
|
extern char * MakeNewStringWithProperQuoting( char * );
|
|
extern void MakeHexChar( unsigned short ch,
|
|
char *p1,
|
|
char *p2);
|
|
extern short SizeIncrIfSpecialChar( int );
|
|
extern void TranslateSpecialCharacter( int ch,
|
|
char *,
|
|
char *,
|
|
char *,
|
|
char *);
|
|
extern BOOL IsValidSizeOfType( node_skl * );
|
|
|
|
|
|
/****************************************************************************
|
|
* local data
|
|
****************************************************************************/
|
|
/**
|
|
** numeric compatibility table
|
|
**/
|
|
unsigned char ArithCompatMatrix[][ I_ETYPE_MAX ] = {
|
|
/*******************************************************************************
|
|
UCH, CHA, USM, SMA, BYT, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, BOO
|
|
******************************************************************************/
|
|
//UCH,
|
|
{UCH, UCH, USM, SMA, UCH, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, UCH}
|
|
//CHA,
|
|
,{UCH, CHA, USM, SMA, CHA, USH, SHO, INT, INT, LON, LON, HYP, HYP, FLO, DOU, UCH
|
|
}
|
|
//USM,
|
|
,{USM, USM, USM, USM, USM, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, USM
|
|
}
|
|
//SMA,
|
|
,{SMA, SMA, USM, SMA, SMA, USH, SHO, INT, INT, LON, LON, HYP, HYP, FLO, DOU, SMA
|
|
}
|
|
//BYT,
|
|
,{UCH, CHA, USM, SMA, BYT, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, BYT
|
|
}
|
|
//USH,
|
|
,{USH, USH, USH, USH, USH, USH, USH, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, SHO}
|
|
//SHO,
|
|
,{SHO, SHO, SHO, SHO, SHO, SHO, SHO, INT, INT, LON, LON, HYP, HYP, FLO, DOU, SHO}
|
|
/*******************************************************************************
|
|
UCH, CHA, USM, SMA, BYT, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, BOO
|
|
******************************************************************************/
|
|
//UIN,
|
|
,{UIN, UIN, UIN, UIN, UIN, UIN, UIN, UIN, UIN, ULO, LON, UHY, HYP, FLO, DOU, UIN}
|
|
//INT,
|
|
,{INT, INT, INT, INT, INT, INT, INT, UIN, INT, LON, LON, HYP, HYP, FLO, DOU, INT}
|
|
//ULO,
|
|
,{ULO, ULO, ULO, ULO, ULO, ULO, ULO, ULO, ULO, ULO, ULO, UHY, HYP, FLO, DOU, ULO}
|
|
//LON,
|
|
,{LON, LON, LON, LON, LON, LON, LON, LON, LON, ULO, LON, HYP, HYP, FLO, DOU, LON}
|
|
//UHY,
|
|
,{UHY, UHY, UHY, UHY, UHY, UHY, UHY, UHY, UHY, UHY, UHY, UHY, UHY, FLO, DOU, UHY}
|
|
//HYP,
|
|
,{HYP, HYP, HYP, HYP, HYP, HYP, HYP, HYP, HYP, HYP, HYP, UHY, HYP, FLO, DOU, HYP}
|
|
//FLO,
|
|
,{FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, DOU, FLO}
|
|
//DOU,
|
|
,{DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU, DOU}
|
|
/*******************************************************************************
|
|
UCH, CHA, USM, SMA, BYT, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, BOO
|
|
******************************************************************************/
|
|
//BOO
|
|
,{UCH, CHA, USM, SMA, BOO, USH, SHO, UIN, INT, ULO, LON, UHY, HYP, FLO, DOU, BOO}
|
|
|
|
};
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
expr_node
|
|
****************************************************************************/
|
|
|
|
expr_node::expr_node()
|
|
{
|
|
fConstant =
|
|
fEvaluated = 0;
|
|
fNeedsResolve = 1;
|
|
fSemanticsDone = 0;
|
|
fTooComplex = 0;
|
|
fLocalScope = 0;
|
|
Type = pErrorTypeNode;
|
|
}
|
|
|
|
expr_node::expr_node( unsigned short Op )
|
|
{
|
|
fConstant =
|
|
fEvaluated = 0;
|
|
fSemanticsDone = 0;
|
|
fTooComplex = 0;
|
|
fNeedsResolve = 1;
|
|
fLocalScope = 0;
|
|
Operator = Op;
|
|
Type = pErrorTypeNode;
|
|
}
|
|
|
|
ETYPE
|
|
expr_node::SetType(
|
|
ETYPE pType)
|
|
{
|
|
return (Type = TrueType( pType ));
|
|
}
|
|
ETYPE
|
|
expr_node::SetTypeAsIs(
|
|
ETYPE pType )
|
|
{
|
|
if( pType->NodeKind() == NODE_DEF )
|
|
Type = pType;
|
|
else
|
|
SetType( pType );
|
|
return Type;
|
|
}
|
|
expr_node *
|
|
expr_node::Clone()
|
|
{
|
|
return this; /** TEMPORARY **/
|
|
}
|
|
node_state
|
|
expr_node::Resolve( class SymTable * p)
|
|
{
|
|
UNUSED(p);
|
|
return NODE_STATE_OK;
|
|
}
|
|
|
|
node_state
|
|
expr_node::SCheck( class SymTable * p)
|
|
{
|
|
UNUSED(p);
|
|
SemanticsDone();
|
|
return NODE_STATE_OK;
|
|
};
|
|
|
|
|
|
/****************************************************************************
|
|
expr_op
|
|
****************************************************************************/
|
|
|
|
expr_op::expr_op(
|
|
unsigned short Op ) : expr_node( Op )
|
|
{
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
expr_op_unary
|
|
****************************************************************************/
|
|
expr_op_unary::expr_op_unary(
|
|
unsigned short Op,
|
|
expr_node *pL) : expr_op( Op )
|
|
{
|
|
pLeft = pL;
|
|
|
|
switch(Op )
|
|
{
|
|
case OP_UNARY_INDIRECTION:
|
|
// case OP_UNARY_CAST:
|
|
case OP_UNARY_AND:
|
|
TooComplex();
|
|
}
|
|
if( pLeft && pLeft->IsConstant() )
|
|
{
|
|
SCheck( pBaseSymTbl );
|
|
if( (Op != OP_UNARY_INDIRECTION) && (Op != OP_UNARY_AND) )
|
|
Constant();
|
|
}
|
|
}
|
|
|
|
node_state
|
|
expr_op_unary::SCheck(
|
|
SymTable * pSymTbl)
|
|
{
|
|
node_state NState = NODE_STATE_OK;
|
|
ETYPE ResultType;
|
|
STATUS_T uError = STATUS_OK;
|
|
|
|
if(! IsSemanticsDone())
|
|
{
|
|
if( (NState = Resolve( pSymTbl ) ) == NODE_STATE_OK )
|
|
{
|
|
pLeft->SCheck( pSymTbl );
|
|
|
|
ResultType = pLeft->GetType();
|
|
|
|
if( ResultType != pErrorTypeNode )
|
|
{
|
|
|
|
switch( (short)GetOperator() )
|
|
{
|
|
case OP_UNARY_INDIRECTION:
|
|
|
|
if( ResultType->NodeKind() == NODE_POINTER )
|
|
ResultType = ResultType->GetBasicType();
|
|
else
|
|
{
|
|
uError = EXPR_DEREF_ON_NON_POINTER;
|
|
ResultType = pErrorTypeNode;
|
|
}
|
|
break;
|
|
|
|
case OP_UNARY_CAST:
|
|
ResultType = GetType();
|
|
break;
|
|
|
|
case OP_UNARY_PLUS:
|
|
case OP_UNARY_MINUS:
|
|
|
|
// the type is what is returned from the left subtree
|
|
break;
|
|
|
|
case OP_UNARY_AND:
|
|
|
|
{
|
|
ETYPE pP = (ETYPE) new node_pointer();
|
|
pP->SetBasicType( ResultType );
|
|
ResultType = pP;
|
|
}
|
|
break;
|
|
|
|
case OP_UNARY_COMPLEMENT:
|
|
case OP_UNARY_NOT:
|
|
|
|
if( !IsIntegralType( ResultType ) )
|
|
{
|
|
uError = EXPR_INCOMPATIBLE_TYPES;
|
|
ResultType = pErrorTypeNode;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return NODE_STATE_OK;
|
|
}
|
|
|
|
if( uError != STATUS_OK )
|
|
{
|
|
ParseError(uError, (char *)NULL );
|
|
}
|
|
}
|
|
SetType( ResultType );
|
|
SemanticsDone();
|
|
}
|
|
}
|
|
return NState;
|
|
}
|
|
|
|
node_state
|
|
expr_op_unary::Resolve(
|
|
SymTable * pSymTbl)
|
|
{
|
|
node_state NState = NODE_STATE_OK;
|
|
|
|
if(!IsResolved() )
|
|
{
|
|
if( pLeft && (pLeft->Resolve( pSymTbl ) == NODE_STATE_OK ) )
|
|
Resolved();
|
|
else
|
|
NState = NODE_STATE_RESOLVE;
|
|
}
|
|
return NState;
|
|
}
|
|
|
|
void
|
|
expr_op_unary::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
OPERATOR Op = GetOperator();
|
|
char * pSuffixString = (char *)NULL;
|
|
char * pPrefixString = (char *)NULL;
|
|
char * pMainString = (char *)NULL;
|
|
|
|
switch( Op )
|
|
{
|
|
case OP_UNARY_AND:
|
|
|
|
pPrefixString = "(";
|
|
pSuffixString = ")";
|
|
pMainString = GetOperatorString( Op );
|
|
break;
|
|
|
|
case OP_UNARY_INDIRECTION:
|
|
|
|
pPrefixString = "(*(";
|
|
pSuffixString = "))";
|
|
break;
|
|
|
|
default:
|
|
|
|
pMainString = GetOperatorString( GetOperator() );
|
|
break;
|
|
}
|
|
|
|
|
|
if( pPrefixString )
|
|
pOutput->ConcatTail( pPrefixString );
|
|
|
|
if( pMainString )
|
|
pOutput->ConcatTail( pMainString );
|
|
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
|
|
if( pSuffixString )
|
|
pOutput->ConcatTail( pSuffixString );
|
|
}
|
|
|
|
long
|
|
expr_op_unary::Evaluate()
|
|
{
|
|
long Result = 0L;
|
|
|
|
if( IsEvaluatable( this ) && pLeft )
|
|
{
|
|
Result = pLeft->Evaluate();
|
|
Evaluated();
|
|
|
|
switch( GetOperator() )
|
|
{
|
|
case OP_UNARY_PLUS:
|
|
|
|
return Result;
|
|
|
|
case OP_UNARY_MINUS:
|
|
|
|
return -Result;
|
|
|
|
case OP_UNARY_NOT:
|
|
|
|
return !Result;
|
|
|
|
case OP_UNARY_COMPLEMENT:
|
|
|
|
return ~Result;
|
|
|
|
case OP_UNARY_CAST:
|
|
|
|
return Result;
|
|
|
|
default:
|
|
|
|
return 0L;
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
BOOL
|
|
expr_op_unary::ExprHasOutOnlyParam()
|
|
{
|
|
|
|
if(pLeft && pLeft->ExprHasOutOnlyParam())
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
expr_op_binary
|
|
****************************************************************************/
|
|
expr_op_binary::expr_op_binary(
|
|
unsigned short Op,
|
|
expr_node * pL,
|
|
expr_node * pR ) : expr_op( Op )
|
|
{
|
|
pLeft = pL;
|
|
pRight = pR;
|
|
|
|
switch( Op )
|
|
{
|
|
// case OP_QM:
|
|
// case OP_COLON:
|
|
case OP_FUNCTION:
|
|
case OP_PARAM:
|
|
case OP_POINTSTO:
|
|
case OP_DOT:
|
|
case OP_INDEX:
|
|
TooComplex();
|
|
}
|
|
|
|
if( pL && pR )
|
|
{
|
|
if( pL->IsConstant() && pR->IsConstant() )
|
|
{
|
|
SCheck( pBaseSymTbl );
|
|
Constant();
|
|
}
|
|
}
|
|
}
|
|
|
|
ETYPE
|
|
expr_op_binary::IsCompatible(
|
|
ETYPE pLeftType,
|
|
ETYPE pRightType )
|
|
{
|
|
ETYPE ResultType;
|
|
unsigned short iRightType,
|
|
iLeftType;
|
|
STATUS_T uError = STATUS_OK;
|
|
OPERATOR Op = GetOperator();
|
|
|
|
switch( Op )
|
|
{
|
|
case OP_PLUS:
|
|
case OP_MINUS:
|
|
case OP_STAR:
|
|
case OP_SLASH:
|
|
case OP_MOD:
|
|
case OP_LEFT_SHIFT:
|
|
case OP_RIGHT_SHIFT:
|
|
|
|
iLeftType = XLateToInternalType( pLeftType );
|
|
iRightType = XLateToInternalType( pRightType );
|
|
|
|
if( ( iLeftType == I_ETYPE_ERROR ) ||
|
|
( iRightType == I_ETYPE_ERROR ) ||
|
|
( (iLeftType = ArithCompatMatrix[ iLeftType ][ iRightType ])==
|
|
I_ETYPE_ERROR) )
|
|
{
|
|
uError = EXPR_INCOMPATIBLE_TYPES;
|
|
break;
|
|
}
|
|
|
|
if( pLeft->IsConstant() && !pRight->IsConstant() )
|
|
{
|
|
iLeftType = iRightType;
|
|
}
|
|
else if( !pLeft->IsConstant() && pRight->IsConstant() )
|
|
{
|
|
iLeftType = XLateToInternalType( pLeftType );
|
|
}
|
|
|
|
ResultType = XLateToType( iLeftType );
|
|
break;
|
|
|
|
case OP_QM:
|
|
|
|
if( !IsIntegralType( pLeftType ) )
|
|
uError = EXPR_INCOMPATIBLE_TYPES;
|
|
else
|
|
ResultType = pRightType;
|
|
break;
|
|
|
|
case OP_COLON:
|
|
|
|
ResultType = pLeftType;
|
|
break;
|
|
|
|
case OP_EQUAL:
|
|
case OP_NOT_EQUAL:
|
|
case OP_LESS:
|
|
case OP_LESS_EQUAL:
|
|
case OP_GREATER_EQUAL:
|
|
case OP_GREATER:
|
|
|
|
#if 0 //////////////////////////////////////////////////////////////////////
|
|
GetBaseTypeNode( &ResultType,
|
|
SIGN_SIGNED,
|
|
SIZE_UNDEF,
|
|
TYPE_INT );
|
|
break;
|
|
#endif // 0 ///////////////////////////////////////////////////////////////
|
|
|
|
// fall thru
|
|
|
|
case OP_OR:
|
|
case OP_AND:
|
|
case OP_XOR:
|
|
case OP_LOGICAL_OR:
|
|
case OP_LOGICAL_AND:
|
|
|
|
if( IsIntegralType( pLeftType ) && IsIntegralType( pRightType ) )
|
|
{
|
|
|
|
iLeftType = XLateToInternalType( pLeftType );
|
|
iRightType = XLateToInternalType( pRightType );
|
|
|
|
#if 0
|
|
if( (Op != OP_LOGICAL_AND) && (Op != OP_LOGICAL_OR ) )
|
|
{
|
|
#endif // 0
|
|
if( ( iLeftType == I_ETYPE_ERROR ) ||
|
|
( iRightType == I_ETYPE_ERROR ) ||
|
|
( (iLeftType = ArithCompatMatrix[ iLeftType ][ iRightType ]) == I_ETYPE_ERROR) )
|
|
{
|
|
uError = EXPR_INCOMPATIBLE_TYPES;
|
|
break;
|
|
}
|
|
else
|
|
ResultType = XLateToType( iLeftType );
|
|
#if 0
|
|
}
|
|
else
|
|
GetBaseTypeNode( &ResultType,
|
|
SIGN_SIGNED,
|
|
SIZE_UNDEF,
|
|
TYPE_INT );
|
|
#endif // 0
|
|
}
|
|
else
|
|
uError = EXPR_INCOMPATIBLE_TYPES;
|
|
|
|
break;
|
|
|
|
case OP_POINTSTO:
|
|
|
|
if( pLeftType->NodeKind() != NODE_POINTER )
|
|
{
|
|
uError = EXPR_DEREF_ON_NON_POINTER;
|
|
break;
|
|
}
|
|
else
|
|
pLeftType = pLeftType->GetBasicType();
|
|
|
|
// fall thru
|
|
|
|
case OP_DOT:
|
|
|
|
if( (pLeftType->NodeKind() != NODE_STRUCT ) &&
|
|
(pLeftType->NodeKind() != NODE_UNION ) &&
|
|
(pLeftType->NodeKind() != NODE_ENUM ) )
|
|
{
|
|
uError = EXPR_LHS_NON_COMPOSITE;
|
|
}
|
|
else
|
|
ResultType = pRightType;
|
|
break;
|
|
|
|
case OP_INDEX:
|
|
|
|
if( (pLeftType->NodeKind() != NODE_ARRAY) &&
|
|
(pLeftType->NodeKind() != NODE_POINTER) )
|
|
{
|
|
uError = EXPR_INDEXING_NON_ARRAY;
|
|
}
|
|
else
|
|
ResultType = pLeftType->GetBasicType();
|
|
break;
|
|
|
|
default:
|
|
uError = EXPR_NOT_IMPLEMENTED;
|
|
ResultType = pErrorTypeNode;
|
|
}
|
|
|
|
if( uError != STATUS_OK )
|
|
{
|
|
ParseError( uError, (char *)NULL );
|
|
ResultType = pErrorTypeNode;
|
|
}
|
|
|
|
return ResultType;
|
|
}
|
|
|
|
node_state
|
|
expr_op_binary::SCheck(
|
|
SymTable * pSymTbl )
|
|
{
|
|
ETYPE pLeftType,
|
|
pRightType,
|
|
pResultType = GetType();
|
|
node_state NState = NODE_STATE_OK;
|
|
OPERATOR Op = GetOperator();
|
|
|
|
|
|
if( !IsSemanticsDone() )
|
|
{
|
|
if( (NState = Resolve( pSymTbl )) == NODE_STATE_OK )
|
|
{
|
|
if( pLeft && pRight )
|
|
{
|
|
pLeft->SCheck( pSymTbl );
|
|
|
|
// if the operator is a "." or a "->", then the right is
|
|
// only an id, and the resolve has resolved it already.
|
|
|
|
if( (Op != OP_DOT) && (Op != OP_POINTSTO) )
|
|
pRight->SCheck( pSymTbl );
|
|
else
|
|
{
|
|
if( pLeft->IsLocalScope() )
|
|
SetLocalScope();
|
|
}
|
|
|
|
pLeftType = pLeft->GetType();
|
|
pRightType = pRight->GetType();
|
|
|
|
pResultType = IsCompatible( pLeftType, pRightType );
|
|
SemanticsDone();
|
|
}
|
|
}
|
|
}
|
|
SetType( pResultType );
|
|
return NState;
|
|
}
|
|
|
|
node_state
|
|
expr_op_binary::Resolve(
|
|
SymTable * pSymTbl)
|
|
{
|
|
node_state NState = NODE_STATE_RESOLVE;
|
|
OPERATOR Op = GetOperator();
|
|
|
|
if( !IsResolved() )
|
|
{
|
|
switch( Op )
|
|
{
|
|
case OP_POINTSTO:
|
|
case OP_DOT:
|
|
|
|
if( pLeft && (pLeft->Resolve( pSymTbl ) == NODE_STATE_OK) )
|
|
{
|
|
node_skl * pNode = (Op == OP_POINTSTO) ?
|
|
pLeft->GetType()->GetBasicType() :
|
|
pLeft->GetType();
|
|
|
|
if( pSymTbl = InScope( pNode, pRight->GetName() ) )
|
|
{
|
|
if( (NState = pRight->Resolve( pSymTbl ) )
|
|
== NODE_STATE_OK)
|
|
Resolved();
|
|
NState = NODE_STATE_OK;
|
|
}
|
|
else
|
|
{
|
|
ParseError( UNDEFINED_SYMBOL, pRight->GetName() );
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
if( pLeft && (pLeft->Resolve( pSymTbl ) == NODE_STATE_OK) &&
|
|
pRight && (pRight->Resolve( pSymTbl ) == NODE_STATE_OK ) )
|
|
{
|
|
Resolved();
|
|
NState = NODE_STATE_OK;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
NState = NODE_STATE_OK;
|
|
return NState;
|
|
}
|
|
|
|
void
|
|
expr_op_binary::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
switch( GetOperator() )
|
|
{
|
|
case OP_INDEX:
|
|
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( "[" );
|
|
pRight->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( "]" );
|
|
break;
|
|
|
|
case OP_DOT:
|
|
case OP_POINTSTO:
|
|
|
|
if( IsLocalScope() && pPrefix )
|
|
{
|
|
pPrefix->Merge( pOutput );
|
|
pOutput = pPrefix;
|
|
pPrefix = (BufferManager *)NULL;
|
|
}
|
|
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( GetOperatorString( GetOperator() ) );
|
|
pRight->PrintExpr( (BufferManager *)NULL, (BufferManager *)NULL, pOutput);
|
|
break;
|
|
|
|
case OP_COLON:
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( GetOperatorString( GetOperator() ) );
|
|
pRight->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
break;
|
|
|
|
default:
|
|
|
|
pOutput->ConcatTail( "(" );
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( GetOperatorString( GetOperator() ) );
|
|
pRight->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( ")" );
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
long
|
|
expr_op_binary::Evaluate()
|
|
{
|
|
|
|
long LeftResult,
|
|
RightResult;
|
|
OPERATOR Oper = GetOperator();
|
|
|
|
if( IsEvaluatable( this ) && pLeft && pRight )
|
|
{
|
|
if( Oper == OP_QM )
|
|
{
|
|
if( pLeft->Evaluate() != 0L )
|
|
{
|
|
LeftResult = ((expr_op_binary *)pRight)->GetLeft()->Evaluate();
|
|
}
|
|
else
|
|
{
|
|
LeftResult = ((expr_op_binary *)pRight)->GetRight()->Evaluate();
|
|
}
|
|
return LeftResult;
|
|
}
|
|
|
|
LeftResult = pLeft->Evaluate();
|
|
RightResult = pRight->Evaluate();
|
|
|
|
switch( Oper )
|
|
{
|
|
case OP_PLUS:
|
|
|
|
LeftResult += RightResult;
|
|
break;
|
|
|
|
case OP_MINUS:
|
|
|
|
LeftResult -= RightResult;
|
|
break;
|
|
|
|
case OP_STAR:
|
|
|
|
LeftResult *= RightResult;
|
|
break;
|
|
|
|
case OP_SLASH:
|
|
case OP_MOD:
|
|
|
|
// LeftResult = 0; // Huh ?
|
|
if( RightResult == 0 )
|
|
ParseError( EXPR_DIV_BY_ZERO, (char *)0 );
|
|
else
|
|
{
|
|
if( Oper == OP_SLASH )
|
|
LeftResult /= RightResult;
|
|
else
|
|
LeftResult %= RightResult;
|
|
}
|
|
break;
|
|
|
|
case OP_LEFT_SHIFT:
|
|
|
|
LeftResult <<= RightResult;
|
|
break;
|
|
|
|
case OP_RIGHT_SHIFT:
|
|
|
|
LeftResult >>= RightResult;
|
|
break;
|
|
|
|
case OP_LESS:
|
|
|
|
LeftResult = LeftResult < RightResult;
|
|
break;
|
|
|
|
case OP_LESS_EQUAL:
|
|
|
|
LeftResult = LeftResult <= RightResult;
|
|
break;
|
|
|
|
case OP_GREATER_EQUAL:
|
|
|
|
LeftResult = LeftResult >= RightResult;
|
|
break;
|
|
|
|
case OP_GREATER:
|
|
|
|
LeftResult = LeftResult > RightResult;
|
|
break;
|
|
|
|
case OP_EQUAL:
|
|
|
|
LeftResult = LeftResult == RightResult;
|
|
break;
|
|
|
|
case OP_NOT_EQUAL:
|
|
|
|
LeftResult = LeftResult != RightResult;
|
|
break;
|
|
|
|
case OP_AND:
|
|
|
|
LeftResult &= RightResult;
|
|
break;
|
|
|
|
case OP_OR:
|
|
|
|
LeftResult |= RightResult;
|
|
break;
|
|
|
|
case OP_XOR:
|
|
|
|
LeftResult ^= RightResult;
|
|
break;
|
|
|
|
case OP_LOGICAL_AND:
|
|
|
|
LeftResult = LeftResult && RightResult;
|
|
break;
|
|
|
|
case OP_LOGICAL_OR:
|
|
|
|
LeftResult = LeftResult || RightResult;
|
|
break;
|
|
|
|
default:
|
|
return 0L;
|
|
|
|
}
|
|
}
|
|
return LeftResult;
|
|
}
|
|
|
|
BOOL
|
|
expr_op_binary::ExprHasOutOnlyParam()
|
|
{
|
|
|
|
if(pLeft && pLeft->ExprHasOutOnlyParam())
|
|
return TRUE;
|
|
if(pRight && pRight->ExprHasOutOnlyParam())
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
expr_cast
|
|
****************************************************************************/
|
|
expr_cast::expr_cast(
|
|
ETYPE T,
|
|
expr_node *pE ) : expr_op_unary( OP_UNARY_CAST, pE )
|
|
{
|
|
|
|
/**
|
|
** if the type was a typedefed name, we want it to be kept as is
|
|
** so we can print it just as specified
|
|
**/
|
|
|
|
SetTypeAsIs( T );
|
|
|
|
}
|
|
|
|
node_state
|
|
expr_cast::SCheck(
|
|
SymTable * pSymTbl)
|
|
{
|
|
node_state NState = NODE_STATE_OK;
|
|
STATUS_T uError = STATUS_OK;
|
|
|
|
if(! IsSemanticsDone())
|
|
{
|
|
if( (NState = Resolve( pSymTbl ) ) == NODE_STATE_OK )
|
|
SemanticsDone();
|
|
else
|
|
NState = NODE_STATE_RESOLVE;
|
|
}
|
|
return NState;
|
|
}
|
|
void
|
|
expr_cast::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
expr_node * pL;
|
|
|
|
pOutput->ConcatTail( "(" );
|
|
Type->PrintSizeofString( pOutput );
|
|
pOutput->ConcatTail( " )" );
|
|
|
|
if( pL = GetLeft() )
|
|
{
|
|
pOutput->ConcatTail( "(" );
|
|
pL->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( ")" );
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
expr_sizeof
|
|
****************************************************************************/
|
|
expr_sizeof::expr_sizeof(
|
|
ETYPE pType ) : expr_op_unary( OP_UNARY_SIZEOF, (expr_node *)NULL )
|
|
{
|
|
|
|
// the type of the size entity
|
|
|
|
pSizeofType = pType ? pType : pErrorTypeNode;
|
|
|
|
// the actual type of the sizeof( type ) expression is int
|
|
|
|
GetBaseTypeNode( &Type,
|
|
SIGN_SIGNED,
|
|
SIZE_UNDEF,
|
|
TYPE_INT );
|
|
|
|
Constant();
|
|
Resolve( pBaseSymTbl );
|
|
// SemanticsDone();
|
|
}
|
|
expr_sizeof::expr_sizeof(
|
|
expr_node * pE ) : expr_op_unary( OP_UNARY_SIZEOF, pE )
|
|
{
|
|
|
|
expr_node * pL = GetLeft();
|
|
|
|
// since the sizeof was on an expression, it will always be accessed via
|
|
// the expression and not the pSizeofType
|
|
|
|
pSizeofType = pErrorTypeNode;
|
|
|
|
// the actual type of the sizeof( type ) expression is int
|
|
|
|
GetBaseTypeNode( &Type,
|
|
SIGN_SIGNED,
|
|
SIZE_UNDEF,
|
|
TYPE_INT );
|
|
|
|
// and the sizeof expression is always a constant
|
|
|
|
Constant();
|
|
|
|
}
|
|
long
|
|
expr_sizeof::Evaluate()
|
|
{
|
|
expr_node * pL = GetLeft();
|
|
node_skl * pT;
|
|
|
|
SCheck( pBaseSymTbl );
|
|
|
|
if( pL )
|
|
pT = pL->GetType();
|
|
else
|
|
pT = pSizeofType;
|
|
|
|
return (long)pT->GetSize(0);
|
|
|
|
}
|
|
|
|
void
|
|
expr_sizeof::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
expr_node * pL;
|
|
|
|
pOutput->ConcatTail( GetOperatorString( OP_UNARY_SIZEOF ) );
|
|
pOutput->ConcatTail( "( " );
|
|
|
|
if( pL = GetLeft() )
|
|
pL->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
else
|
|
pSizeofType->PrintSizeofString( pOutput );
|
|
|
|
pOutput->ConcatTail( " )" );
|
|
}
|
|
|
|
node_state
|
|
expr_sizeof::Resolve(
|
|
SymTable * pSymTbl )
|
|
{
|
|
|
|
expr_node * pL = GetLeft();
|
|
node_state NState = NODE_STATE_RESOLVE;
|
|
|
|
// either the sizeof is on an expression which should be resolved by now
|
|
// or
|
|
// sizeof is on a type which is not an error and not a forward decl.
|
|
|
|
if( (pL &&
|
|
(pL->Resolve( pSymTbl ) & NODE_STATE_OK ) )
|
|
||
|
|
((pSizeofType != pErrorTypeNode ) &&
|
|
(pSizeofType->NodeKind() != NODE_FORWARD ) ) )
|
|
{
|
|
Resolved();
|
|
NState = NODE_STATE_OK;
|
|
}
|
|
|
|
return NState;
|
|
|
|
}
|
|
/**************************************************************************
|
|
* expr_variable
|
|
**************************************************************************/
|
|
expr_variable::expr_variable(
|
|
char * pN )
|
|
{
|
|
node_skl * pNode;
|
|
|
|
fInitList = 0;
|
|
pName = pN;
|
|
pExpr = pTerminator;
|
|
SetType( pErrorTypeNode );
|
|
|
|
|
|
SymKey SKey(pName, NAME_LABEL);
|
|
|
|
// maybe an enum label
|
|
|
|
if( pNode = pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
pExpr = new expr_constant( (long)(((node_label *)pNode)->GetValue()) );
|
|
fInitList = 1;
|
|
Constant();
|
|
Resolved();
|
|
SetType( GetExpr()->GetType() );
|
|
}
|
|
else
|
|
{
|
|
SKey.SetKind( NAME_ID );
|
|
if( pNode = pBaseSymTbl->SymSearch( SKey ) )
|
|
{
|
|
expr_node * pInList = ((node_id *)pNode)->GetInitList();
|
|
|
|
if( pInList &&
|
|
pInList->IsInitList() &&
|
|
!pInList->IsExprTerminator()
|
|
)
|
|
{
|
|
pExpr = pInList;
|
|
fInitList = 1;
|
|
Constant();
|
|
Resolved();
|
|
}
|
|
SetType( pNode->GetBasicType() );
|
|
}
|
|
}
|
|
SetOutOnly( FALSE );
|
|
|
|
}
|
|
|
|
expr_variable::expr_variable(
|
|
char * pN ,
|
|
ETYPE pType )
|
|
{
|
|
|
|
fInitList = 0;
|
|
pName = pN;
|
|
pExpr = pTerminator;
|
|
SetType( pType );
|
|
|
|
|
|
if( pType->NodeKind() == NODE_ID )
|
|
{
|
|
expr_node * pInList = ((node_id *)pType)->GetInitList();
|
|
|
|
if( pInList && pInList->IsInitList() )
|
|
{
|
|
pExpr = pInList;
|
|
fInitList = 1;
|
|
Constant();
|
|
Resolved();
|
|
}
|
|
}
|
|
}
|
|
|
|
expr_node *
|
|
expr_variable::ChildNthExpr(
|
|
short n )
|
|
{
|
|
return pExpr->ChildNthExpr( n );
|
|
}
|
|
expr_node *
|
|
expr_variable::SiblingNthExpr(
|
|
short n )
|
|
{
|
|
return pExpr->SiblingNthExpr( n );
|
|
}
|
|
|
|
node_state
|
|
expr_variable::Resolve(
|
|
SymTable * pSymTbl)
|
|
{
|
|
ETYPE pT = GetType();
|
|
node_state NState = NODE_STATE_OK;
|
|
|
|
if( !IsResolved() )
|
|
{
|
|
if( pSymTbl )
|
|
{
|
|
SymKey SKey( pName, NAME_MEMBER );
|
|
|
|
if( !(pT = pSymTbl->SymSearch( SKey )) )
|
|
{
|
|
|
|
//
|
|
// if the symbol is not found in the current scope, check from the
|
|
// last symbol context if the name was in the last structs top
|
|
// level names.
|
|
//
|
|
|
|
node_skl * pNode;
|
|
if( pNode = pGlobalContext->GetLastContext( C_COMP ) )
|
|
{
|
|
pSymTbl = ((su *)pNode)->GetSymScopeOfTopLevelName( pName );
|
|
if( pSymTbl )
|
|
if( pT = pSymTbl->SymSearch( SKey ) )
|
|
SetLocalScope();
|
|
}
|
|
else
|
|
{
|
|
SKey.SetKind( NAME_ID );
|
|
pT = pBaseSymTbl->SymSearch( SKey );
|
|
}
|
|
|
|
if( !pT )
|
|
{
|
|
ParseError( UNDEFINED_SYMBOL, pName );
|
|
pT = pErrorTypeNode;
|
|
NState = NODE_STATE_RESOLVE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLocalScope();
|
|
NODE_T NT = pT->NodeKind();
|
|
if( (NT == NODE_PARAM) || (NT == NODE_FIELD) )
|
|
{
|
|
if( NT == NODE_PARAM )
|
|
{
|
|
if( pT->FInSummary( ATTR_OUT ) &&
|
|
!pT->FInSummary( ATTR_IN ) )
|
|
{
|
|
SetOutOnly( TRUE );
|
|
}
|
|
}
|
|
|
|
//
|
|
// if the field or param is a pointer then mark them wiht
|
|
// a used in expression, so that the backend deallocates them
|
|
// last
|
|
//
|
|
if( pT->GetBasicType()->NodeKind() == NODE_POINTER )
|
|
{
|
|
pT->SetUsedInAnExpression();
|
|
}
|
|
}
|
|
|
|
}
|
|
SetType( pT );
|
|
}
|
|
else
|
|
{
|
|
ParseError( UNDEFINED_SYMBOL, pName );
|
|
pT = pErrorTypeNode;
|
|
NState = NODE_STATE_RESOLVE;
|
|
}
|
|
}
|
|
|
|
if( pT != pErrorTypeNode )
|
|
{
|
|
Resolved();
|
|
}
|
|
return NState;
|
|
}
|
|
|
|
node_state
|
|
expr_variable::SCheck(
|
|
SymTable * pSymTbl)
|
|
{
|
|
node_state NState;
|
|
|
|
if( ( NState = Resolve( pSymTbl ) ) == NODE_STATE_OK )
|
|
SemanticsDone();
|
|
return NState;
|
|
}
|
|
|
|
void
|
|
expr_variable::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
|
|
#if 0
|
|
fprintf(stderr, "Prefix ++++++++++++++++\n");
|
|
pPrefix->Print( stderr );
|
|
fprintf(stderr, "\n-----------------------\n");
|
|
|
|
fprintf(stderr, "Suffix ++++++++++++++++\n");
|
|
pSuffix->Print( stderr );
|
|
fprintf(stderr, "\n-----------------------\n");
|
|
fprintf(stderr, "Output ++++++++++++++++\n");
|
|
pOutput->Print( stderr );
|
|
fprintf(stderr, "\n-----------------------\n");
|
|
#endif // 1
|
|
|
|
//
|
|
// profuse apologies for this last minute hack. If the expression
|
|
// has a transmit_as as the variable, then dont add the variable name
|
|
// or the generated stubs will be garbage. This is too diffcult to fix
|
|
// in the back end so I am hacking here. This situtation comes in when
|
|
// the transmitted type is a string.
|
|
//
|
|
|
|
BOOL fNoName = FALSE;
|
|
if( pPrefix )
|
|
{
|
|
char *pTemp;
|
|
pPrefix->RemoveTail( &pTemp );
|
|
if( pTemp )
|
|
{
|
|
pPrefix->ConcatTail( pTemp );
|
|
if( strcmp( pTemp, "_xmit_type") == 0 )
|
|
{
|
|
pPrefix->RemoveHead( &pTemp);// extra param permanently removed.
|
|
fNoName = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( IsLocalScope() && pPrefix )
|
|
pPrefix->Clone( pOutput );
|
|
|
|
if( fNoName == FALSE )
|
|
pOutput->ConcatTail( pName );
|
|
|
|
if( pSuffix )
|
|
pSuffix->Clone( pOutput );
|
|
};
|
|
BOOL
|
|
expr_variable::ExprHasOutOnlyParam()
|
|
{
|
|
return GetOutOnly();
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* expr_constant
|
|
****************************************************************************/
|
|
expr_constant::expr_constant( char *pS )
|
|
{
|
|
node_skl *pN;
|
|
|
|
Value.sValue = pS;
|
|
ValueType = VALUE_TYPE_STRING;
|
|
fValueTypeIsSet = 0;
|
|
ValueTypeMask = VALUE_T_MASK_CLEAR;
|
|
|
|
GetBaseTypeNode( &Type,
|
|
SIGN_SIGNED,
|
|
SIZE_CHAR,
|
|
TYPE_INT );
|
|
pN = (node_skl *)new node_pointer();
|
|
pN->SetBasicType( Type );
|
|
SetType( pN );
|
|
Evaluated();
|
|
Constant();
|
|
Resolved();
|
|
SemanticsDone();
|
|
}
|
|
|
|
expr_constant::expr_constant( long lV )
|
|
{
|
|
Setup( lV, VALUE_TYPE_NUMERIC );
|
|
}
|
|
|
|
expr_constant::expr_constant(
|
|
long lV,
|
|
unsigned short VT )
|
|
{
|
|
Setup( lV, VT );
|
|
}
|
|
|
|
expr_constant::expr_constant(
|
|
wchar_t * pWString )
|
|
{
|
|
node_skl * pN;
|
|
|
|
Value.sValue = (char *)pWString;
|
|
ValueType = VALUE_TYPE_WSTRING;
|
|
fValueTypeIsSet = 0;
|
|
ValueTypeMask = VALUE_T_MASK_CLEAR;
|
|
|
|
SymKey SKey( "wchar_t", NAME_DEF );
|
|
|
|
Type = pBaseSymTbl->SymSearch( SKey );
|
|
|
|
assert( Type != (node_skl *)NULL );
|
|
|
|
|
|
pN = (node_skl *)new node_pointer();
|
|
pN->SetBasicType( Type );
|
|
SetType( pN );
|
|
Evaluated();
|
|
Constant();
|
|
Resolved();
|
|
SemanticsDone();
|
|
}
|
|
|
|
expr_constant::expr_constant(
|
|
long lV,
|
|
unsigned short VType,
|
|
node_skl * pT)
|
|
{
|
|
BOOL fUnsigned = pT->FInSummary( ATTR_UNSIGNED );
|
|
|
|
ValueType = VType;
|
|
Value.lValue = lV;
|
|
fValueTypeIsSet = 1;
|
|
ValueTypeMask = VALUE_T_MASK_CLEAR;
|
|
|
|
switch( pT->NodeKind() )
|
|
{
|
|
case NODE_CHAR:
|
|
ValueTypeMask = fUnsigned ? VALUE_T_MASK_UCHAR : VALUE_T_MASK_CHAR;
|
|
break;
|
|
case NODE_SHORT:
|
|
ValueTypeMask = fUnsigned ? VALUE_T_MASK_USHORT : VALUE_T_MASK_SHORT;
|
|
break;
|
|
case NODE_LONG:
|
|
ValueTypeMask = fUnsigned ? VALUE_T_MASK_ULONG : VALUE_T_MASK_LONG;
|
|
break;
|
|
default:
|
|
ValueTypeMask = VALUE_T_MASK_CLEAR;
|
|
break;
|
|
}
|
|
|
|
SetType( pT );
|
|
Evaluated();
|
|
Constant();
|
|
Resolved();
|
|
SemanticsDone();
|
|
}
|
|
|
|
|
|
void
|
|
expr_constant::Setup(
|
|
long lV,
|
|
unsigned short VT )
|
|
{
|
|
short size;
|
|
BOOL fChar = FALSE;
|
|
BOOL fShort = FALSE;
|
|
BOOL fLong = FALSE;
|
|
BOOL fUChar = FALSE;
|
|
BOOL fUShort = FALSE;
|
|
BOOL fULong = FALSE;
|
|
BOOL unsign = FALSE;
|
|
unsigned long l = (unsigned long) lV;
|
|
unsigned short VTMask = VALUE_T_MASK_CLEAR;
|
|
|
|
Value.lValue = lV;
|
|
ValueType = VT;
|
|
fValueTypeIsSet = 0;
|
|
|
|
|
|
//
|
|
// determine the size of the constant.
|
|
//
|
|
|
|
VTMask = GetValueMask( lV, &fChar,&fShort,&fLong,&fUChar,&fUShort,&fULong );
|
|
|
|
//
|
|
// determine the sign of the constant.
|
|
//
|
|
|
|
if( (fLong || fULong) && !( fShort || fUShort || fChar || fUChar ) )
|
|
{
|
|
size = SIZE_LONG;
|
|
if( !fLong)
|
|
unsign = fULong;
|
|
}
|
|
else if( (fShort || fUShort) )
|
|
{
|
|
size = SIZE_SHORT;
|
|
if( !fShort )
|
|
unsign = fUShort;
|
|
}
|
|
else
|
|
{
|
|
size = SIZE_CHAR;
|
|
if( !fChar )
|
|
unsign = fUChar;
|
|
}
|
|
|
|
ValueTypeMask = VTMask;
|
|
|
|
//
|
|
// if the value type is such that it does not force a size, then the
|
|
// value of the constant determines the value type. value type is used
|
|
// to display/print the constant if needed.
|
|
//
|
|
|
|
switch( VT )
|
|
{
|
|
case VALUE_TYPE_NUMERIC:
|
|
if( size == SIZE_LONG )
|
|
ValueType = VALUE_TYPE_NUMERIC_LONG;
|
|
break;
|
|
case VALUE_TYPE_HEX:
|
|
if( size == SIZE_LONG )
|
|
ValueType = VALUE_TYPE_HEX_LONG;
|
|
break;
|
|
case VALUE_TYPE_OCTAL:
|
|
if( size == SIZE_LONG )
|
|
ValueType = VALUE_TYPE_OCTAL_LONG;
|
|
break;
|
|
}
|
|
|
|
GetBaseTypeNode( &Type,
|
|
unsign ? SIGN_UNSIGNED : SIGN_SIGNED,
|
|
size,
|
|
TYPE_INT );
|
|
Evaluated();
|
|
Constant();
|
|
Resolved();
|
|
SemanticsDone();
|
|
}
|
|
|
|
unsigned short
|
|
expr_constant::GetValueMask(
|
|
unsigned long l,
|
|
BOOL * pfChar,
|
|
BOOL * pfShort,
|
|
BOOL * pfLong,
|
|
BOOL * pfUChar,
|
|
BOOL * pfUShort,
|
|
BOOL * pfULong)
|
|
{
|
|
unsigned short VTMask = VALUE_T_MASK_CLEAR;
|
|
|
|
*pfChar = FALSE;
|
|
*pfShort = FALSE;
|
|
*pfLong = FALSE;
|
|
*pfUChar = FALSE;
|
|
*pfUShort = FALSE;
|
|
*pfULong = FALSE;
|
|
|
|
if( ((long )l >= SCHAR_MIN) && ((long)l <= SCHAR_MAX) )
|
|
{
|
|
VTMask |= ( VALUE_T_MASK_CHAR |
|
|
VALUE_T_MASK_SHORT |
|
|
VALUE_T_MASK_LONG );
|
|
*pfChar = TRUE;
|
|
*pfShort = TRUE;
|
|
*pfLong = TRUE;
|
|
}
|
|
else if( (((long )l >= SHRT_MIN) && ((long)l <= SHRT_MAX) ))
|
|
{
|
|
VTMask |= ( VALUE_T_MASK_SHORT |
|
|
VALUE_T_MASK_LONG );
|
|
*pfShort = TRUE;
|
|
*pfLong = TRUE;
|
|
}
|
|
else
|
|
{
|
|
VTMask |= VALUE_T_MASK_LONG;
|
|
*pfLong = TRUE;
|
|
}
|
|
|
|
if( ((unsigned long)l <= UCHAR_MAX ) )
|
|
{
|
|
VTMask |= ( VALUE_T_MASK_UCHAR |
|
|
VALUE_T_MASK_USHORT |
|
|
VALUE_T_MASK_ULONG );
|
|
*pfUChar = TRUE;
|
|
*pfUShort = TRUE;
|
|
*pfULong = TRUE;
|
|
}
|
|
else if( ((unsigned long)l <= USHRT_MAX ) )
|
|
{
|
|
VTMask |= ( VALUE_T_MASK_USHORT | VALUE_T_MASK_ULONG );
|
|
*pfUShort = TRUE;
|
|
*pfULong = TRUE;
|
|
}
|
|
else
|
|
{
|
|
VTMask |= VALUE_T_MASK_ULONG;
|
|
*pfULong = TRUE;
|
|
}
|
|
|
|
return VTMask;
|
|
|
|
}
|
|
node_state
|
|
expr_constant::SCheck(
|
|
SymTable * pSymTbl)
|
|
{
|
|
UNUSED( pSymTbl );
|
|
SemanticsDone();
|
|
return NODE_STATE_OK;
|
|
}
|
|
void
|
|
expr_constant::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
#define MAX_DECIMAL_LENGTH (10)
|
|
#define MAX_HEX_LENGTH (8)
|
|
#define MAX_OCTAL_LENGTH (25)
|
|
#define ONE_FOR_SIGN (1)
|
|
#define ONE_FOR_ZERO (1)
|
|
#define TWO_FOR_ZERO_X (2)
|
|
#define MAX_CHAR_LENGTH (10) /* arbitrary */
|
|
#define MAX_WCHAR_LENGTH (10) /* arbitrary */
|
|
#define ONE_FOR_L (1)
|
|
#define ONE_FOR_U (1)
|
|
|
|
char * p;
|
|
|
|
UNUSED( pPrefix );
|
|
UNUSED( pSuffix );
|
|
|
|
p = Value.sValue;
|
|
|
|
#if 0 ////////////////////////////////////////////////////////////////////
|
|
|
|
if( (ValueType == VALUE_TYPE_STRING) ||
|
|
(ValueType == VALUE_TYPE_WSTRING ) )
|
|
{
|
|
|
|
if (p )
|
|
p = MakeNewStringWithProperQuoting( Value.sValue );
|
|
|
|
}
|
|
|
|
#endif ///////////////////////////////////////////////////////////////// 0
|
|
|
|
switch( ValueType )
|
|
{
|
|
case VALUE_TYPE_STRING:
|
|
|
|
if( p )
|
|
{
|
|
pOutput->ConcatTail("\"");
|
|
pOutput->ConcatTail( p );
|
|
pOutput->ConcatTail("\"");
|
|
}
|
|
else
|
|
pOutput->ConcatTail( " NULL " );
|
|
return;
|
|
|
|
case VALUE_TYPE_WSTRING:
|
|
|
|
if( p )
|
|
{
|
|
pOutput->ConcatTail("L\"");
|
|
pOutput->ConcatTail( p );
|
|
pOutput->ConcatTail("\"");
|
|
}
|
|
else
|
|
pOutput->ConcatTail( " NULL " );
|
|
|
|
return;
|
|
|
|
case VALUE_TYPE_NUMERIC:
|
|
|
|
p = new char[ MAX_DECIMAL_LENGTH + ONE_FOR_SIGN + ONE_FOR_ZERO ];
|
|
sprintf( p, "%ld" , Value.lValue);
|
|
break;
|
|
|
|
case VALUE_TYPE_NUMERIC_LONG:
|
|
|
|
p = new char[ MAX_DECIMAL_LENGTH + ONE_FOR_SIGN + ONE_FOR_L + ONE_FOR_ZERO ];
|
|
sprintf( p, "%ldL" , Value.lValue);
|
|
break;
|
|
|
|
case VALUE_TYPE_NUMERIC_ULONG:
|
|
|
|
p = new char[ MAX_DECIMAL_LENGTH + ONE_FOR_SIGN + ONE_FOR_L + ONE_FOR_U + ONE_FOR_ZERO ];
|
|
sprintf( p, "%ldUL" , Value.lValue);
|
|
break;
|
|
|
|
case VALUE_TYPE_CHAR:
|
|
case VALUE_TYPE_WCHAR:
|
|
{
|
|
short Size = 1;
|
|
char Char1 = 0;
|
|
char Char2 = 0;
|
|
char Char3 = 0;
|
|
char Char4 = 0;
|
|
char *pTemp;
|
|
|
|
Size += SizeIncrIfSpecialChar( (int )Value.lValue );
|
|
p = pTemp = new char [ Size + 1 + 2 + 1 ]; /* 2 for quote */
|
|
/* 1 for possible L */
|
|
|
|
if( ValueType == VALUE_TYPE_WCHAR )
|
|
*p++ = 'L';
|
|
*p++ = '\'';
|
|
TranslateSpecialCharacter((int)Value.lValue,
|
|
&Char1,
|
|
&Char2,
|
|
&Char3,
|
|
&Char4);
|
|
if( Char1 ) *p++ = Char1;
|
|
if( Char2 ) *p++ = Char2;
|
|
if( Char3 ) *p++ = Char3;
|
|
if( Char4 ) *p++ = Char4;
|
|
*p++ = '\'';
|
|
*p = 0;
|
|
p = pTemp;
|
|
}
|
|
break;
|
|
|
|
case VALUE_TYPE_HEX:
|
|
p = new char[ MAX_HEX_LENGTH + TWO_FOR_ZERO_X + ONE_FOR_ZERO ];
|
|
sprintf( p, "0x%x", Value.lValue );
|
|
break;
|
|
|
|
case VALUE_TYPE_OCTAL:
|
|
p = new char[ ONE_FOR_ZERO + MAX_OCTAL_LENGTH + ONE_FOR_ZERO + ONE_FOR_ZERO ];
|
|
sprintf( p, "0%o", Value.lValue );
|
|
break;
|
|
|
|
case VALUE_TYPE_HEX_LONG:
|
|
p = new char[ MAX_HEX_LENGTH + TWO_FOR_ZERO_X + ONE_FOR_L + ONE_FOR_ZERO ];
|
|
sprintf( p, "0x%lxL", Value.lValue );
|
|
break;
|
|
|
|
case VALUE_TYPE_HEX_ULONG:
|
|
p = new char[ MAX_HEX_LENGTH + TWO_FOR_ZERO_X + ONE_FOR_L + ONE_FOR_U + ONE_FOR_ZERO ];
|
|
sprintf( p, "0x%lxUL", Value.lValue );
|
|
break;
|
|
|
|
case VALUE_TYPE_OCTAL_LONG:
|
|
p = new char[ ONE_FOR_ZERO + MAX_OCTAL_LENGTH + ONE_FOR_L + ONE_FOR_ZERO ];
|
|
sprintf( p, "0%loL", Value.lValue );
|
|
break;
|
|
|
|
case VALUE_TYPE_OCTAL_ULONG:
|
|
p = new char[ ONE_FOR_ZERO + MAX_OCTAL_LENGTH + ONE_FOR_L + ONE_FOR_U + ONE_FOR_ZERO ];
|
|
sprintf( p, "0%loUL", Value.lValue );
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
|
|
}
|
|
|
|
pOutput->ConcatTail( p );
|
|
// delete p; /*** CANNOT DELETE p ***/
|
|
|
|
}
|
|
|
|
long
|
|
expr_constant::Evaluate()
|
|
{
|
|
return GetValue();
|
|
}
|
|
|
|
long
|
|
expr_constant::GetValue()
|
|
{
|
|
|
|
switch( ValueType )
|
|
{
|
|
case VALUE_TYPE_NUMERIC:
|
|
case VALUE_TYPE_NUMERIC_LONG:
|
|
case VALUE_TYPE_NUMERIC_ULONG:
|
|
case VALUE_TYPE_CHAR:
|
|
case VALUE_TYPE_WCHAR:
|
|
case VALUE_TYPE_HEX:
|
|
case VALUE_TYPE_HEX_LONG:
|
|
case VALUE_TYPE_HEX_ULONG:
|
|
case VALUE_TYPE_OCTAL:
|
|
return Value.lValue;
|
|
/************************************************************************
|
|
*** commented out for nt
|
|
***
|
|
case VALUE_TYPE_FLOAT:
|
|
return (long)Value.fValue;
|
|
case VALUE_TYPE_DOUBLE:
|
|
return (long)Value.dValue;
|
|
***********************************************************************/
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
expr_constant::IsAValidConstantOfType(
|
|
node_skl * pValueType )
|
|
{
|
|
NODE_T NT = pValueType->NodeKind();
|
|
BOOL fUnsigned = pValueType->FInSummary( ATTR_UNSIGNED );
|
|
unsigned short VTMask,
|
|
TestMask;
|
|
BOOL fDummy;
|
|
|
|
if( (VTMask = ValueTypeMask) == VALUE_T_MASK_CLEAR )
|
|
{
|
|
//
|
|
// we dont need the individual flags to be returned so we pass all the
|
|
// pointers as pointers to the dummy flag.
|
|
//
|
|
|
|
VTMask = GetValueMask( GetValue(),
|
|
&fDummy,
|
|
&fDummy,
|
|
&fDummy,
|
|
&fDummy,
|
|
&fDummy,
|
|
&fDummy);
|
|
|
|
}
|
|
|
|
//
|
|
// in the generic or win32 case, treat enum as a 32 bit entity.
|
|
//
|
|
|
|
if( NT == NODE_ENUM )
|
|
{
|
|
unsigned short Env = pCommand->GetEnv();
|
|
if( (Env == ENV_WIN32) )
|
|
{
|
|
NT = NODE_LONG;
|
|
}
|
|
else
|
|
NT = NODE_SHORT;
|
|
}
|
|
|
|
switch( NT )
|
|
{
|
|
case NODE_BOOLEAN:
|
|
case NODE_SMALL:
|
|
case NODE_CHAR:
|
|
TestMask = fUnsigned ? VALUE_T_MASK_UCHAR : VALUE_T_MASK_CHAR;
|
|
break;
|
|
case NODE_SHORT:
|
|
TestMask = fUnsigned ? VALUE_T_MASK_USHORT : VALUE_T_MASK_SHORT;
|
|
break;
|
|
case NODE_LONG:
|
|
TestMask = fUnsigned ? VALUE_T_MASK_ULONG : VALUE_T_MASK_LONG;
|
|
break;
|
|
default:
|
|
TestMask = VALUE_T_MASK_CLEAR;
|
|
}
|
|
|
|
return (BOOL) ( VTMask & TestMask );
|
|
}
|
|
|
|
BOOL
|
|
expr_constant::IsExprInt()
|
|
{
|
|
node_skl * pType = GetType();
|
|
NODE_T NT = pType->NodeKind();
|
|
|
|
switch( NT )
|
|
{
|
|
case NODE_SHORT:
|
|
case NODE_INT:
|
|
case NODE_LONG:
|
|
case NODE_LONGLONG:
|
|
case NODE_HYPER:
|
|
case NODE_SMALL:
|
|
case NODE_ENUM:
|
|
case NODE_WCHAR_T:
|
|
case NODE_CHAR:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
/***************************************************************************
|
|
* expr_init_list routines
|
|
***************************************************************************/
|
|
expr_node *
|
|
expr_init_list::ChildNthExpr(
|
|
short n )
|
|
{
|
|
expr_node * pC = GetChild();
|
|
|
|
if( !n )
|
|
return this;
|
|
|
|
if( pC )
|
|
return pC->ChildNthExpr( n - 1 );
|
|
else
|
|
return pTerminator;
|
|
}
|
|
|
|
expr_node *
|
|
expr_init_list::SiblingNthExpr(
|
|
short n )
|
|
{
|
|
expr_node * pS = GetSibling();
|
|
|
|
if( !n )
|
|
return this;
|
|
|
|
if(pS)
|
|
return pS->SiblingNthExpr( n - 1 );
|
|
else
|
|
return pTerminator;
|
|
}
|
|
|
|
void
|
|
expr_init_list::Print(
|
|
BufferManager * pPrefix ,
|
|
BufferManager * pSuffix ,
|
|
BufferManager * pOutput )
|
|
{
|
|
expr_init_list * pC = GetChild(),
|
|
* pS = GetSibling();
|
|
|
|
|
|
if( pC )
|
|
{
|
|
pOutput->ConcatTail( "\n { " );
|
|
pC->Print( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( " }\n" );
|
|
}
|
|
|
|
|
|
if( pExpr )
|
|
pExpr->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
|
|
// dump the sibling now
|
|
|
|
if( pS )
|
|
{
|
|
pOutput->ConcatTail( "," );
|
|
pS->Print( pPrefix, pSuffix, pOutput );
|
|
}
|
|
}
|
|
|
|
void
|
|
expr_init_list::LinkSibling(
|
|
expr_init_list * pNewSibling )
|
|
{
|
|
expr_init_list * pS = this;
|
|
expr_init_list * pSave;
|
|
|
|
while( (pSave = pS ) && (pS = pS->GetSibling()) );
|
|
|
|
// pSave will definitely have a non-zero
|
|
|
|
pSave->SetSibling( pNewSibling );
|
|
}
|
|
|
|
void
|
|
expr_init_list::LinkChild(
|
|
expr_init_list * pNewChild )
|
|
{
|
|
expr_init_list * pC = this;
|
|
expr_init_list * pSave;
|
|
|
|
while( (pSave = pC ) && (pC = pC->GetChild()) );
|
|
|
|
// pSave will definitely have a non-zero
|
|
|
|
pSave->SetChild( pNewChild );
|
|
}
|
|
|
|
ETYPE
|
|
expr_init_list::SetType(
|
|
ETYPE pType)
|
|
{
|
|
type_node_list * pTNList;
|
|
node_skl * pNode;
|
|
expr_init_list * pSibOfChild,
|
|
* pC = GetChild(),
|
|
* pS = GetSibling();
|
|
expr_node * pE;
|
|
ETYPE pTypeForSibling = pType;
|
|
|
|
Type = pType = TrueType( pType );
|
|
|
|
if( pC )
|
|
{
|
|
switch( pType->NodeKind() )
|
|
{
|
|
case NODE_ARRAY:
|
|
|
|
pC->SetType( pType->GetBasicType() );
|
|
break;
|
|
|
|
case NODE_STRUCT:
|
|
case NODE_UNION:
|
|
|
|
{
|
|
|
|
BOOL fTypeExists;
|
|
|
|
pSibOfChild = GetChild();
|
|
pTNList = new type_node_list;
|
|
|
|
pType->GetMembers( pTNList );
|
|
|
|
while( pSibOfChild && (pTNList->GetPeer( &pNode )==STATUS_OK) )
|
|
{
|
|
pSibOfChild->SetOneType( pNode );
|
|
pSibOfChild = pSibOfChild->GetSibling();
|
|
}
|
|
|
|
fTypeExists = (BOOL)(pTNList->GetPeer( &pNode ) == STATUS_OK);
|
|
#if 0
|
|
if( pSibOfChild || fTypeExists )
|
|
{
|
|
ParseError( INITIALIZER_MISMATCH, (char *)NULL );
|
|
}
|
|
#endif // 0
|
|
delete pTNList;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
GetChild()->SetType( pType );
|
|
}
|
|
}
|
|
|
|
else if(!(pType->NodeKind() == NODE_ERROR) &&
|
|
!( (IsIntegralType( pType )) ||
|
|
(pType->NodeKind() == NODE_FLOAT) ||
|
|
(pType->NodeKind() == NODE_CHAR) ||
|
|
(pType->NodeKind() == NODE_WCHAR_T) ||
|
|
(pType->NodeKind() == NODE_BOOLEAN) ||
|
|
(pType->NodeKind() == NODE_DOUBLE) ||
|
|
(pType->NodeKind() == NODE_POINTER) ) )
|
|
{
|
|
#if 0
|
|
ParseError( INITIALIZER_MISMATCH, (char *)NULL );
|
|
#endif // 0
|
|
pTypeForSibling = pErrorTypeNode;
|
|
|
|
}
|
|
|
|
if( pS )
|
|
pS->SetType( pTypeForSibling );
|
|
|
|
if( pE = GetExpr() )
|
|
{
|
|
pType = pE->SetType( pType );
|
|
}
|
|
|
|
return pType;
|
|
}
|
|
|
|
ETYPE
|
|
expr_init_list::SetOneType(
|
|
ETYPE pType )
|
|
{
|
|
Type = TrueType( pType );
|
|
|
|
if( pExpr )
|
|
pExpr->SetType( Type );
|
|
|
|
return Type;
|
|
}
|
|
|
|
short
|
|
expr_init_list::Dump(
|
|
short Num,
|
|
BufferManager * pPrefix,
|
|
BufferManager * pOutput )
|
|
{
|
|
expr_init_list * pC = GetChild(),
|
|
* pS = GetSibling();
|
|
short CurrentNum = Num;
|
|
|
|
if( Num == 0 )
|
|
{
|
|
pPrefix = new BufferManager(10);
|
|
pOutput = new BufferManager(10);
|
|
pOutput->ConcatTail( "Expression Dump \n" );
|
|
pOutput->ConcatTail( "--------------- \n" );
|
|
pOutput->Print( stdout );
|
|
pOutput->Clear();
|
|
}
|
|
|
|
// dump this node
|
|
|
|
if( pExpr )
|
|
{
|
|
pExpr->PrintExpr( pPrefix, (BufferManager *)NULL, pOutput );
|
|
pOutput->ConcatTail( "[ ");
|
|
pOutput->ConcatTail(pExpr->GetType()->GetNodeNameString());
|
|
pOutput->ConcatTail( "] ");
|
|
pOutput->Print( stdout );
|
|
pOutput->Clear();
|
|
}
|
|
|
|
if( pC )
|
|
{
|
|
pOutput->ConcatTail("\n{");
|
|
pOutput->Print( stdout );
|
|
pOutput->Clear();
|
|
|
|
CurrentNum = pC->Dump( CurrentNum+1, pPrefix, pOutput );
|
|
|
|
pOutput->ConcatTail("}");
|
|
pOutput->Print( stdout );
|
|
pOutput->Clear();
|
|
}
|
|
|
|
if( pS )
|
|
{
|
|
pOutput->ConcatTail(",");
|
|
pOutput->Print( stdout );
|
|
pOutput->Clear();
|
|
|
|
CurrentNum = pS->Dump( CurrentNum+1, pPrefix, pOutput );
|
|
|
|
pOutput->Clear();
|
|
}
|
|
|
|
if( Num == 0 )
|
|
{
|
|
pOutput->ConcatTail( "\n--------------- \n" );
|
|
pOutput->Print( stdout );
|
|
pOutput->Clear();
|
|
}
|
|
return CurrentNum;
|
|
}
|
|
|
|
expr_init_list *
|
|
expr_init_list::GetChild()
|
|
{
|
|
if( pChild && !pChild->IsExprTerminator() )
|
|
return pChild;
|
|
return (expr_init_list *)NULL;
|
|
}
|
|
|
|
expr_init_list *
|
|
expr_init_list::GetSibling()
|
|
{
|
|
if( pSibling && !pSibling->IsExprTerminator() )
|
|
return pSibling;
|
|
return (expr_init_list *)NULL;
|
|
}
|
|
BOOL
|
|
expr_init_list::IsANumber()
|
|
{
|
|
expr_init_list * pC = GetChild(),
|
|
* pS = GetSibling();
|
|
|
|
if( !pS && !pC && pExpr )
|
|
return pExpr->IsANumber();
|
|
return FALSE;
|
|
}
|
|
long
|
|
expr_init_list::Evaluate()
|
|
{
|
|
if( pExpr )
|
|
return pExpr->Evaluate();
|
|
else
|
|
return 0L;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
* expr_terminator
|
|
***************************************************************************/
|
|
long
|
|
expr_terminator::Evaluate()
|
|
{
|
|
// ParseError( USE_OF_UNINITED_DATA, (char *)NULL);
|
|
return 0L;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* expression list handler
|
|
*****************************************************************************/
|
|
expr_list::expr_list()
|
|
{
|
|
extern int ConstExprCompare( void *, void *);
|
|
|
|
SetAllocFn( (void *(*)(void))NULL);
|
|
SetDeAllocFn( (void (*)(void *))NULL);
|
|
SetCompFn( ConstExprCompare );
|
|
}
|
|
STATUS_T
|
|
expr_list::GetPeer(
|
|
expr_node ** ppExpr )
|
|
{
|
|
return (GetNext( (void **)ppExpr ) );
|
|
}
|
|
STATUS_T
|
|
expr_list::SetPeer(
|
|
expr_node * pExpr )
|
|
{
|
|
return Insert( (void *) pExpr );
|
|
}
|
|
STATUS_T
|
|
expr_list::Merge(
|
|
expr_list *pSrcList )
|
|
{
|
|
expr_node *pNode;
|
|
|
|
if(pSrcList)
|
|
{
|
|
pSrcList->Init();
|
|
while(pSrcList->GetPeer(&pNode) == STATUS_OK)
|
|
SetPeer(pNode);
|
|
}
|
|
return STATUS_OK;
|
|
}
|
|
/***************************************************************************
|
|
* utility routines
|
|
***************************************************************************/
|
|
SymTable *
|
|
InScope(
|
|
node_skl * pNode,
|
|
char * pName )
|
|
{
|
|
NODE_T NT = pNode->NodeKind();
|
|
char * pBaseName;
|
|
NAME_T Tag;
|
|
SymTable * pSTbl;
|
|
|
|
|
|
pBaseName = pNode->GetSymName();
|
|
|
|
switch( NT )
|
|
{
|
|
case NODE_PROC: Tag = NAME_PROC; break;
|
|
case NODE_STRUCT: Tag = NAME_TAG; break;
|
|
case NODE_UNION: Tag = NAME_UNION; break;
|
|
case NODE_ENUM: Tag = NAME_ENUM; break;
|
|
default: return (SymTable *)NULL;
|
|
}
|
|
|
|
SymKey SBaseKey( pBaseName, Tag );
|
|
|
|
if( pBaseSymTbl->SymSearch( SBaseKey ) )
|
|
{
|
|
pSTbl = pBaseSymTbl;
|
|
pSTbl->EnterScope( SBaseKey, &pSTbl );
|
|
SymKey SKey( pName, NAME_MEMBER );
|
|
if( pSTbl->SymSearch( SKey ) )
|
|
return pSTbl;
|
|
|
|
if( Tag == NAME_TAG )
|
|
{
|
|
TLNDICT * pTLNDict = new TLNDICT();
|
|
|
|
pNode->GetTopLevelNames( pTLNDict, FALSE );
|
|
|
|
pSTbl = pTLNDict->GetSymTableForTopLevelName( pName );
|
|
|
|
delete pTLNDict;
|
|
return pSTbl;
|
|
}
|
|
}
|
|
return (SymTable *)NULL;
|
|
|
|
}
|
|
|
|
BOOL
|
|
IsEvaluatable(
|
|
expr_node * pExpr )
|
|
{
|
|
if( !pExpr->IsConstant() )
|
|
{
|
|
ParseError( EXPR_NOT_EVALUATABLE, (char *)NULL );
|
|
return FALSE;
|
|
}
|
|
else if( pExpr->IsTooComplex() )
|
|
{
|
|
ParseError( EXPR_NOT_IMPLEMENTED, (char *)NULL );
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
ETYPE
|
|
TrueType(
|
|
ETYPE pType )
|
|
{
|
|
NODE_T NT = pType->NodeKind();
|
|
|
|
if( ( NT == NODE_PARAM ) ||
|
|
( NT == NODE_FIELD ) ||
|
|
( NT == NODE_DEF ) ||
|
|
( NT == NODE_PROC ) ||
|
|
( NT == NODE_ID ))
|
|
pType = pType->GetBasicType();
|
|
return pType;
|
|
}
|
|
|
|
BOOL
|
|
IsIntegralType(
|
|
ETYPE Type )
|
|
{
|
|
NODE_T NT;
|
|
|
|
if( (NT = Type->NodeKind()) == NODE_DEF )
|
|
{
|
|
NT = (Type->GetBasicType())->NodeKind();
|
|
}
|
|
|
|
switch( NT )
|
|
{
|
|
case NODE_SHORT:
|
|
case NODE_INT:
|
|
case NODE_LONG:
|
|
case NODE_LONGLONG:
|
|
case NODE_HYPER:
|
|
case NODE_SMALL:
|
|
case NODE_ENUM:
|
|
case NODE_WCHAR_T:
|
|
return 1;
|
|
|
|
case NODE_CHAR:
|
|
if(pCommand->IsSwitchDefined(SWITCH_C_EXT))
|
|
return 1;
|
|
else
|
|
return 0;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
ETYPE
|
|
GetResultantArithType(
|
|
ETYPE pLeftType,
|
|
ETYPE pRightType )
|
|
{
|
|
ETYPE ResultType;
|
|
unsigned short iRightType,
|
|
iLeftType;
|
|
|
|
iLeftType = XLateToInternalType( pLeftType );
|
|
iRightType = XLateToInternalType( pRightType );
|
|
|
|
if( ( iLeftType == I_ETYPE_ERROR ) ||
|
|
( iRightType == I_ETYPE_ERROR ) ||
|
|
( (iLeftType = ArithCompatMatrix[ iLeftType ][ iRightType ])==
|
|
I_ETYPE_ERROR) )
|
|
{
|
|
return pLeftType;
|
|
}
|
|
else
|
|
ResultType = XLateToType( iLeftType );
|
|
|
|
return ResultType;
|
|
}
|
|
|
|
BOOL
|
|
IsCompatibleIntegralType(
|
|
ETYPE pLeftType,
|
|
ETYPE pRightType )
|
|
{
|
|
unsigned short iRightType,
|
|
iLeftType;
|
|
|
|
iLeftType = XLateToInternalType( pLeftType );
|
|
iRightType = XLateToInternalType( pRightType );
|
|
|
|
if( ( iLeftType == I_ETYPE_ERROR ) ||
|
|
( iRightType == I_ETYPE_ERROR ) ||
|
|
( (iLeftType = ArithCompatMatrix[ iLeftType ][ iRightType ])==
|
|
I_ETYPE_ERROR) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
IsNumeric(
|
|
ETYPE Type )
|
|
{
|
|
return ((IsIntegralType( Type )) ||
|
|
(Type->NodeKind() == NODE_CHAR) ||
|
|
(Type->NodeKind() == NODE_WCHAR_T) ||
|
|
(Type->NodeKind() == NODE_FLOAT) ||
|
|
(Type->NodeKind() == NODE_DOUBLE) );
|
|
}
|
|
|
|
unsigned short
|
|
XLateToInternalType(
|
|
ETYPE Type )
|
|
{
|
|
unsigned short InternalType;
|
|
|
|
switch( Type->NodeKind() )
|
|
{
|
|
case NODE_CHAR: InternalType = I_ETYPE_CHAR; break;
|
|
case NODE_SHORT: InternalType = I_ETYPE_SHORT; break;
|
|
case NODE_INT: InternalType = I_ETYPE_INT; break;
|
|
case NODE_LONG: InternalType = I_ETYPE_LONG; break;
|
|
case NODE_SMALL: InternalType = I_ETYPE_SMALL; break;
|
|
case NODE_BYTE: InternalType = I_ETYPE_BYTE; break;
|
|
case NODE_HYPER: InternalType = I_ETYPE_HYPER; break;
|
|
case NODE_FLOAT: InternalType = I_ETYPE_FLOAT; break;
|
|
case NODE_DOUBLE: InternalType = I_ETYPE_DOUBLE; break;
|
|
case NODE_BOOLEAN: InternalType = I_ETYPE_BOOL; break;
|
|
default:
|
|
return I_ETYPE_ERROR;
|
|
}
|
|
|
|
if( Type->FInSummary( ATTR_UNSIGNED ) )
|
|
InternalType = CONVERT_TO_UNSIGNED( InternalType );
|
|
return InternalType;
|
|
}
|
|
|
|
ETYPE
|
|
XLateToType(
|
|
unsigned short IType )
|
|
{
|
|
int BaseType = TYPE_INT;
|
|
int Sign;
|
|
int Size;
|
|
ETYPE ResultType;
|
|
|
|
switch( IType )
|
|
{
|
|
case I_ETYPE_UCHAR: Sign = SIGN_UNSIGNED; Size = SIZE_CHAR; break;
|
|
case I_ETYPE_CHAR: Sign = SIGN_SIGNED; Size = SIZE_CHAR; break;
|
|
case I_ETYPE_USHORT:Sign = SIGN_UNSIGNED; Size = SIZE_SHORT; break;
|
|
case I_ETYPE_SHORT: Sign = SIGN_SIGNED; Size = SIZE_SHORT; break;
|
|
case I_ETYPE_UINT: Sign = SIGN_UNSIGNED; Size = SIZE_UNDEF; break;
|
|
case I_ETYPE_INT: Sign = SIGN_SIGNED; Size = SIZE_UNDEF; break;
|
|
case I_ETYPE_ULONG: Sign = SIGN_UNSIGNED; Size = SIZE_LONG; break;
|
|
case I_ETYPE_LONG: Sign = SIGN_SIGNED; Size = SIZE_LONG; break;
|
|
case I_ETYPE_USMALL:Sign = SIGN_UNSIGNED; Size = SIZE_SMALL;break;
|
|
case I_ETYPE_SMALL: Sign = SIGN_SIGNED; Size = SIZE_SMALL;break;
|
|
case I_ETYPE_UHYPER:Sign = SIGN_UNSIGNED; Size = SIZE_HYPER; break;
|
|
case I_ETYPE_HYPER: Sign = SIGN_SIGNED; Size = SIZE_HYPER; break;
|
|
case I_ETYPE_BYTE:
|
|
Sign = SIGN_UNSIGNED;
|
|
Size = SIZE_UNDEF;
|
|
BaseType= TYPE_BYTE;
|
|
break;
|
|
case I_ETYPE_BOOL:
|
|
Sign = SIGN_UNSIGNED;
|
|
Size = SIZE_UNDEF;
|
|
BaseType= TYPE_BOOLEAN;
|
|
break;
|
|
case I_ETYPE_FLOAT:
|
|
Sign = SIGN_UNDEF;
|
|
Size = SIZE_UNDEF;
|
|
BaseType= TYPE_FLOAT;
|
|
break;
|
|
case I_ETYPE_DOUBLE:
|
|
Sign = SIGN_UNDEF;
|
|
Size = SIZE_UNDEF;
|
|
BaseType= TYPE_DOUBLE;
|
|
break;
|
|
default:
|
|
return pErrorTypeNode;
|
|
}
|
|
|
|
GetBaseTypeNode( &ResultType, Sign, Size, BaseType );
|
|
return ResultType;
|
|
}
|
|
|
|
char *
|
|
GetOperatorString(
|
|
OPERATOR Op )
|
|
{
|
|
char * p;
|
|
|
|
switch( Op )
|
|
{
|
|
case OP_UNARY_PLUS:
|
|
case OP_PLUS: p = " + "; break;
|
|
case OP_UNARY_MINUS:
|
|
case OP_MINUS: p = " - "; break;
|
|
case OP_UNARY_AND: p = " & "; break;
|
|
case OP_UNARY_SIZEOF: p = " sizeof "; break;
|
|
case OP_UNARY_INDIRECTION:
|
|
case OP_STAR: p = " * "; break;
|
|
case OP_SLASH: p = " / "; break;
|
|
case OP_MOD: p = " % "; break;
|
|
|
|
case OP_UNARY_NOT: p = " ! "; break;
|
|
case OP_UNARY_COMPLEMENT: p = " ~ "; break;
|
|
case OP_LEFT_SHIFT: p = " << "; break;
|
|
case OP_RIGHT_SHIFT: p = " >> "; break;
|
|
case OP_LESS: p = " < "; break;
|
|
case OP_LESS_EQUAL: p = " <= "; break;
|
|
case OP_EQUAL: p = " == "; break;
|
|
case OP_NOT_EQUAL: p = " != "; break;
|
|
case OP_GREATER_EQUAL: p = " >= "; break;
|
|
case OP_GREATER: p = " > "; break;
|
|
case OP_AND: p = " & "; break;
|
|
case OP_OR: p = " | "; break;
|
|
case OP_XOR: p = " ^ "; break;
|
|
case OP_LOGICAL_OR: p = " || "; break;
|
|
case OP_LOGICAL_AND: p = " && "; break;
|
|
case OP_QM: p = " ? "; break;
|
|
case OP_COLON: p = " : "; break;
|
|
case OP_POINTSTO: p = " -> "; break;
|
|
case OP_DOT: p = " . "; break;
|
|
|
|
|
|
default:
|
|
assert( FALSE );
|
|
p = "???";
|
|
break;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
int
|
|
ConstExprCompare(
|
|
void * p1,
|
|
void * p2 )
|
|
{
|
|
expr_node * pE1 = (expr_node *)p1;
|
|
expr_node * pE2 = (expr_node *)p2;
|
|
long Val1;
|
|
long Val2;
|
|
|
|
if( !pE1 ) return -1;
|
|
if( !pE2 ) return -1;
|
|
|
|
Val1 = pE1->GetValue();
|
|
Val2 = pE2->GetValue();
|
|
|
|
return ( Val1 < Val2 ) ? -1 : ( Val1 == Val2 ) ? 0 : 1;
|
|
}
|
|
|
|
/***************************************************************************
|
|
These functions exist here because cfront generates redefintions for virtual
|
|
in line functions and the MIPS compiler does not like it.
|
|
***************************************************************************/
|
|
|
|
BOOL
|
|
expr_node::IsOperator()
|
|
{
|
|
return FALSE;
|
|
}
|
|
BOOL
|
|
expr_node::IsANumber()
|
|
{
|
|
return FALSE;
|
|
}
|
|
BOOL
|
|
expr_node::IsAnExpression()
|
|
{
|
|
return FALSE;
|
|
}
|
|
void
|
|
expr_node::PrintExpr(
|
|
BufferManager *pPrefix,
|
|
BufferManager *pSuffix,
|
|
BufferManager *pOutput )
|
|
{
|
|
}
|
|
long
|
|
expr_node::Evaluate()
|
|
{
|
|
return 0L;
|
|
}
|
|
long
|
|
expr_node::GetValue()
|
|
{
|
|
return 0L;
|
|
}
|
|
BOOL
|
|
expr_node::IsExprTerminator()
|
|
{
|
|
return (BOOL)FALSE;
|
|
}
|
|
BOOL
|
|
expr_node::IsInitList()
|
|
{
|
|
return (BOOL)FALSE;
|
|
}
|
|
expr_node *
|
|
expr_node::ChildNthExpr( short )
|
|
{
|
|
return (expr_node *)pTerminator;
|
|
}
|
|
|
|
expr_node *
|
|
expr_node::SiblingNthExpr( short )
|
|
{
|
|
return (expr_node *)pTerminator;
|
|
}
|
|
char *
|
|
expr_node::GetName()
|
|
{
|
|
return "";
|
|
}
|
|
BOOL
|
|
expr_op_unary::IsAPointerExpr()
|
|
{
|
|
if( (GetOperator() == OP_UNARY_INDIRECTION ) &&
|
|
( GetLeft()->IsAPureVariable() ) )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
BOOL
|
|
expr_op_unary::DerivesUniqueFull()
|
|
{
|
|
node_skl * pT = GetType();
|
|
BOOL fAnyChildIsUniqueFull = pLeft && pLeft->DerivesUniqueFull();
|
|
BOOL fThisIsUniqueFull;
|
|
|
|
fThisIsUniqueFull = (pT->NodeKind() == NODE_POINTER) &&
|
|
( (pT->FInSummary( ATTR_UNIQUE ) ||
|
|
pT->FInSummary( ATTR_PTR )
|
|
)
|
|
);
|
|
|
|
return ( fAnyChildIsUniqueFull || fThisIsUniqueFull );
|
|
}
|
|
|
|
BOOL
|
|
expr_op_unary::DerivesFromIgnore()
|
|
{
|
|
node_skl * pT = GetType();
|
|
BOOL fAnyChildIsIgnore = pLeft && pLeft->DerivesFromIgnore();
|
|
BOOL fThisIsIgnore;
|
|
|
|
fThisIsIgnore = (pT->NodeKind() == NODE_POINTER) &&
|
|
(pT->FInSummary( ATTR_IGNORE ));
|
|
|
|
return ( fAnyChildIsIgnore || fThisIsIgnore );
|
|
}
|
|
/*****************************************************************************/
|
|
BOOL
|
|
expr_op::IsOperator()
|
|
{
|
|
return (BOOL)TRUE;
|
|
}
|
|
|
|
BOOL
|
|
expr_op::IsAnExpression()
|
|
{
|
|
return (BOOL) TRUE;
|
|
}
|
|
long
|
|
expr_op::Evaluate()
|
|
{
|
|
return 0L;
|
|
}
|
|
long
|
|
expr_op::GetValue()
|
|
{
|
|
return 0L;
|
|
}
|
|
/*****************************************************************************/
|
|
|
|
BOOL
|
|
expr_op_unary::IsANumber()
|
|
{
|
|
return pLeft->IsANumber();
|
|
}
|
|
long
|
|
expr_op_unary::GetValue()
|
|
{
|
|
return Evaluate();
|
|
}
|
|
/*****************************************************************************/
|
|
BOOL
|
|
expr_op_binary::IsANumber()
|
|
{
|
|
BOOL fLeft, fRight;
|
|
|
|
fLeft = pLeft ? pLeft->IsANumber() : 0;
|
|
fRight = pRight ? pRight->IsANumber() : 0;
|
|
return (BOOL)(pLeft && pRight);
|
|
}
|
|
long
|
|
expr_op_binary::GetValue()
|
|
{
|
|
return Evaluate();
|
|
}
|
|
BOOL
|
|
expr_op_binary::DerivesUniqueFull()
|
|
{
|
|
node_skl * pT = GetType();
|
|
|
|
BOOL fAnyChildIsUniqueFull =
|
|
( (pLeft && pLeft->DerivesUniqueFull()) ||
|
|
(pRight && pRight->DerivesUniqueFull())
|
|
);
|
|
|
|
BOOL fThisIsUniqueFull;
|
|
|
|
fThisIsUniqueFull = (pT->NodeKind() == NODE_POINTER) &&
|
|
( (pT->FInSummary( ATTR_UNIQUE ) ||
|
|
pT->FInSummary( ATTR_PTR )
|
|
)
|
|
);
|
|
|
|
return ( fAnyChildIsUniqueFull || fThisIsUniqueFull );
|
|
}
|
|
|
|
BOOL
|
|
expr_op_binary::DerivesFromIgnore()
|
|
{
|
|
node_skl * pT = GetType();
|
|
|
|
BOOL fAnyChildIsIgnore =
|
|
( (pLeft && pLeft->DerivesFromIgnore()) ||
|
|
(pRight && pRight->DerivesFromIgnore())
|
|
);
|
|
|
|
BOOL fThisIsIgnore;
|
|
|
|
fThisIsIgnore = (pT->NodeKind() == NODE_POINTER) &&
|
|
(pT->FInSummary( ATTR_IGNORE ));
|
|
|
|
return ( fAnyChildIsIgnore || fThisIsIgnore );
|
|
}
|
|
/*****************************************************************************/
|
|
BOOL
|
|
expr_sizeof::IsANumber()
|
|
{
|
|
return (BOOL)TRUE;
|
|
}
|
|
long
|
|
expr_sizeof::GetValue()
|
|
{
|
|
return Evaluate();
|
|
}
|
|
/*****************************************************************************/
|
|
char *
|
|
expr_fn_param::GetName()
|
|
{
|
|
return pName;
|
|
}
|
|
|
|
void
|
|
expr_fn_param::PrintExpr(
|
|
class BufferManager * pPrefix,
|
|
class BufferManager * pSuffix,
|
|
class BufferManager * pOutput)
|
|
{
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
|
|
if(pNext )
|
|
pNext->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
}
|
|
/*****************************************************************************/
|
|
char *
|
|
expr_fn::GetName()
|
|
{
|
|
return pName;
|
|
}
|
|
void
|
|
expr_fn::PrintExpr(
|
|
class BufferManager * pPrefix,
|
|
class BufferManager * pSuffix,
|
|
class BufferManager * pOutput )
|
|
{
|
|
pOutput->ConcatTail( pName );
|
|
pOutput->ConcatTail( "(" );
|
|
if( pLeft )
|
|
pLeft->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
pOutput->ConcatTail( ")" );
|
|
}
|
|
/*****************************************************************************/
|
|
BOOL
|
|
expr_constant::IsANumber()
|
|
{
|
|
return (ValueType != VALUE_TYPE_STRING);
|
|
}
|
|
/*****************************************************************************/
|
|
long
|
|
expr_variable::Evaluate()
|
|
{
|
|
return pExpr->Evaluate();
|
|
}
|
|
char *
|
|
expr_variable::GetName()
|
|
{
|
|
return pName;
|
|
}
|
|
long
|
|
expr_variable::GetValue()
|
|
{
|
|
if( pExpr )
|
|
return pExpr->GetValue();
|
|
else
|
|
return 0L;
|
|
}
|
|
BOOL
|
|
expr_variable::DerivesUniqueFull()
|
|
{
|
|
node_skl * pT = GetType();
|
|
|
|
if( (pT->NodeKind() == NODE_POINTER) &&
|
|
(pT->FInSummary( ATTR_UNIQUE ) || pT->FInSummary( ATTR_PTR ) ) )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
BOOL
|
|
expr_variable::DerivesFromIgnore()
|
|
{
|
|
node_skl * pT = GetType();
|
|
|
|
if( (pT->NodeKind() == NODE_POINTER) &&
|
|
(pT->FInSummary( ATTR_IGNORE ) ) )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
/*****************************************************************************/
|
|
void
|
|
expr_init_list::SetChild(
|
|
class expr_init_list *pC )
|
|
{
|
|
pChild = pC;
|
|
}
|
|
void
|
|
expr_init_list::SetSibling(
|
|
class expr_init_list *pS )
|
|
{
|
|
pSibling = pS;
|
|
}
|
|
|
|
expr_node *
|
|
expr_init_list::GetExpr()
|
|
{
|
|
return pExpr ? pExpr->GetExpr() : (expr_node *)0 ;
|
|
}
|
|
BOOL
|
|
expr_init_list::IsCompoundInitializer()
|
|
{
|
|
return ( GetSibling() != (expr_init_list *)NULL );
|
|
}
|
|
|
|
void
|
|
expr_init_list::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix,
|
|
BufferManager * pOutput )
|
|
{
|
|
if( pExpr )
|
|
pExpr->PrintExpr( pPrefix, pSuffix, pOutput );
|
|
}
|
|
long
|
|
expr_init_list::GetValue()
|
|
{
|
|
return Evaluate();
|
|
}
|
|
BOOL
|
|
expr_init_list::IsInitList()
|
|
{
|
|
return TRUE;
|
|
}
|
|
/*****************************************************************************/
|
|
void
|
|
expr_terminator::LinkSibling(
|
|
class expr_init_list *p )
|
|
{
|
|
}
|
|
|
|
void
|
|
expr_terminator::LinkChild(
|
|
class expr_init_list *p )
|
|
{
|
|
}
|
|
|
|
void
|
|
expr_terminator::SetChild(
|
|
class expr_init_list *pC )
|
|
{
|
|
}
|
|
void
|
|
expr_terminator::SetSibling(
|
|
class expr_init_list *pS )
|
|
{
|
|
}
|
|
|
|
expr_init_list *
|
|
expr_terminator::GetSibling()
|
|
{
|
|
return (expr_init_list *)NULL;
|
|
}
|
|
|
|
expr_init_list *
|
|
expr_terminator::GetChild()
|
|
{
|
|
return (expr_init_list *)NULL;
|
|
}
|
|
|
|
BOOL
|
|
expr_terminator::IsCompoundInitializer()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
expr_terminator::Print(
|
|
BufferManager *pP ,
|
|
BufferManager *pS,
|
|
BufferManager *pO )
|
|
{
|
|
}
|
|
|
|
void
|
|
expr_terminator::PrintExpr(
|
|
BufferManager * pPrefix,
|
|
BufferManager * pSuffix ,
|
|
BufferManager * pOutput )
|
|
{
|
|
}
|
|
|
|
ETYPE
|
|
expr_terminator::SetType(
|
|
ETYPE pType )
|
|
{
|
|
return ( Type = pType );
|
|
}
|
|
|
|
BOOL
|
|
expr_terminator::IsANumber()
|
|
{
|
|
return (BOOL)FALSE;
|
|
}
|
|
|
|
BOOL
|
|
expr_terminator::IsExprTerminator()
|
|
{
|
|
return (BOOL)TRUE;
|
|
}
|
|
/*****************************************************************************/
|
|
node_state
|
|
expr_sizeof::SCheck(
|
|
class SymTable *pSymTbl )
|
|
{
|
|
if( !IsSemanticsDone() )
|
|
{
|
|
if( !IsValidSizeOfType( pSizeofType ) )
|
|
{
|
|
ParseError( INVALID_SIZEOF_OPERAND , (char *)0 );
|
|
}
|
|
}
|
|
|
|
SemanticsDone();
|
|
return Resolve( pSymTbl );
|
|
}
|
|
|
|
node_state
|
|
expr_fn_param::SCheck(
|
|
class SymTable * pSymTbl)
|
|
{
|
|
|
|
UNUSED( pSymTbl );
|
|
|
|
SemanticsDone();
|
|
return NODE_STATE_OK;
|
|
|
|
}
|
|
|
|
node_state
|
|
expr_fn::SCheck(
|
|
class SymTable * pSymTbl)
|
|
{
|
|
|
|
UNUSED( pSymTbl );
|
|
|
|
SemanticsDone();
|
|
return NODE_STATE_OK;
|
|
|
|
}
|
|
|
|
expr_fn_param::expr_fn_param(
|
|
expr_node * pL) : expr_op_unary(OP_PARAM, pL )
|
|
{
|
|
pNext = (expr_fn_param *)NULL;
|
|
pName = "";
|
|
};
|
|
|
|
expr_fn_param::~expr_fn_param()
|
|
{
|
|
delete pNext;
|
|
delete pName;
|
|
delete pLeft;
|
|
};
|
|
|
|
expr_fn::expr_fn(
|
|
expr_node *pL ) : expr_op_unary( OP_FUNCTION, pL )
|
|
{
|
|
pName = "";
|
|
};
|
|
|
|
expr_fn::expr_fn(
|
|
expr_node *pL, char *pN ) : expr_op_unary( OP_FUNCTION, pL )
|
|
{
|
|
pName = pN;
|
|
};
|
|
|
|
expr_fn::~expr_fn()
|
|
{
|
|
delete pLeft;
|
|
delete pName;
|
|
};
|
|
|
|
expr_init_list::expr_init_list( expr_node * pE )
|
|
{
|
|
pSibling = pChild
|
|
= (class expr_init_list *)pTerminator;
|
|
pExpr = pE;
|
|
NodeNum = 0;
|
|
Constant();
|
|
};
|
|
|
|
|
|
expr_init_list::~expr_init_list()
|
|
{
|
|
if( pSibling )
|
|
delete pSibling;
|
|
if( pChild )
|
|
delete pChild;
|
|
if( pExpr )
|
|
delete pExpr;
|
|
};
|
|
|
|
expr_terminator::expr_terminator() : expr_init_list( (expr_node *)NULL )
|
|
{
|
|
};
|
|
|
|
/**
|
|
** This routine attempts to recreate the string to be eaten by c compilers.
|
|
** If the user specified a string with a quote inside, substitute with an
|
|
** escape character. The new string with possible escapes will ALWAYS be
|
|
** smaller than the older one, so allocating the same amount of space is
|
|
** enough.
|
|
**/
|
|
|
|
char *
|
|
MakeNewStringWithProperQuoting(
|
|
char * pSrc )
|
|
{
|
|
char * pResult = new char [ strlen( pSrc ) + 1];
|
|
char ch;
|
|
char * pDest = pResult;
|
|
|
|
while( ch = *pSrc++ )
|
|
{
|
|
|
|
*pDest = ch;
|
|
|
|
if( ch == '\\')
|
|
{
|
|
if( ch = *pSrc++ )
|
|
{
|
|
if( (ch == '"') || ( ch == '\\') )
|
|
{
|
|
*pDest = ch;
|
|
}
|
|
else
|
|
{
|
|
*pDest++ = '\\';
|
|
*pDest = ch;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
pDest++;
|
|
}
|
|
*pDest = '\0';
|
|
return pResult;
|
|
}
|
|
|
|
#if 0
|
|
char *
|
|
MakeNewStringWithProperQuoting(
|
|
char * pSrc )
|
|
{
|
|
|
|
return pSrc;
|
|
|
|
#if 0
|
|
int SizeIncrForEscapedChars = 0;
|
|
char * pTemp = pSrc;
|
|
short ch;
|
|
|
|
while( ch = *pTemp++ )
|
|
{
|
|
SizeIncrForEscapedChars += SizeIncrIfSpecialChar( (int )ch );
|
|
}
|
|
|
|
if( SizeIncrForEscapedChars != 0 )
|
|
{
|
|
|
|
char * pDest = pTemp =
|
|
new char [ strlen( pSrc ) + SizeIncrForEscapedChars + 1 ];
|
|
|
|
while( (ch = *pSrc++ ) )
|
|
{
|
|
char firstchar;
|
|
char nextchar;
|
|
char thirdchar;
|
|
char fourthchar;
|
|
|
|
TranslateSpecialCharacter( (int)ch, &firstchar, &nextchar, &thirdchar, &fourthchar );
|
|
*pDest++ = firstchar;
|
|
if( nextchar != 0 ) *pDest++ = nextchar;
|
|
if( thirdchar != 0 ) *pDest++ = thirdchar;
|
|
if( fourthchar != 0 ) *pDest++ = fourthchar;
|
|
}
|
|
|
|
pSrc = pTemp;
|
|
*pDest = '\0';
|
|
|
|
}
|
|
|
|
return pSrc;
|
|
#endif // 0
|
|
}
|
|
#endif // 0
|
|
|
|
void
|
|
MakeHexChar(
|
|
unsigned short ch,
|
|
char * p1,
|
|
char * p2 )
|
|
{
|
|
unsigned short chT = ((ch >> 4) & 0x0f);
|
|
|
|
chT = ((chT >= 0x0) && (chT <= 0x9)) ? ( chT + '0' ) : (chT - 0xa) + 'A';
|
|
*p1 = (unsigned char )chT;
|
|
|
|
chT = ch & 0xf;
|
|
|
|
chT = ((chT >= 0x0) && (chT <= 0x9)) ? ( chT + '0' ) : (chT - 0xa) + 'A';
|
|
*p2 = (unsigned char)chT;
|
|
}
|
|
|
|
/** determine the size increment that will happen, if this is a special
|
|
** char needing to be printed.
|
|
**/
|
|
short
|
|
SizeIncrIfSpecialChar(
|
|
int ch )
|
|
{
|
|
short SizeIncr = 0;
|
|
|
|
if( !isascii( ch ) || !isprint( ch ) || (ch == '\'') || (ch == '\\') || (ch == '\"') )
|
|
{
|
|
if( (ch == '"') ||
|
|
(ch == '\\') ||
|
|
(ch == '\n') ||
|
|
(ch == '\t') ||
|
|
(ch == '\v') ||
|
|
(ch == '\b') ||
|
|
(ch == '\r') ||
|
|
(ch == '\f') ||
|
|
(ch == '\'') ||
|
|
(ch == '\\') ||
|
|
(ch == '\"') ||
|
|
(ch == '\a') ||
|
|
(ch == '\0'))
|
|
{
|
|
SizeIncr++;
|
|
}
|
|
else
|
|
{
|
|
|
|
// this is when chars need to be reproduced as hex values
|
|
|
|
SizeIncr += 3;
|
|
|
|
}
|
|
}
|
|
return SizeIncr;
|
|
}
|
|
|
|
void
|
|
TranslateSpecialCharacter(
|
|
int ch,
|
|
char * pFirstChar,
|
|
char * pNextChar,
|
|
char * pThirdChar,
|
|
char * pFourthChar )
|
|
{
|
|
*pFirstChar = *pNextChar = *pThirdChar = *pFourthChar = '\0';
|
|
|
|
if( !isascii( ch ) || !isprint( ch ) || (ch == '\'') || (ch == '"') || (ch == '\\') )
|
|
{
|
|
*pFirstChar = '\\';
|
|
|
|
if( ch == '\n') *pNextChar = 'n';
|
|
else if( ch == '\t') *pNextChar = 't';
|
|
else if( ch == '\v') *pNextChar = 'v';
|
|
else if( ch == '\b') *pNextChar = 'b';
|
|
else if( ch == '\r') *pNextChar = 'r';
|
|
else if( ch == '\f') *pNextChar = 'f';
|
|
else if( ch == '\a') *pNextChar = 'a';
|
|
else if( ch == '\'') *pNextChar = '\'';
|
|
else if( ch == '\"') *pNextChar = '\"';
|
|
else if( ch == '\\') *pNextChar = '\\';
|
|
else if( ch == '\0') *pNextChar = '0';
|
|
else
|
|
{
|
|
|
|
// this is when chars need to be reproduced as hex values
|
|
|
|
*pNextChar = 'x';
|
|
|
|
MakeHexChar( ch, pThirdChar, pFourthChar );
|
|
|
|
}
|
|
}
|
|
else
|
|
*pFirstChar = (char) ch;
|
|
}
|