504 lines
12 KiB
C++
504 lines
12 KiB
C++
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
Copyright (c) 1989-1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
makexpr.cxx
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file contains specialized routines for creating complex expressions
|
||
|
from the basic expressions.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
|
||
|
History:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
|
||
|
#pragma warning ( disable : 4514 )
|
||
|
|
||
|
/****************************************************************************
|
||
|
* include files
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "nulldefs.h"
|
||
|
extern "C"
|
||
|
{
|
||
|
#include <stdio.h>
|
||
|
|
||
|
}
|
||
|
#include "makexpr.hxx"
|
||
|
#include "gramutil.hxx"
|
||
|
|
||
|
/****************************************************************************
|
||
|
* local definitions
|
||
|
***************************************************************************/
|
||
|
/****************************************************************************
|
||
|
* local data
|
||
|
***************************************************************************/
|
||
|
|
||
|
/****************************************************************************
|
||
|
* externs
|
||
|
***************************************************************************/
|
||
|
/****************************************************************************/
|
||
|
|
||
|
expr_node *
|
||
|
MakeReferentExpressionIfNecessary(
|
||
|
expr_node * pExpr )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Create a reference expression out of this expression.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pExpr - The input expression for making another reference expr.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The final generated expression.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
If the input expression is a simple variable, make a &(variable) expression
|
||
|
out of it. If it is already a pointer, return the same expression.
|
||
|
|
||
|
The method is implemented for this situation: I have an expression with me,
|
||
|
I dont really want to know if it is a pointer or not. I just know that this
|
||
|
expression represents the final data location for me to unmarshall into or
|
||
|
marshall from. Given that , generate an expression that will effectively
|
||
|
point to this piece of data. So if it is already a pointer, just return the
|
||
|
same expression, if it is a variable, return the address of this variable,
|
||
|
if it is already a pointer, just dont do anything.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
node_skl * pNode = pExpr->GetType();
|
||
|
NODE_T NT = pExpr->GetType()->NodeKind();
|
||
|
|
||
|
if( (NT == NODE_PARAM) || (NT == NODE_ID) || (NT == NODE_FIELD) )
|
||
|
{
|
||
|
pNode = pNode->GetBasicType();
|
||
|
NT = pNode->NodeKind();
|
||
|
}
|
||
|
|
||
|
if( IS_BASE_TYPE_NODE( NT ) )
|
||
|
{
|
||
|
return MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
}
|
||
|
|
||
|
switch( NT )
|
||
|
{
|
||
|
default:
|
||
|
MIDL_ASSERT( FALSE );
|
||
|
|
||
|
case NODE_POINTER:
|
||
|
return pExpr;
|
||
|
}
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeDereferentExpressionIfNecessary(
|
||
|
expr_node * pExpr )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Create a de-reference expression out of this expression.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pExpr - The input expression for making another de-reference expr.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The final generated expression.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
If the input expression is a simple variable, return just that.
|
||
|
If it is already a pointer, return a deref expression.
|
||
|
|
||
|
The method is implemented for this situation: I have an expression with me,
|
||
|
I dont really want to know if it is a variable or not. I just know that this
|
||
|
expression represents the final data address for me to unmarshall into or
|
||
|
marshall from. Given that , generate an expression that will effectively
|
||
|
be a dereference of this piece of data. So if it is already a variable,
|
||
|
just return the same expression, if it is a pointer, return the deref of
|
||
|
this expression.
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
expr_node * pENew;
|
||
|
node_skl * pNode = pExpr->GetType();
|
||
|
NODE_T NT = pNode->NodeKind();
|
||
|
|
||
|
if( (NT == NODE_PARAM) || (NT == NODE_FIELD) || (NT == NODE_ID) )
|
||
|
{
|
||
|
pNode = pNode->GetBasicType();
|
||
|
NT = pNode->NodeKind();
|
||
|
}
|
||
|
|
||
|
if( IS_BASE_TYPE_NODE( NT ) )
|
||
|
{
|
||
|
return pExpr;
|
||
|
}
|
||
|
|
||
|
switch( NT )
|
||
|
{
|
||
|
default:
|
||
|
// MIDL_ASSERT( FALSE );
|
||
|
case NODE_POINTER:
|
||
|
pENew = new expr_u_deref( pExpr );
|
||
|
pENew->SetType( pNode->GetBasicType() );
|
||
|
return pENew;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
expr_node *
|
||
|
MakeAddressExpressionNoMatterWhat(
|
||
|
expr_node * pExpr )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Make an address expression out of this one, ie generate &(expr).
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pExpr - A pointer to the expression to manipulate.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The final expression.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
expr_node * pENew = (expr_node *) new expr_u_address( pExpr );
|
||
|
node_skl * pNode = new node_pointer();
|
||
|
pNode->SetBasicType( pExpr->GetType() );
|
||
|
pNode->SetEdgeType( EDGE_USE );
|
||
|
pENew->SetType( pNode );
|
||
|
return pENew;
|
||
|
}
|
||
|
|
||
|
expr_node *
|
||
|
MakeDerefExpressionOfCastPtrToType(
|
||
|
node_skl * pType,
|
||
|
expr_node * pExpr )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Make an deref expression of a pointer cast to the type.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pType - The type to cast to.
|
||
|
pExpr - A pointer to the expression to manipulate.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The final expression.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
node_skl * pPtr = new node_pointer();
|
||
|
|
||
|
pPtr->SetBasicType( pType );
|
||
|
pPtr->SetEdgeType( EDGE_USE );
|
||
|
|
||
|
pExpr = new expr_cast( pPtr, pExpr );
|
||
|
pExpr = new expr_u_deref( pExpr );
|
||
|
pExpr->SetType( pType );
|
||
|
|
||
|
return pExpr;
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeExpressionOfCastPtrToType(
|
||
|
node_skl * pType,
|
||
|
expr_node * pExpr )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Make an expression of a pointer cast to the type.
|
||
|
(type *) expr
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pType - The type to cast to.
|
||
|
pExpr - A pointer to the expression to manipulate.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The final expression.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
node_skl * pPtr = new node_pointer();
|
||
|
|
||
|
pPtr->SetBasicType( pType );
|
||
|
pPtr->SetEdgeType( EDGE_USE );
|
||
|
|
||
|
pExpr = new expr_cast( pPtr, pExpr );
|
||
|
|
||
|
return pExpr;
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeExpressionOfCastToTypeName(
|
||
|
PNAME pName,
|
||
|
expr_node * pExpr )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Make an expression of a cast to the type whose name is specified.
|
||
|
(name) expr
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pName - The type name to cast to.
|
||
|
pExpr - A pointer to the expression to manipulate.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The final expression.
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
node_skl * pDef = new node_def( (char *)pName );
|
||
|
|
||
|
pDef->SetBasicType( 0 );
|
||
|
pDef->SetEdgeType( EDGE_USE );
|
||
|
|
||
|
pExpr = new expr_cast( pDef, pExpr );
|
||
|
|
||
|
return pExpr;
|
||
|
}
|
||
|
|
||
|
expr_proc_call *
|
||
|
MakeProcCallOutOfParamExprList(
|
||
|
PNAME pName,
|
||
|
node_skl * pType,
|
||
|
ITERATOR& ParamExprList )
|
||
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Make a procedure call expression given a list of param expressions.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pName - The name of the procedure.
|
||
|
pType - The return type of the procedure.
|
||
|
ParamExprList - The list of expressions (sans the expr_param nodes)
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
----------------------------------------------------------------------------*/
|
||
|
{
|
||
|
expr_node * pExpr = 0;
|
||
|
expr_proc_call * pProc = new expr_proc_call( pName );
|
||
|
|
||
|
pProc->SetType( pType );
|
||
|
|
||
|
if( ITERATOR_GETCOUNT( ParamExprList ) )
|
||
|
{
|
||
|
while( ITERATOR_GETNEXT( ParamExprList, pExpr ) )
|
||
|
{
|
||
|
pProc->SetParam( new expr_param( pExpr ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pProc;
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeRefExprOutOfDeref(
|
||
|
expr_node * pExpr )
|
||
|
{
|
||
|
|
||
|
if( pExpr->GetOperator() == OP_UNARY_INDIRECTION )
|
||
|
{
|
||
|
return pExpr->GetLeft();
|
||
|
}
|
||
|
return pExpr;
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeAddressOfPointer(
|
||
|
expr_node * pExpr )
|
||
|
{
|
||
|
if( pExpr->GetOperator() == OP_UNARY_INDIRECTION )
|
||
|
{
|
||
|
return pExpr->GetLeft();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return MakeAddressExpressionNoMatterWhat( pExpr );
|
||
|
}
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeCastExprPtrToUChar(
|
||
|
expr_node * pExpr )
|
||
|
{
|
||
|
node_skl * pType;
|
||
|
node_skl * pP;
|
||
|
|
||
|
GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_CHAR, TYPE_INT );
|
||
|
pP = new node_pointer();
|
||
|
pP->SetBasicType( pType );
|
||
|
pP->SetEdgeType( EDGE_USE );
|
||
|
return new expr_cast( pP, pExpr );
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeCastExprPtrToPtrToUChar(
|
||
|
expr_node * pExpr )
|
||
|
{
|
||
|
node_skl * pType;
|
||
|
node_skl * pP;
|
||
|
node_skl * pP1;
|
||
|
|
||
|
GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_CHAR, TYPE_INT );
|
||
|
pP = new node_pointer();
|
||
|
pP->SetBasicType( pType );
|
||
|
pP->SetEdgeType( EDGE_USE );
|
||
|
pP1 = new node_pointer();
|
||
|
pP1->SetBasicType( pP );
|
||
|
pP1->SetEdgeType( EDGE_USE );
|
||
|
return new expr_cast( pP1, pExpr );
|
||
|
}
|
||
|
expr_node *
|
||
|
MakeCastExprPtrToVoid(
|
||
|
expr_node * pExpr )
|
||
|
{
|
||
|
node_skl * pType;
|
||
|
node_skl * pP;
|
||
|
|
||
|
GetBaseTypeNode( &pType, SIGN_UNDEF, SIZE_UNDEF, TYPE_VOID );
|
||
|
pP = new node_pointer();
|
||
|
pP->SetBasicType( pType );
|
||
|
pP->SetEdgeType( EDGE_USE );
|
||
|
return new expr_cast( pP, pExpr );
|
||
|
}
|
||
|
void
|
||
|
SetPrefixes(
|
||
|
ITERATOR& VarList,
|
||
|
char * pPrefix,
|
||
|
expr_node * pTarget )
|
||
|
{
|
||
|
short Count;
|
||
|
|
||
|
ITERATOR_INIT(VarList);
|
||
|
|
||
|
for( Count = pTarget->MakeListOfVars( VarList),
|
||
|
ITERATOR_INIT( VarList) ;
|
||
|
Count > 0 ;
|
||
|
Count-- )
|
||
|
{
|
||
|
expr_variable * pE = 0;
|
||
|
|
||
|
ITERATOR_GETNEXT( VarList, pE );
|
||
|
pE->SetPrefix( pPrefix );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
void
|
||
|
ResetPrefixes(
|
||
|
ITERATOR& VarList,
|
||
|
expr_node * pTarget )
|
||
|
{
|
||
|
short Count;
|
||
|
|
||
|
ITERATOR_INIT(VarList);
|
||
|
|
||
|
for( Count = pTarget->MakeListOfVars( VarList),
|
||
|
ITERATOR_INIT( VarList) ;
|
||
|
Count > 0 ;
|
||
|
Count-- )
|
||
|
{
|
||
|
expr_variable * pE = 0;
|
||
|
|
||
|
ITERATOR_GETNEXT( VarList, pE );
|
||
|
pE->SetPrefix( 0 );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
expr_node *
|
||
|
Make_1_ArrayExpressionFromVarName(
|
||
|
PNAME pName,
|
||
|
int Dimension )
|
||
|
{
|
||
|
expr_variable * pEV = new expr_variable( pName, 0 );
|
||
|
expr_index * pIV = new expr_index( pEV,
|
||
|
new expr_constant( (long) Dimension)
|
||
|
);
|
||
|
return pIV;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// This method combines all expressions in the list wiht logical ANDs. There is
|
||
|
// guaranteed to be at least 1 member in the list.
|
||
|
|
||
|
expr_node *
|
||
|
CombineIntoLogicalAndExpr(
|
||
|
ITERATOR& List )
|
||
|
{
|
||
|
expr_node * pExpr = 0;
|
||
|
expr_node * pExpr1 = 0;
|
||
|
|
||
|
ITERATOR_INIT( List );
|
||
|
|
||
|
ITERATOR_GETNEXT( List, pExpr );
|
||
|
|
||
|
while( ITERATOR_GETNEXT( List, pExpr1 ) )
|
||
|
{
|
||
|
pExpr = new expr_op_binary( OP_LOGICAL_AND, pExpr, pExpr1 );
|
||
|
}
|
||
|
|
||
|
return pExpr;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************
|
||
|
We need to generate an expression to check that any pointers that
|
||
|
are used in the expression are non-null, otherwise we will end
|
||
|
up generating a deref of those pointers and GP fault.
|
||
|
|
||
|
For example, a length_is expression of *pLengthIs should generate
|
||
|
code like so:
|
||
|
_StubMsg.ActualCount = (pLengthIs) ? *pLengthIs : 0;
|
||
|
|
||
|
Return the same expression if there is no pointer deref in the expr.
|
||
|
*******************************************************************/
|
||
|
expr_node *
|
||
|
MakeAttrExprWithNullPtrChecks(
|
||
|
expr_node * pAttrExpr )
|
||
|
{
|
||
|
ITERATOR List;
|
||
|
|
||
|
if( pAttrExpr->MakeListOfDerefedVars( List ) )
|
||
|
{
|
||
|
expr_node * pExpr;
|
||
|
|
||
|
// There is at least 1 deref expression here.
|
||
|
|
||
|
pExpr = CombineIntoLogicalAndExpr( List );
|
||
|
pAttrExpr = new expr_ternary( OP_QM,
|
||
|
pExpr,
|
||
|
pAttrExpr,
|
||
|
new expr_constant( 0L ) );
|
||
|
}
|
||
|
return pAttrExpr;
|
||
|
}
|