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

360 lines
9.4 KiB
C++

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
walkctxt.cxx
Abstract:
typegraph walk context block routines
Notes:
Author:
GregJen Oct-27-1993 Created.
Notes:
----------------------------------------------------------------------------*/
#pragma warning ( disable : 4514 4706 )
/****************************************************************************
* include files
***************************************************************************/
#include "allnodes.hxx"
#include "walkctxt.hxx"
#include "cmdana.hxx"
#include "semantic.hxx"
#include "control.hxx"
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
extern ATTR_SUMMARY FieldAttrs;
extern CMD_ARG * pCommand;
extern ccontrol * pCompiler;
extern ATTR_SUMMARY RedundantsOk;
/****************************************************************************
* definitions
***************************************************************************/
// Extract a single attribute from the attribute list (and remove from
// summary).
node_base_attr *
ATTR_ITERATOR::GetAttribute( ATTR_T Attr )
{
return AllAttrs[ Attr ];
}
// Extract a single attribute from the attribute list (and remove from
// summary).
node_base_attr *
ATTR_ITERATOR::ExtractAttribute( ATTR_T Attr )
{
node_base_attr * pResult = AllAttrs[ Attr ];
if ( !pResult )
{
return pResult;
}
// if there were extras of a redundant attr, get the next one from the list
if ( ( Attr <= REDUNDANT_ATTR_END ) && RedundantAttrExtras[ Attr ].NonNull() )
{
RedundantAttrExtras[ Attr ].GetCurrent( (void **)&AllAttrs[Attr] );
RedundantAttrExtras[ Attr ].RemoveHead();
}
else // no more of this attribute
{
AllAttrs[Attr] = NULL;
RESET_ATTR( Summary, Attr );
}
return pResult;
}
void
ATTR_ITERATOR::ExtractFieldAttributes( FIELD_ATTR_INFO * FACtxt )
{
node_base_attr * pAttrNode;
expr_node * pExpr;
if ( pAttrNode = ExtractAttribute( ATTR_FIRST ) )
{
pExpr = pAttrNode->GetExpr();
if ( pExpr )
FACtxt->SetFirstIs( pExpr );
}
if ( pAttrNode = ExtractAttribute( ATTR_LAST ) )
{
pExpr = pAttrNode->GetExpr();
if ( pExpr )
FACtxt->SetLastIs( pExpr );
}
if ( pAttrNode = ExtractAttribute( ATTR_LENGTH ) )
{
pExpr = pAttrNode->GetExpr();
if ( pExpr )
FACtxt->SetLengthIs( pExpr );
}
if ( pAttrNode = ExtractAttribute( ATTR_MIN ) )
{
pExpr = pAttrNode->GetExpr();
if ( pExpr )
FACtxt->SetMinIs( pExpr );
}
if ( pAttrNode = ExtractAttribute( ATTR_MAX ) )
{
pExpr = pAttrNode->GetExpr();
if ( pExpr )
FACtxt->SetMaxIs( pExpr );
}
if ( pAttrNode = ExtractAttribute( ATTR_SIZE ) )
{
pExpr = pAttrNode->GetExpr();
if ( pExpr )
FACtxt->SetSizeIs( pExpr );
}
// pass iid_is and string attrs on to child
if ( (FACtxt->Control & FA_CHILD_IS_ARRAY_OR_PTR) == 0 )
{
if ( pAttrNode = ExtractAttribute( ATTR_IID_IS ) )
{
FACtxt->SetIIDIs( pAttrNode->GetExpr() );
}
if ( pAttrNode = ExtractAttribute( ATTR_STRING ) )
{
FACtxt->SetString();
}
if ( pAttrNode = ExtractAttribute( ATTR_BSTRING ) )
{
FACtxt->SetBString();
}
}
}
// this routine searches up the context stack looking for a
// matching node
WALK_CTXT *
WALK_CTXT::FindAncestorContext( NODE_T Kind )
{
WALK_CTXT * pCur = this;
while ( pCur )
{
if ( (pCur->GetParent())->NodeKind() == Kind )
return pCur;
pCur = pCur->GetParentContext();
}
return NULL;
}
// this routine searches up the context stack looking for a
// matching node
WALK_CTXT *
WALK_CTXT::FindRecursiveContext( node_skl * self )
{
WALK_CTXT * pCur = this;
while ( pCur )
{
if ( pCur->GetParent() == self )
return pCur;
pCur = pCur->GetParentContext();
}
return NULL;
}
// this routine searches up the context stack looking for a
// node other than a typedef
WALK_CTXT *
WALK_CTXT::FindNonDefAncestorContext( )
{
WALK_CTXT * pCur = this->GetParentContext();
while ( pCur )
{
if ( (pCur->GetParent())->NodeKind() != NODE_DEF )
return pCur;
pCur = pCur->GetParentContext();
}
return NULL;
}
// for my context, find the appropriate pointer kind ( and extract it if needed )
PTRTYPE
WALK_CTXT::GetPtrKind( BOOL * pfExplicitPtrAttr )
{
PTRTYPE PtrKind = PTR_UNKNOWN;
node_ptr_attr * pPtrAttr;
node_interface * pIntf;
BOOL fMsExt = pCommand->IsSwitchDefined( SWITCH_MS_EXT );
WALK_CTXT * pImportantCtxt = ( fMsExt ) ? FindNonDefAncestorContext() :
GetParentContext();
BOOL fBelowParam = (pImportantCtxt->GetParent()->NodeKind())
== NODE_PARAM;
node_interface * pItsIntf = GetParent()->GetMyInterfaceNode();
////////////////////////////////////////////////////////////////////////
// process pointer attributes
if ( pfExplicitPtrAttr )
*pfExplicitPtrAttr = FALSE;
if ( FInSummary( ATTR_PTR_KIND ) )
{
pPtrAttr = (node_ptr_attr *) ExtractAttribute( ATTR_PTR_KIND );
PtrKind = pPtrAttr->GetPtrKind();
if ( pfExplicitPtrAttr &&
( PtrKind == PTR_REF || PtrKind == PTR_FULL ) )
{
*pfExplicitPtrAttr = TRUE;
}
}
// top level pointer under param is ref ptr unless explicitly changed
else if ( fBelowParam )
{
PtrKind = PTR_REF;
}
// pointer default on defining interface
else if ( pItsIntf->FInSummary( ATTR_PTR_KIND ) )
{
pPtrAttr = (node_ptr_attr *) pItsIntf->GetAttribute( ATTR_PTR_KIND );
PtrKind = pPtrAttr->GetPtrKind();
}
// pointer default on using interface
else if ( (pIntf=GetInterfaceNode()) ->FInSummary( ATTR_PTR_KIND ) )
{
pPtrAttr = (node_ptr_attr *) pIntf->GetAttribute( ATTR_PTR_KIND );
// semantics verifies that there is exactly one here...
// ...and adds REF if needed
PtrKind = pPtrAttr->GetPtrKind();
}
else // global default -- full for DCE, unique for MS_EXT
{
if ( fMsExt )
{
PtrKind = PTR_UNIQUE;
}
else
{
PtrKind = PTR_FULL;
}
}
return PtrKind;
}
// get all the operation bits (MAYBE, IDEMPOTENT, BROADCAST, etc.
unsigned short
WALK_CTXT::GetOperationBits()
{
unsigned short Bits = 0;
if ( ExtractAttribute( ATTR_MAYBE ))
Bits |= OPERATION_MAYBE;
if ( ExtractAttribute( ATTR_BROADCAST ))
Bits |= OPERATION_BROADCAST;
if ( ExtractAttribute( ATTR_IDEMPOTENT ))
Bits |= OPERATION_IDEMPOTENT;
if ( ExtractAttribute( ATTR_MESSAGE ))
Bits |= OPERATION_MESSAGE;
if ( ExtractAttribute( ATTR_INPUTSYNC ))
Bits |= OPERATION_INPUT_SYNC;
return Bits;
}
// add all the attributes to the attribute list; for duplicates, report the duplicate
void
WALK_CTXT::AddAttributes( named_node * pNode )
{
ATTRLIST MyAttrs;
node_base_attr * pCurAttr;
ATTR_T CurAttrKind;
pNode->GetAttributeList( MyAttrs );
pCurAttr = MyAttrs.GetFirst();
while ( pCurAttr )
{
CurAttrKind = pCurAttr->GetAttrID();
if ( ( pDownAttrList->FInSummary( CurAttrKind ) )
&& ( !IS_ATTR( RedundantsOk , CurAttrKind ) ) )
{
ProcessDuplicates( pCurAttr );
}
else
pDownAttrList->Add( pCurAttr );
pCurAttr = pCurAttr->GetNext();
}
}
void
WALK_CTXT::ProcessDuplicates( node_base_attr * pAttr )
{
if ( pCompiler->GetPassNumber() == SEMANTIC_PASS )
{
STATUS_T errnum = ((pAttr->GetAttrID() > NO_DUPLICATES_END)? REDUNDANT_ATTRIBUTE : DUPLICATE_ATTR);
// it is safe to use SemError on us, since it only uses parts of OUR
// context that are ready, even though this is called during the constructor
if ( pAttr->IsAcfAttr() )
{
AcfError( (acf_attr *)pAttr,
NULL,
*((SEM_ANALYSIS_CTXT *)this),
errnum,
NULL);
}
else
{
char * pAttrName = pAttr->GetNodeNameString();
SemError( NULL, *((SEM_ANALYSIS_CTXT *)this), errnum ,pAttrName);
}
}
}