windows-nt/Source/XPSP1/NT/com/rpc/midl/expr/makexpr.cxx
2020-09-26 16:20:57 +08:00

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;
}