2239 lines
67 KiB
C++
2239 lines
67 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1989-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ilxlat.cxx
|
|
|
|
Abstract:
|
|
|
|
Intermediate Language translator
|
|
|
|
Notes:
|
|
|
|
|
|
Author:
|
|
|
|
GregJen Jun-11-1993 Created.
|
|
|
|
Notes:
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/****************************************************************************
|
|
* include files
|
|
***************************************************************************/
|
|
|
|
#include "becls.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "ilxlat.hxx"
|
|
#include "ilreg.hxx"
|
|
#include "control.hxx"
|
|
#include "tlgen.hxx"
|
|
|
|
/****************************************************************************
|
|
* local data
|
|
***************************************************************************/
|
|
|
|
// #define trace_cg 1
|
|
|
|
/****************************************************************************
|
|
* externs
|
|
***************************************************************************/
|
|
|
|
extern CMD_ARG * pCommand;
|
|
extern BOOL IsTempName( char *);
|
|
extern ccontrol * pCompiler;
|
|
extern REUSE_DICT * pReUseDict;
|
|
extern SymTable * pBaseSymTbl;
|
|
|
|
/****************************************************************************
|
|
* definitions
|
|
***************************************************************************/
|
|
|
|
|
|
void
|
|
AddToCGFileList( CG_FILE *& pCGList, CG_FILE * pFile )
|
|
{
|
|
if (pFile)
|
|
{
|
|
pFile->SetSibling( pCGList );
|
|
pCGList = pFile;
|
|
}
|
|
}
|
|
|
|
void XLAT_CTXT::InitializeMustAlign( node_skl * pPar )
|
|
{
|
|
if (pPar)
|
|
{
|
|
if (pPar->GetModifiers().IsModifierSet(ATTR_DECLSPEC_ALIGN))
|
|
{
|
|
GetMustAlign() = true;
|
|
GetMemAlign() = __max(GetMemAlign(),
|
|
pPar->GetModifiers().GetDeclspecAlign());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// XLAT_CTXT::~XLAT_CTXT
|
|
//
|
|
// Notes: If the node that created this context didn't remove all
|
|
// the attributes it added, force the issue. This is done
|
|
// mostly because tlb generation short-circuits code
|
|
// generation and tends to leave attributes hanging around.
|
|
// This causes asserts and possibly other problems in random
|
|
// places later on. Also note that a lot of the top-level
|
|
// stuff (interfaces, etc) don't strip much so you get lots
|
|
// of hits with those.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
XLAT_CTXT::~XLAT_CTXT()
|
|
{
|
|
if ( !GetParent() || !GetParent()->HasAttributes() )
|
|
return;
|
|
|
|
named_node *pNode = dynamic_cast<named_node *>(GetParent());
|
|
type_node_list attrs;
|
|
node_base_attr *pAttr;
|
|
|
|
MIDL_ASSERT( NULL != pNode);
|
|
|
|
pNode->GetAttributeList(&attrs);
|
|
|
|
while (ITERATOR_GETNEXT(attrs, pAttr))
|
|
{
|
|
#ifdef DUMP_UNEXTRACTED_ATTRIBUTES
|
|
extern void GetSemContextString(char *, node_skl *, WALK_CTXT *);
|
|
char szContext[1024];
|
|
|
|
GetSemContextString(szContext, pNode, this);
|
|
|
|
fprintf(
|
|
stderr,
|
|
"Unextracted attribute: %s: %s\n",
|
|
pAttr->GetNodeNameString(),
|
|
szContext );
|
|
#endif
|
|
|
|
ExtractAttribute( pAttr->GetAttrID() );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// IsComplexReturn
|
|
//
|
|
// Notes: A complex return value is one that isn't be returned in an
|
|
// ordinary register. structs, unions, and floating point
|
|
// values are complex
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
bool IsComplexReturn(node_skl *node)
|
|
{
|
|
// straight dce doesn't support complex returns in intrepreted mode yet
|
|
|
|
if ( !pCommand->NeedsNDR64Run() )
|
|
return false;
|
|
|
|
node = node->GetNonDefSelf();
|
|
|
|
NODE_T kind = node->NodeKind();
|
|
|
|
if ( NODE_STRUCT == kind
|
|
|| NODE_UNION == kind
|
|
|| NODE_ARRAY == kind
|
|
|| NODE_FLOAT == kind
|
|
|| NODE_DOUBLE == kind
|
|
|| ( NODE_HYPER == kind && pCommand->Is32BitEnv() ) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// REVIEW: NODE_INT64, NODE_LONGLONG
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_file::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_file::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
node_interface * pI = 0;
|
|
CG_CLASS * pcgInterfaceList = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
|
|
CG_PROXY_FILE * pProxyCG = NULL;
|
|
CG_IID_FILE * pIidCG = NULL;
|
|
CG_TYPELIBRARY_FILE * pLibCG = NULL;
|
|
CG_NETMONSTUB_FILE * pNetmonCG = NULL;
|
|
CG_NETMONSTUB_FILE * pNetmonObjCG = NULL;
|
|
|
|
CG_CSTUB_FILE * pCCG = NULL;
|
|
CG_SSTUB_FILE * pSCG = NULL;
|
|
CG_HDR_FILE * pHCG = NULL;
|
|
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_FILE * pCGList = NULL;
|
|
|
|
char * pHdrName = pCommand->GetHeader();
|
|
XLAT_CTXT MyContext(this);
|
|
|
|
BOOL HasObjectInterface = FALSE;
|
|
BOOL HasRemoteProc = FALSE;
|
|
BOOL HasRemoteObjectProc = FALSE;
|
|
BOOL HasDefs = FALSE;
|
|
BOOL HasLibrary = FALSE;
|
|
#ifdef trace_cg
|
|
printf("..node_file,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
// don't process for imported stuff
|
|
if ( ImportLevel > 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// at this point, there should be no more attributes...
|
|
|
|
MIDL_ASSERT( !MyContext.HasAttributes() );
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// compute all the child nodes
|
|
|
|
for(pI = (node_interface *)GetFirstMember();
|
|
pI;
|
|
pI = (node_interface *)pI->GetSibling())
|
|
{
|
|
// build a linked list of CG_INTERFACE and CG_OBJECT_INTERFACE nodes.
|
|
// Notes: pChildCG points to first node. pPrevChildCG points to last node.
|
|
|
|
MyContext.SetInterfaceContext( &MyContext );
|
|
pcgInterfaceList = pI->ILxlate( &MyContext );
|
|
if(pcgInterfaceList)
|
|
{
|
|
if (pPrevChildCG)
|
|
{
|
|
pPrevChildCG->SetSibling( pcgInterfaceList );
|
|
}
|
|
else
|
|
{
|
|
pChildCG = pcgInterfaceList;
|
|
}
|
|
pPrevChildCG = pcgInterfaceList;
|
|
// advance to the end of the list (skipping inherited interfaces)
|
|
while ( pPrevChildCG->GetSibling() )
|
|
pPrevChildCG = pPrevChildCG->GetSibling();
|
|
|
|
switch(pPrevChildCG->GetCGID())
|
|
{
|
|
case ID_CG_INTERFACE:
|
|
//Check for a remote procedure.
|
|
if(pPrevChildCG->GetChild())
|
|
HasRemoteProc = TRUE;
|
|
HasDefs = TRUE;
|
|
break;
|
|
case ID_CG_OBJECT_INTERFACE:
|
|
case ID_CG_INHERITED_OBJECT_INTERFACE:
|
|
HasDefs = TRUE;
|
|
HasObjectInterface = TRUE;
|
|
|
|
//Check for a remote object procedure or base interface
|
|
if( pPrevChildCG->GetChild() ||
|
|
((CG_OBJECT_INTERFACE *)pPrevChildCG)->GetBaseInterfaceCG() )
|
|
HasRemoteObjectProc = TRUE;
|
|
break;
|
|
case ID_CG_LIBRARY:
|
|
HasLibrary = TRUE;
|
|
if( pCommand->IsSwitchDefined( SWITCH_HEADER ) )
|
|
HasDefs = TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// process the server and client stubs
|
|
|
|
// make the list of imported files
|
|
|
|
ITERATOR * pFileList = new ITERATOR;
|
|
named_node * pCur;
|
|
|
|
// make a list of the file nodes included directly by the main file
|
|
|
|
// start with the first child of our parent
|
|
pCur = (named_node *)
|
|
((node_source *) pContext->GetParent())
|
|
->GetFirstMember();
|
|
|
|
while ( pCur )
|
|
{
|
|
if ( ( pCur->NodeKind() == NODE_FILE ) &&
|
|
( ( (node_file *) pCur )->GetImportLevel() == 1 ) )
|
|
{
|
|
// add all the files imported at lex level 1
|
|
ITERATOR_INSERT( (*pFileList), ((void *) pCur) );
|
|
}
|
|
pCur = pCur->GetSibling();
|
|
}
|
|
|
|
ITERATOR_INIT( (*pFileList) );
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// manufacture the header file node
|
|
|
|
if ( HasDefs )
|
|
{
|
|
pHCG = new CG_HDR_FILE( this,
|
|
pHdrName,
|
|
pFileList);
|
|
|
|
pHCG->SetChild( pChildCG );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// manufacture the CG_SSTUB_FILE
|
|
|
|
// if the IDL file contains at least one remotable function in a
|
|
// non-object interface, then generate a server stub file.
|
|
//
|
|
|
|
if ( HasRemoteProc &&
|
|
(pChildCG != NULL) ) // if server stub desired
|
|
{
|
|
pSCG = new CG_SSTUB_FILE(
|
|
this,
|
|
( pCommand->GenerateSStub() ) ?
|
|
pCommand->GetSstubFName():
|
|
NULL,
|
|
pHdrName
|
|
);
|
|
|
|
// plug in the child subtree and add the sstub to the head of the list
|
|
pSCG->SetChild( pChildCG );
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// manufacture the CG_CSTUB_FILE
|
|
|
|
// if the IDL file contains at least one remotable function in a
|
|
// non-object interface, then generate a client stub file.
|
|
|
|
if ( HasRemoteProc &&
|
|
(pChildCG != NULL) ) // if client stub desired
|
|
{
|
|
pCCG = new CG_CSTUB_FILE(
|
|
this,
|
|
( pCommand->GenerateCStub() ) ?
|
|
pCommand->GetCstubFName():
|
|
NULL,
|
|
pHdrName
|
|
);
|
|
|
|
pCCG->SetChild( pChildCG );
|
|
|
|
}
|
|
|
|
// If the IDL file contains at least one remotable function in an
|
|
// object interface, then generate a proxy file.
|
|
if ( HasRemoteObjectProc &&
|
|
(pChildCG != NULL) ) // if proxy file desired
|
|
{
|
|
pProxyCG = new CG_PROXY_FILE(
|
|
this,
|
|
( pCommand->GenerateProxy() ) ?
|
|
pCommand->GetProxyFName():
|
|
NULL,
|
|
pHdrName
|
|
);
|
|
|
|
pProxyCG->SetChild( pChildCG );
|
|
|
|
}
|
|
|
|
|
|
// If the IDL file contains at least one object interface,
|
|
// then generate an IID file.
|
|
if ( (HasObjectInterface || (HasLibrary && HasDefs) )&&
|
|
(pChildCG != NULL) ) // if IID file desired
|
|
{
|
|
pIidCG = new CG_IID_FILE(
|
|
this,
|
|
( pCommand->GenerateIID() ) ?
|
|
pCommand->GetIIDFName():
|
|
NULL);
|
|
|
|
pIidCG->SetChild( pChildCG );
|
|
}
|
|
|
|
// If the IDL file contains a library then gnerate a TYPELIBRARY_FILE
|
|
if (HasLibrary && (NULL != pChildCG) )
|
|
{
|
|
#ifdef _WIN64
|
|
bool fGenTypeLib = pCommand->Is64BitEnv() || ( pCommand->Is32BitEnv() && pCommand->IsSwitchDefined( SWITCH_ENV ) );
|
|
#else
|
|
bool fGenTypeLib = pCommand->Is32BitEnv() || ( pCommand->Is64BitEnv() && pCommand->IsSwitchDefined( SWITCH_ENV ) );
|
|
#endif
|
|
|
|
if ( fGenTypeLib && pCommand->GenerateTypeLibrary() )
|
|
{
|
|
pLibCG = new CG_TYPELIBRARY_FILE(
|
|
this,
|
|
pCommand->GetTypeLibraryFName() ) ;
|
|
pLibCG->SetChild( pChildCG );
|
|
}
|
|
}
|
|
|
|
// If the -netmon switch was used, generate the two NETMONSTUB_FILE's
|
|
if ( pCommand->IsNetmonStubGenerationEnabled() )
|
|
{
|
|
if (HasRemoteProc)
|
|
{
|
|
pNetmonCG = new CG_NETMONSTUB_FILE(
|
|
FALSE,
|
|
this,
|
|
pCommand->GetNetmonStubFName());
|
|
|
|
pNetmonCG->SetChild( pChildCG );
|
|
}
|
|
|
|
if (HasRemoteObjectProc)
|
|
{
|
|
pNetmonObjCG = new CG_NETMONSTUB_FILE(
|
|
TRUE,
|
|
this,
|
|
pCommand->GetNetmonStubObjFName());
|
|
pNetmonObjCG->SetChild( pChildCG );
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// glue all the parts together by tacking onto the head of the list.
|
|
// the final order is:
|
|
// CStub - SStub - Proxy - IID - Hdr
|
|
// doesn't need to create Hdr & tlb in ndr64 run.
|
|
pCGList = NULL;
|
|
|
|
AddToCGFileList( pCGList, pNetmonObjCG );
|
|
AddToCGFileList( pCGList, pNetmonCG );
|
|
|
|
if ( !pCommand->Is2ndCodegenRun() )
|
|
AddToCGFileList( pCGList, pHCG );
|
|
|
|
if ( !pCommand->Is2ndCodegenRun() )
|
|
AddToCGFileList( pCGList, pIidCG );
|
|
AddToCGFileList( pCGList, pProxyCG );
|
|
|
|
AddToCGFileList( pCGList, pSCG );
|
|
AddToCGFileList( pCGList, pCCG );
|
|
|
|
if ( !pCommand->Is2ndCodegenRun() )
|
|
AddToCGFileList( pCGList, pLibCG );
|
|
|
|
return pCGList;
|
|
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_implicit::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
// This is a little bit different, since it is not a node_skl...
|
|
// therefore, it will not set up its own context
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_implicit::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
CG_NDR * pCG;
|
|
|
|
if ( pHandleType->NodeKind() == NODE_HANDLE_T )
|
|
{
|
|
pCG = new CG_PRIMITIVE_HANDLE( pHandleType,
|
|
pHandleID,
|
|
*pContext );
|
|
}
|
|
else // assume generic handle
|
|
{
|
|
pCG = new CG_GENERIC_HANDLE( pHandleType,
|
|
pHandleID,
|
|
*pContext );
|
|
}
|
|
#ifdef trace_cg
|
|
printf("..node_implicit,\t\n");
|
|
#endif
|
|
return pCG;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_proc::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_proc::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
MEM_ITER MemIter( this );
|
|
node_param * pN;
|
|
CG_PROC * pCG;
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
CG_CLASS * pFirstChildCG = NULL;
|
|
CG_RETURN * pReturnCG = NULL;
|
|
CG_CLASS * pBinding = NULL;
|
|
CG_CLASS * pBindingParam = NULL;
|
|
BOOL fHasCallback = FALSE;
|
|
BOOL fNoCode = FALSE;
|
|
BOOL fObject;
|
|
BOOL fRetHresult = FALSE;
|
|
BOOL fEnableAllocate;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
unsigned short OpBits = MyContext.GetOperationBits();
|
|
XLAT_CTXT * pIntfCtxt = (XLAT_CTXT *)
|
|
MyContext.GetInterfaceContext();
|
|
node_interface * pIntf = (node_interface *)
|
|
pIntfCtxt->GetParent();
|
|
node_base_attr * pNotify,
|
|
* pNotifyFlag;
|
|
BOOL HasEncode = (NULL !=
|
|
MyContext.ExtractAttribute( ATTR_ENCODE ) );
|
|
BOOL HasDecode = (NULL !=
|
|
MyContext.ExtractAttribute( ATTR_DECODE ) );
|
|
node_call_as * pCallAs = (node_call_as *)
|
|
MyContext.ExtractAttribute( ATTR_CALL_AS );
|
|
bool fLocalProc = MyContext.ExtractAttribute( ATTR_LOCAL ) != 0;
|
|
BOOL fLocal = (BOOL ) fLocalProc ||
|
|
pIntfCtxt->FInSummary( ATTR_LOCAL );
|
|
BOOL fLocalCall = IsCallAsTarget();
|
|
unsigned short SavedProcCount = 0;
|
|
unsigned short SavedCallbackProcCount = 0;
|
|
node_param * pComplexReturn = NULL;
|
|
|
|
|
|
MyContext.ExtractAttribute( ATTR_ENTRY );
|
|
MyContext.ExtractAttribute( ATTR_ID );
|
|
MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
|
|
MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
|
|
MyContext.ExtractAttribute( ATTR_HELPSTRING );
|
|
MyContext.ExtractAttribute( ATTR_IDLDESCATTR );
|
|
MyContext.ExtractAttribute( ATTR_FUNCDESCATTR );
|
|
MyContext.ExtractAttribute( ATTR_HIDDEN );
|
|
MyContext.ExtractAttribute( ATTR_ASYNC );
|
|
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_proc,\t%s\n", GetSymName());
|
|
#endif
|
|
BOOL fSupressHeader = FALSE;
|
|
unsigned long ulOptFlags;
|
|
unsigned long ulStackSize = 0;
|
|
|
|
node_member_attr * pMA;
|
|
while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 );
|
|
|
|
// do my attribute parsing...
|
|
fHasCallback = (NULL != MyContext.ExtractAttribute( ATTR_CALLBACK ) );
|
|
|
|
fObject = (NULL != MyContext.ExtractAttribute( ATTR_OBJECT )) ||
|
|
pIntfCtxt->FInSummary( ATTR_OBJECT );
|
|
|
|
// do my attribute parsing... attributes to ignore here
|
|
|
|
MyContext.ExtractAttribute( ATTR_OPTIMIZE );
|
|
|
|
MyContext.ExtractAttribute( ATTR_EXPLICIT );
|
|
|
|
HasEncode = HasEncode || pIntfCtxt->FInSummary( ATTR_ENCODE );
|
|
HasDecode = HasDecode || pIntfCtxt->FInSummary( ATTR_DECODE );
|
|
|
|
|
|
pNotify = MyContext.ExtractAttribute( ATTR_NOTIFY );
|
|
pNotifyFlag = MyContext.ExtractAttribute( ATTR_NOTIFY_FLAG );
|
|
fEnableAllocate = (NULL != MyContext.ExtractAttribute( ATTR_ENABLE_ALLOCATE ));
|
|
fEnableAllocate = fEnableAllocate ||
|
|
pIntfCtxt->FInSummary( ATTR_ENABLE_ALLOCATE ) ||
|
|
pCommand->IsRpcSSAllocateEnabled();
|
|
|
|
// do my attribute parsing...
|
|
// locally applied [code] attribute overrides global [nocode] attribute
|
|
fNoCode = MyContext.ExtractAttribute( ATTR_NOCODE ) ||
|
|
pIntfCtxt->FInSummary( ATTR_NOCODE );
|
|
fNoCode = !MyContext.ExtractAttribute( ATTR_CODE ) && fNoCode;
|
|
|
|
if ( NULL != MyContext.ExtractAttribute( ATTR_CSTAGRTN ) )
|
|
MyContext.SetAncestorBits( IL_CS_HAS_TAG_RTN );
|
|
|
|
BOOL fImported = FALSE;
|
|
if ( GetDefiningFile() )
|
|
{
|
|
fImported = GetDefiningFile()->GetImportLevel() != 0;
|
|
}
|
|
|
|
if ( fLocalProc && !IsCallAsTarget() && fObject )
|
|
{
|
|
SemError( this, MyContext, LOCAL_NO_CALL_AS, 0 );
|
|
}
|
|
|
|
// determine if the proc is local and
|
|
// determine the proc number (local procs don't bump the number)
|
|
if (fLocalCall || (fLocal && !fObject))
|
|
{
|
|
// return without making anything
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
if ( fHasCallback )
|
|
{
|
|
ProcNum = ( pIntf ->GetCallBackProcCount() )++;
|
|
}
|
|
else
|
|
{
|
|
ProcNum = ( pIntf ->GetProcCount() )++;
|
|
}
|
|
}
|
|
|
|
if ( fLocal && fObject && !MyContext.AnyAncestorBits(IL_IN_LIBRARY) )
|
|
{
|
|
|
|
if ( pIntf->IsValidRootInterface() )
|
|
{
|
|
pCG = new CG_IUNKNOWN_OBJECT_PROC( ProcNum,
|
|
this,
|
|
GetDefiningFile()->GetImportLevel() > 0,
|
|
GetOptimizationFlags(),
|
|
fHasDeny );
|
|
}
|
|
else
|
|
{
|
|
pCG = new CG_LOCAL_OBJECT_PROC( ProcNum,
|
|
this,
|
|
GetDefiningFile()->GetImportLevel() > 0,
|
|
GetOptimizationFlags(),
|
|
fHasDeny );
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
SavedProcCount = pIntf->GetProcCount();
|
|
SavedCallbackProcCount = pIntf->GetCallBackProcCount();
|
|
|
|
// add the return type
|
|
if ( HasReturn() )
|
|
{
|
|
node_skl * pReturnType = GetReturnType();
|
|
CG_CLASS * pRetCG;
|
|
|
|
// If the return value is complex it is treated in ndr as if a ref
|
|
// pointer to the complex type was in the parameter list instead of
|
|
// a true return value. Temporarily add a parameter to the type
|
|
// to get the back-end parameter created.
|
|
|
|
if ( IsComplexReturn( pReturnType ) )
|
|
{
|
|
pComplexReturn = new node_param;
|
|
pComplexReturn->SetSymName( RETURN_VALUE_VAR_NAME );
|
|
pComplexReturn->SetChild( new node_pointer( pReturnType) );
|
|
pComplexReturn->GetChild()->GetModifiers().SetModifier( ATTR_TAGREF );
|
|
pComplexReturn->SetAttribute( new node_base_attr( ATTR_OUT ) );
|
|
|
|
MemIter.AddLastMember( pComplexReturn );
|
|
ITERATOR_INIT( MemIter );
|
|
}
|
|
else
|
|
{
|
|
pRetCG = pReturnType->ILxlate( &MyContext );
|
|
fRetHresult = (BOOL) ( pRetCG->GetCGID() == ID_CG_HRESULT );
|
|
pReturnCG = new CG_RETURN( pReturnType,
|
|
MyContext,
|
|
(unsigned short) RTStatuses );
|
|
pReturnCG->SetChild( pRetCG );
|
|
}
|
|
}
|
|
|
|
// at this point, there should be no more attributes...
|
|
MIDL_ASSERT( !MyContext.HasAttributes() );
|
|
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
if ( MemIter.GetNumberOfArguments() > 0 )
|
|
{
|
|
//
|
|
// for each of the parameters, call the core transformer.
|
|
//
|
|
|
|
while ( ( pN = (node_param *) MemIter.GetNext() ) != 0 )
|
|
{
|
|
// REVIEW: One could argue that hidden status params
|
|
// aren't on the wire so there shouldn't be a CG node
|
|
// for them. The main problem with this is that we
|
|
// need to be able to calculate a stack offset for the
|
|
// hidden param and that can only be done in the
|
|
// back end.
|
|
|
|
// Hidden status params are not really [out] params but the way
|
|
// the -Os generator builds up local resources requires them to
|
|
// be.
|
|
|
|
if ( pN->IsExtraStatusParam()
|
|
&& ! ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
|
|
{
|
|
pN->SetAttribute( ATTR_OUT );
|
|
}
|
|
|
|
pChildCG = pN->ILxlate( &MyContext );
|
|
|
|
#ifdef trace_cg
|
|
printf("back from..node_param %s\n",pN->GetSymName());
|
|
printf("binding is now %08x\n",pBindingParam );
|
|
printf("child is now %08x\n",pChildCG );
|
|
#endif
|
|
|
|
// pChildCG could be NULL if it's imported from .tlb somewhere else already
|
|
if ( pChildCG )
|
|
{
|
|
// the first binding param gets picked up for binding
|
|
if ( !pBindingParam
|
|
&& pN->IsBindingParam() )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("value for IsBindingParam is %08x\n",pN->IsBindingParam() );
|
|
printf("binding found on node_param %s\n",pN->GetSymName());
|
|
printf("binding is now %08x\n",pBindingParam );
|
|
#endif
|
|
pBindingParam = pChildCG;
|
|
}
|
|
|
|
// build up the parameter list
|
|
if( pPrevChildCG )
|
|
{
|
|
pPrevChildCG->SetSibling( pChildCG );
|
|
}
|
|
else
|
|
{
|
|
pFirstChildCG = pChildCG;
|
|
};
|
|
|
|
// this is only a calculated guess. We need more information to make an accurate
|
|
// estimate.
|
|
unsigned long ulSize = ( ( CG_PARAM* ) pChildCG )->GetStackSize();
|
|
ulSize += (8 - (ulSize % 8));
|
|
ulStackSize += ulSize;
|
|
|
|
pPrevChildCG = pChildCG;
|
|
}
|
|
else
|
|
SemError( this, MyContext, FAILED_TO_GENERATE_PARAM, pN->GetSymName() );
|
|
}
|
|
}
|
|
|
|
ulOptFlags = GetOptimizationFlags();
|
|
if ( ( ulOptFlags & OPTIMIZE_INTERPRETER ) &&
|
|
!( ulOptFlags & OPTIMIZE_INTERPRETER_V2 ) &&
|
|
( ulStackSize > INTERPRETER_THUNK_PARAM_SIZE_THRESHOLD ) )
|
|
{
|
|
if ( ForceNonInterpret() )
|
|
{
|
|
SemError( this, *pContext, OI_STACK_SIZE_EXCEEDED, 0 );
|
|
}
|
|
}
|
|
if ( ulOptFlags & OPTIMIZE_INTERPRETER && ulStackSize > INTERPRETER_PROC_STACK_FRAME_SIZE_THRESHOLD )
|
|
{
|
|
if ( ForceNonInterpret() )
|
|
{
|
|
SemError( this, *pContext, STACK_FRAME_SIZE_EXCEEDED, GetSymName() );
|
|
exit ( STACK_FRAME_SIZE_EXCEEDED );
|
|
}
|
|
}
|
|
if (fForcedI2 && fForcedS)
|
|
{
|
|
// ERROR - Can't force it both ways.
|
|
SemError( this, *pContext, CONFLICTING_OPTIMIZATION_REQUIREMENTS, 0 );
|
|
exit ( CONFLICTING_OPTIMIZATION_REQUIREMENTS );
|
|
}
|
|
|
|
|
|
#ifdef trace_cg
|
|
printf("done with param list for %s\n",GetSymName());
|
|
printf("binding is now %08x\n",pBindingParam );
|
|
#endif
|
|
|
|
// get the binding information
|
|
if ( pBindingParam )
|
|
{
|
|
pBinding = pBindingParam;
|
|
|
|
while (! ((CG_NDR *) pBinding)->IsAHandle() )
|
|
pBinding = pBinding->GetChild();
|
|
// pBinding now points to the node for the binding handle
|
|
}
|
|
else // implicit handle or auto handle
|
|
{
|
|
// note: if no implicit handle,
|
|
// then leave pBinding NULL for auto_handle
|
|
if (pIntfCtxt->FInSummary( ATTR_IMPLICIT ) )
|
|
{
|
|
node_implicit * pImplAttr;
|
|
pImplAttr = (node_implicit *) pIntf->GetAttribute( ATTR_IMPLICIT );
|
|
|
|
pBinding = pImplAttr->ILxlate( &MyContext );
|
|
}
|
|
}
|
|
|
|
#ifdef trace_cg
|
|
printf("done with binding for %s",GetSymName());
|
|
printf("binding is now %08x\n",pBinding );
|
|
#endif
|
|
|
|
// see if thunked interpreter needed for server side
|
|
if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER )
|
|
{ // check for non-stdcall
|
|
ATTR_T CallingConv;
|
|
|
|
GetCallingConvention( CallingConv );
|
|
|
|
if ( ( CallingConv != ATTR_STDCALL ) &&
|
|
( CallingConv != ATTR_NONE ) )
|
|
{
|
|
SetOptimizationFlags( unsigned short( GetOptimizationFlags() | OPTIMIZE_THUNKED_INTERPRET ) );
|
|
}
|
|
else if ( pCallAs )
|
|
{
|
|
SetOptimizationFlags( unsigned short( GetOptimizationFlags() | OPTIMIZE_THUNKED_INTERPRET ) );
|
|
}
|
|
else if ( pReturnCG ) // check the return type
|
|
{
|
|
CG_NDR * pRetTypeCG = (CG_NDR *) pReturnCG->GetChild();
|
|
|
|
if ( !pCommand->NeedsNDR64Run()
|
|
&& pRetTypeCG->GetCGID() != ID_CG_CONTEXT_HDL )
|
|
{
|
|
// This check is bogus. First off, it should be checking the
|
|
// memory size, not the wire size. Secondly, for straight dce
|
|
// mode large (i.e. complex) return types are prohibited in
|
|
// semantic analysis. Finally, it should be checking the size
|
|
// against the pointer size, not 4.
|
|
|
|
if ( ( pRetTypeCG->GetWireSize() > 4 ) ||
|
|
( !pRetTypeCG->IsSimpleType() &&
|
|
!pRetTypeCG->IsPointer() ) )
|
|
SetOptimizationFlags( unsigned short( GetOptimizationFlags() | OPTIMIZE_THUNKED_INTERPRET ) );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( fHasCallback )
|
|
{
|
|
pCG = new CG_CALLBACK_PROC(
|
|
ProcNum,
|
|
this,
|
|
(CG_HANDLE *) pBinding,
|
|
(CG_PARAM *) pBindingParam,
|
|
HasAtLeastOneIn(),
|
|
HasAtLeastOneOut(),
|
|
HasAtLeastOneShipped(),
|
|
fHasStatuses,
|
|
fHasFullPointer,
|
|
pReturnCG,
|
|
GetOptimizationFlags(),
|
|
OpBits,
|
|
fHasDeny
|
|
);
|
|
}
|
|
else if ( fObject )
|
|
{
|
|
BOOL fInherited = 0;
|
|
if ( GetDefiningFile() )
|
|
{
|
|
fInherited = GetDefiningFile()->GetImportLevel() > 0;
|
|
}
|
|
if ( fInherited )
|
|
{
|
|
pCG = new CG_INHERITED_OBJECT_PROC(
|
|
ProcNum,
|
|
this,
|
|
(CG_HANDLE *) pBinding,
|
|
(CG_PARAM *) pBindingParam,
|
|
HasAtLeastOneIn(),
|
|
HasAtLeastOneOut(),
|
|
HasAtLeastOneShipped(),
|
|
fHasStatuses,
|
|
fHasFullPointer,
|
|
pReturnCG,
|
|
GetOptimizationFlags(),
|
|
OpBits,
|
|
fHasDeny
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pCG = new CG_OBJECT_PROC(
|
|
ProcNum,
|
|
this,
|
|
(CG_HANDLE *) pBinding,
|
|
(CG_PARAM *) pBindingParam,
|
|
HasAtLeastOneIn(),
|
|
HasAtLeastOneOut(),
|
|
HasAtLeastOneShipped(),
|
|
fHasStatuses,
|
|
fHasFullPointer,
|
|
pReturnCG,
|
|
GetOptimizationFlags(),
|
|
OpBits,
|
|
fHasDeny
|
|
);
|
|
}
|
|
}
|
|
else if ( HasEncode || HasDecode )
|
|
{
|
|
pCG = new CG_ENCODE_PROC(
|
|
ProcNum,
|
|
this,
|
|
(CG_HANDLE *) pBinding,
|
|
(CG_PARAM *) pBindingParam,
|
|
HasAtLeastOneIn(),
|
|
HasAtLeastOneOut(),
|
|
HasAtLeastOneShipped(),
|
|
fHasStatuses,
|
|
fHasFullPointer,
|
|
pReturnCG,
|
|
GetOptimizationFlags(),
|
|
OpBits,
|
|
HasEncode,
|
|
HasDecode,
|
|
fHasDeny
|
|
);
|
|
}
|
|
else
|
|
{
|
|
pCG = new CG_PROC(
|
|
ProcNum,
|
|
this,
|
|
(CG_HANDLE *) pBinding,
|
|
(CG_PARAM *) pBindingParam,
|
|
HasAtLeastOneIn(),
|
|
HasAtLeastOneOut(),
|
|
HasAtLeastOneShipped(),
|
|
fHasStatuses,
|
|
fHasFullPointer,
|
|
pReturnCG,
|
|
GetOptimizationFlags(),
|
|
OpBits,
|
|
fHasDeny
|
|
);
|
|
}
|
|
|
|
pCG->SetChild( pFirstChildCG );
|
|
|
|
#ifdef trace_cg
|
|
printf("....returning from %s\n",GetSymName());
|
|
#endif
|
|
|
|
pIntf->GetProcCount() = SavedProcCount;
|
|
pIntf->GetCallBackProcCount() = SavedCallbackProcCount;
|
|
|
|
done:
|
|
// save a pointer to the interface CG node
|
|
pCG->SetInterfaceNode( (CG_INTERFACE*) pIntf->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) ) );
|
|
|
|
if (fSupressHeader)
|
|
pCG->SetSupressHeader();
|
|
|
|
// mark nocode procs
|
|
if ( fNoCode )
|
|
pCG->SetNoCode();
|
|
|
|
if ( pNotify )
|
|
pCG->SetHasNotify();
|
|
|
|
if ( pNotifyFlag )
|
|
pCG->SetHasNotifyFlag();
|
|
|
|
if ( fEnableAllocate )
|
|
pCG->SetRpcSSSpecified( 1 );
|
|
|
|
if ( fRetHresult )
|
|
pCG->SetReturnsHRESULT();
|
|
|
|
if (HasPipes())
|
|
pCG->SetHasPipes(1);
|
|
|
|
if ( pCallAs )
|
|
pCG->SetCallAsName( pCallAs->GetCallAsName() );
|
|
|
|
if ( HasExtraStatusParam() )
|
|
pCG->SetHasExtraStatusParam();
|
|
|
|
if ( HasAsyncHandle() )
|
|
pCG->SetHasAsyncHandle();
|
|
|
|
if ( HasAsyncUUID() )
|
|
pCG->SetHasAsyncUUID();
|
|
|
|
if ( HasServerCorr() )
|
|
pCG->SetHasServerCorr();
|
|
|
|
if ( HasClientCorr() )
|
|
pCG->SetHasClientCorr();
|
|
|
|
// A fake parameter was added to the type for complex return values.
|
|
// Remove it.
|
|
|
|
if ( pComplexReturn )
|
|
{
|
|
pCG->SetHasComplexReturnType();
|
|
MemIter.RemoveLastMember();
|
|
}
|
|
|
|
pCG->SetCSTagRoutine( GetCSTagRoutine() );
|
|
|
|
// Typelib generation does not remove ATTR_V1_ENUM.
|
|
MyContext.ExtractAttribute( ATTR_V1_ENUM );
|
|
|
|
// at this point, there should be no more attributes...
|
|
MIDL_ASSERT( !MyContext.HasAttributes() );
|
|
|
|
if ( ( pCG->GetOptimizationFlags() & OPTIMIZE_INTERPRETER ) &&
|
|
!( pCG->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) &&
|
|
pCommand->Is64BitEnv() )
|
|
{
|
|
SemError( this, *pContext, NO_OLD_INTERPRETER_64B, GetSymName() );
|
|
exit ( NO_OLD_INTERPRETER_64B );
|
|
}
|
|
|
|
return pCG;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_param::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_param::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
CG_PARAM * pCG;
|
|
CG_CLASS * pChildCG = NULL;
|
|
expr_node * pSwitchExpr = NULL;
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_param,\t%s\n",GetSymName());
|
|
#endif
|
|
|
|
PARAM_DIR_FLAGS F = 0;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
|
|
// make sure all member attributes get processed
|
|
node_member_attr * pMA;
|
|
|
|
MyContext.ExtractAttribute(ATTR_IDLDESCATTR);
|
|
MyContext.ExtractAttribute(ATTR_DEFAULTVALUE);
|
|
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
|
|
|
|
if ( MyContext.ExtractAttribute(ATTR_FLCID) )
|
|
{
|
|
LCID();
|
|
}
|
|
|
|
while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
|
|
{
|
|
switch (pMA->GetAttr())
|
|
{
|
|
case MATTR_RETVAL:
|
|
Retval();
|
|
break;
|
|
case MATTR_OPTIONAL:
|
|
{
|
|
Optional();
|
|
}
|
|
break;
|
|
default:
|
|
char * pAttrName = pMA->GetNodeNameString();
|
|
SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( MyContext.ExtractAttribute( ATTR_IN ) )
|
|
{
|
|
F |= IN_PARAM;
|
|
}
|
|
|
|
if( MyContext.ExtractAttribute( ATTR_OUT ) )
|
|
{
|
|
F |= OUT_PARAM;
|
|
}
|
|
|
|
if ( MyContext.ExtractAttribute( ATTR_PARTIAL_IGNORE ) )
|
|
{
|
|
F |= PARTIAL_IGNORE_PARAM;
|
|
}
|
|
|
|
// default to in
|
|
if ( F == 0 && !IsExtraStatusParam() )
|
|
F |= IN_PARAM;
|
|
|
|
if ( MyContext.FInSummary( ATTR_SWITCH_IS ) )
|
|
{
|
|
node_switch_is * pAttr;
|
|
|
|
if ( pCommand->IsNDR64Run() )
|
|
{
|
|
pAttr = (node_switch_is *) MyContext.GetAttribute( ATTR_SWITCH_IS );
|
|
}
|
|
else
|
|
{
|
|
pAttr = (node_switch_is *) MyContext.ExtractAttribute( ATTR_SWITCH_IS );
|
|
}
|
|
pSwitchExpr = pAttr->GetExpr();
|
|
}
|
|
|
|
BOOL fHasCSSTag = ( NULL != MyContext.ExtractAttribute( ATTR_STAG ) );
|
|
BOOL fHasCSDRTag = ( NULL != MyContext.ExtractAttribute( ATTR_DRTAG ) );
|
|
BOOL fHasCSRTag = ( NULL != MyContext.ExtractAttribute( ATTR_RTAG ) );
|
|
|
|
MyContext.SetAncestorBits(
|
|
( fHasCSSTag ? IL_CS_STAG : 0 )
|
|
| ( fHasCSDRTag ? IL_CS_DRTAG : 0 )
|
|
| ( fHasCSRTag ? IL_CS_RTAG : 0 ) );
|
|
|
|
BOOL HasForceAllocate = ( NULL != MyContext.ExtractAttribute( ATTR_FORCEALLOCATE ) );
|
|
|
|
pChildCG = GetChild()->ILxlate( &MyContext );
|
|
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_param back.. %s\n",GetSymName());
|
|
#endif
|
|
// make sure void parameters get skipped
|
|
if ( !pChildCG )
|
|
return NULL;
|
|
|
|
pCG = new CG_PARAM( this,
|
|
F,
|
|
MyContext,
|
|
pSwitchExpr,
|
|
(unsigned short) Statuses );
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_param ..... %08x child=%08x\n", pCG, pChildCG );
|
|
fflush(stdout);
|
|
#endif
|
|
|
|
if ( IsExtraStatusParam() )
|
|
pCG->SetIsExtraStatusParam();
|
|
|
|
// only set the bit if there was non-toplevel only
|
|
if ( fDontCallFreeInst == 1 )
|
|
pCG->SetDontCallFreeInst( TRUE );
|
|
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_param ........ %08x child=%08x\n", pCG, pChildCG );
|
|
fflush(stdout);
|
|
#endif
|
|
pCG->SetChild( pChildCG );
|
|
|
|
if (IsAsyncHandleParam())
|
|
{
|
|
pCG->SetIsAsyncHandleParam();
|
|
}
|
|
if ( IsSaveForAsyncFinish() )
|
|
{
|
|
pCG->SaveForAsyncFinish();
|
|
}
|
|
|
|
pCG->SetIsCSSTag( fHasCSSTag );
|
|
pCG->SetIsCSDRTag( fHasCSDRTag );
|
|
pCG->SetIsCSRTag( fHasCSRTag );
|
|
|
|
if ( MyContext.AnyAncestorBits( IL_CS_HAS_TAG_RTN ) && pCG->IsSomeCSTag() )
|
|
pCG->SetIsOmittedParam();
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_param return %s\n",GetSymName());
|
|
fflush(stdout);
|
|
#endif
|
|
if ( HasForceAllocate )
|
|
{
|
|
pCG->SetForceAllocate( );
|
|
}
|
|
|
|
|
|
if ( !MyContext.AnyAncestorBits(IL_IN_LIBRARY) )
|
|
{
|
|
SetCG( pCG );
|
|
}
|
|
|
|
// REVIEW: There is no concept of switch_type in a library block.
|
|
// Perhaps issue an error in semantic analysis.
|
|
|
|
if ( MyContext.AnyAncestorBits( IL_IN_LIBRARY )
|
|
&& MyContext.ExtractAttribute( ATTR_SWITCH_TYPE ) )
|
|
{
|
|
SemError(
|
|
this,
|
|
MyContext,
|
|
IGNORE_UNIMPLEMENTED_ATTRIBUTE,
|
|
"[switch_type] in a library block");
|
|
}
|
|
|
|
return pCG;
|
|
}
|
|
|
|
const GUID_STRS DummyGuidStrs( "00000000", "0000", "0000", "0000", "000000000000" );
|
|
|
|
// helper function for adding a new list to the end of the list of children
|
|
inline
|
|
void AddToCGList(
|
|
const CG_CLASS * pCNew,
|
|
CG_CLASS * * ppChild,
|
|
CG_CLASS * * ppLastSibling )
|
|
{
|
|
CG_CLASS * pCurrent;
|
|
CG_CLASS * pNew = (CG_CLASS *) pCNew;
|
|
|
|
// hook the head on
|
|
if ( !*ppChild )
|
|
*ppChild = pNew;
|
|
else
|
|
(*ppLastSibling)->SetSibling( pNew );
|
|
|
|
// advance the last sibling pointer
|
|
*ppLastSibling = pNew;
|
|
while ( ( pCurrent = (*ppLastSibling)->GetSibling() ) != 0 )
|
|
*ppLastSibling = pCurrent;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_interface::ILxlate
|
|
//
|
|
// Notes: This function returns either a CG_INTERFACE or a
|
|
// CG_OBJECT_INTERFACE node.
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_interface::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
CG_NDR * pcgInterface = NULL;
|
|
CG_NDR * pResultCG = NULL;
|
|
CG_CLASS * pCG = NULL;
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
MEM_ITER MemIter( this );
|
|
node_skl * pN;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
XLAT_CTXT ChildContext( MyContext );
|
|
node_guid * pGuid = (node_guid *)
|
|
MyContext.ExtractAttribute( ATTR_GUID );
|
|
GUID_STRS GuidStrs;
|
|
node_implicit * pImpHdl = NULL;
|
|
CG_HANDLE * pImpHdlCG = NULL;
|
|
NODE_T ChildKind;
|
|
BOOL IsPickle = MyContext.FInSummary( ATTR_ENCODE ) ||
|
|
MyContext.FInSummary( ATTR_DECODE );
|
|
BOOL fAllRpcSS = MyContext.FInSummary( ATTR_ENABLE_ALLOCATE ) ||
|
|
pCommand->IsRpcSSAllocateEnabled();
|
|
BOOL fObject = MyContext.FInSummary( ATTR_OBJECT );
|
|
|
|
node_interface * pBaseIntf = GetMyBaseInterface();
|
|
CG_OBJECT_INTERFACE * pBaseCG = NULL;
|
|
CG_OBJECT_INTERFACE * pCurrentCG = NULL;
|
|
CG_OBJECT_INTERFACE * pLastItfCG = 0;
|
|
BOOL fInheritedIntf = NULL;
|
|
|
|
MyContext.ExtractAttribute( ATTR_TYPEDESCATTR );
|
|
MyContext.ExtractAttribute( ATTR_HIDDEN );
|
|
MyContext.ExtractAttribute( ATTR_ASYNC );
|
|
MyContext.ExtractAttribute( ATTR_CSTAGRTN );
|
|
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_interface,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
if( FInSummary( ATTR_IMPLICIT ) )
|
|
{
|
|
pImpHdl = (node_implicit *) GetAttribute( ATTR_IMPLICIT );
|
|
if (pImpHdl)
|
|
pImpHdlCG = (CG_HANDLE *) pImpHdl->ILxlate( &MyContext );
|
|
}
|
|
|
|
if (pGuid)
|
|
GuidStrs = pGuid->GetStrs();
|
|
else
|
|
GuidStrs = DummyGuidStrs;
|
|
|
|
// don't pass the interface attributes down...
|
|
// save them off elsewhere
|
|
|
|
ChildContext.SetInterfaceContext( &MyContext );
|
|
|
|
// if we already got spit out, don't do it again...
|
|
if ( GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) ) )
|
|
return NULL;
|
|
|
|
// start the procnum counting over
|
|
GetProcCount() = 0;
|
|
GetCallBackProcCount() = 0;
|
|
|
|
// Generate the interface's CG node first
|
|
if( fObject || MyContext.AnyAncestorBits(IL_IN_LIBRARY))
|
|
{
|
|
// object interfaces need to have their base classes generated, too
|
|
if ( pBaseIntf )
|
|
{
|
|
pBaseCG = (CG_OBJECT_INTERFACE *) pBaseIntf->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
|
|
if ( !pBaseCG )
|
|
{
|
|
XLAT_CTXT BaseCtxt( &ChildContext );
|
|
|
|
BaseCtxt.SetInterfaceContext( &BaseCtxt );
|
|
pCurrentCG = (CG_OBJECT_INTERFACE *)
|
|
pBaseIntf->ILxlate( &BaseCtxt );
|
|
AddToCGList( pCurrentCG, (CG_CLASS**) &pResultCG, (CG_CLASS**) &pLastItfCG );
|
|
|
|
// our base interface made the last one on the list
|
|
pBaseCG = pLastItfCG;
|
|
}
|
|
|
|
// start the procnum from our base interface
|
|
GetProcCount() = pBaseIntf->GetProcCount();
|
|
GetCallBackProcCount() = pBaseIntf->GetCallBackProcCount();
|
|
|
|
}
|
|
|
|
if ( GetFileNode() )
|
|
{
|
|
fInheritedIntf = GetFileNode()->GetImportLevel() > 0;
|
|
}
|
|
|
|
if ( IsValidRootInterface() )
|
|
{
|
|
pcgInterface = new CG_IUNKNOWN_OBJECT_INTERFACE(this,
|
|
GuidStrs,
|
|
FALSE,
|
|
FALSE,
|
|
pBaseCG,
|
|
fInheritedIntf);
|
|
}
|
|
else if ( fInheritedIntf )
|
|
{
|
|
pcgInterface = new CG_INHERITED_OBJECT_INTERFACE(this,
|
|
GuidStrs,
|
|
FALSE,
|
|
FALSE,
|
|
pBaseCG);
|
|
}
|
|
else
|
|
{
|
|
pcgInterface = new CG_OBJECT_INTERFACE(this,
|
|
GuidStrs,
|
|
FALSE,
|
|
FALSE,
|
|
pBaseCG);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pcgInterface = new CG_INTERFACE(this,
|
|
GuidStrs,
|
|
FALSE,
|
|
FALSE,
|
|
pImpHdlCG,
|
|
pBaseCG);
|
|
}
|
|
|
|
if ( fHasMSConfStructAttr )
|
|
{
|
|
( (CG_INTERFACE*) pcgInterface)->SetHasMSConfStructAttr();
|
|
}
|
|
|
|
// store a pointer to our CG node
|
|
SetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY), pcgInterface );
|
|
|
|
// if we generated a bunch of new inherited interfaces, link us to the end
|
|
// of the list, and return the list
|
|
AddToCGList( pcgInterface, (CG_CLASS**) &pResultCG, (CG_CLASS**) &pLastItfCG );
|
|
|
|
BOOL fImported = FALSE;
|
|
if ( GetDefiningFile() )
|
|
{
|
|
fImported = GetDefiningFile()->GetImportLevel() != 0;
|
|
}
|
|
|
|
// if they specified LOCAL, don't generate any CG nodes (except for object)
|
|
if ( MyContext.FInSummary(ATTR_LOCAL) && !fObject )
|
|
{
|
|
return pResultCG;
|
|
}
|
|
|
|
//
|
|
// for each of the procedures.
|
|
//
|
|
|
|
CG_PROC * pBeginProc = NULL;
|
|
|
|
while ( ( pN = MemIter.GetNext() ) != 0 )
|
|
{
|
|
ChildKind = pN->NodeKind();
|
|
|
|
// proc nodes may hang under node_id's
|
|
if( ( ChildKind == NODE_PROC ) ||
|
|
( ( ChildKind == NODE_ID )
|
|
&& ( pN->GetChild()->NodeKind() == NODE_PROC ) ) ||
|
|
( ( ChildKind == NODE_DEF )
|
|
&& ( IsPickle ||
|
|
pN->FInSummary( ATTR_ENCODE ) ||
|
|
pN->FInSummary( ATTR_DECODE ) ) ) )
|
|
{
|
|
// skip call_as targets
|
|
if (ChildKind == NODE_PROC && ((node_proc *)pN)->IsCallAsTarget())
|
|
continue;
|
|
|
|
// translate target of call_as proc
|
|
CG_PROC * pTarget = NULL;
|
|
if (ChildKind == NODE_PROC)
|
|
{
|
|
node_proc * p = ((node_proc *)pN)->GetCallAsType();
|
|
if (p)
|
|
{
|
|
pTarget = (CG_PROC *) p->ILxlate( &ChildContext);
|
|
}
|
|
}
|
|
|
|
// translate CG_NODE
|
|
pChildCG = pN->ILxlate( &ChildContext );
|
|
|
|
// attach target of call_as proc
|
|
if ( pChildCG )
|
|
{
|
|
if (pTarget)
|
|
((CG_PROC *)pChildCG)->SetCallAsCG(pTarget);
|
|
|
|
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
|
|
}
|
|
|
|
// Connect Begin and Finish async DCOM procs together.
|
|
// CloneIFAndSplitMethods always places the procedures
|
|
// immediatly under the interface with the Finish proc
|
|
// immediatly following the begin proc. This code
|
|
// will need to be changed if CloneIFAndSplitMethods
|
|
// changes.
|
|
if ( NODE_PROC == ChildKind )
|
|
{
|
|
|
|
node_proc *pProc = ( node_proc * ) pN;
|
|
|
|
if ( pProc->IsBeginProc() )
|
|
{
|
|
|
|
MIDL_ASSERT( ( ( CG_NDR * ) pChildCG )->IsProc() );
|
|
pBeginProc = ( CG_PROC * )pChildCG;
|
|
#ifndef NDEBUG
|
|
// assert that the next proc is the finish proc
|
|
MEM_ITER NewMemIter = MemIter;
|
|
named_node *pNextNode = NewMemIter.GetNext();
|
|
MIDL_ASSERT( pNextNode );
|
|
MIDL_ASSERT( NODE_PROC == pNextNode->NodeKind() );
|
|
MIDL_ASSERT( ( (node_proc *)pNextNode )->IsFinishProc() );
|
|
#endif // NDEBUG
|
|
}
|
|
|
|
else if ( pProc->IsFinishProc() )
|
|
{
|
|
|
|
MIDL_ASSERT( ( ( CG_NDR * ) pChildCG )->IsProc() );
|
|
CG_PROC *pFinishProc = ( CG_PROC * )pChildCG;
|
|
|
|
// Link the begin and finsh procs together
|
|
pBeginProc->SetIsBeginProc();
|
|
pBeginProc->SetAsyncRelative( pFinishProc );
|
|
pFinishProc->SetIsFinishProc();
|
|
pFinishProc->SetAsyncRelative( pBeginProc );
|
|
|
|
pBeginProc = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// make sure we don't have too many procs
|
|
if ( fObject && fInheritedIntf )
|
|
{
|
|
if ( ( GetProcCount() > 256 ) )
|
|
{
|
|
// complain about too many delegated routines
|
|
SemError(this, MyContext, TOO_MANY_DELEGATED_PROCS, NULL);
|
|
}
|
|
else if ( GetProcCount() > 64 )
|
|
{
|
|
pCommand->GetNdrVersionControl().SetHasMoreThan64DelegatedProcs();
|
|
}
|
|
}
|
|
|
|
// mark ourselves if we are an all RPC SS interface
|
|
// or if enable is used anywhere within.
|
|
|
|
if ( fAllRpcSS )
|
|
{
|
|
((CG_INTERFACE *)pcgInterface)->SetAllRpcSS( TRUE );
|
|
}
|
|
if ( fAllRpcSS || GetHasProcsWithRpcSs() )
|
|
{
|
|
((CG_INTERFACE *)pcgInterface)->SetUsesRpcSS( TRUE );
|
|
}
|
|
|
|
// consume all the interface attributes
|
|
MyContext.ClearAttributes();
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
pcgInterface->SetChild(pCG);
|
|
|
|
return pResultCG;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_interface_reference::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_interface_reference::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
CG_CLASS * pCG = NULL;
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_interface_reference,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
pCG = new CG_INTERFACE_POINTER( this,
|
|
(node_interface *) GetChild() );
|
|
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
return pCG;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_source::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_source::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
MEM_ITER MemIter( this );
|
|
CG_CLASS * pCG;
|
|
CG_CLASS * pNew;
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
node_skl * pN;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_source,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
pCG = (CG_CLASS *) new CG_SOURCE( this );
|
|
|
|
//
|
|
// for each of the children.
|
|
//
|
|
|
|
while ( ( pN = MemIter.GetNext() ) != 0 )
|
|
{
|
|
pChildCG = pN->ILxlate( &MyContext );
|
|
|
|
if ( pChildCG )
|
|
{
|
|
if (pPrevChildCG)
|
|
{
|
|
pPrevChildCG->SetSibling( pChildCG );
|
|
}
|
|
else
|
|
{
|
|
pCG->SetChild(pChildCG);
|
|
};
|
|
|
|
pPrevChildCG = pChildCG;
|
|
while ( ( pNew = pPrevChildCG->GetSibling() ) != 0 )
|
|
pPrevChildCG = pNew;
|
|
}
|
|
}
|
|
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
return pCG;
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_echo_string::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_echo_string::ILxlate( XLAT_CTXT* )
|
|
{
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_echo_string,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
return 0;
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_error::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_error::ILxlate( XLAT_CTXT* )
|
|
{
|
|
|
|
#ifdef trace_cg
|
|
printf("..node_error,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
return 0;
|
|
};
|
|
|
|
|
|
CG_CLASS *
|
|
Transform(
|
|
IN node_skl * pIL )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
This routine performs the translation from the type graph into the
|
|
code generation classes.
|
|
|
|
Arguments:
|
|
|
|
pIL - a pointer to the il tranformer controlling structure.
|
|
|
|
Return Value:
|
|
|
|
A pointer to the new code generator class.
|
|
|
|
Notes:
|
|
|
|
This method should be called only on placeholder nodes like struct / proc
|
|
interface, file etc.
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
{
|
|
XLAT_CTXT MyContext;
|
|
|
|
#ifdef trace_cg
|
|
printf("transforming...\n");
|
|
#endif
|
|
|
|
pReUseDict = new REUSE_DICT;
|
|
|
|
return pIL->ILxlate( &MyContext );
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_library::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_library::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
MEM_ITER MemIter(this);
|
|
#ifdef trace_cg
|
|
printf("..node_library,\t%s\n", GetSymName());
|
|
#endif
|
|
XLAT_CTXT MyContext( this, pContext);
|
|
|
|
if ( pCommand->IsNDR64Run() )
|
|
{
|
|
if ( !pCommand->NeedsNDRRun() )
|
|
{
|
|
|
|
SemError( this, MyContext , NDR64_ONLY_TLB, GetSymName() );
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
MyContext.SetAncestorBits(IL_IN_LIBRARY);
|
|
XLAT_CTXT ChildContext( MyContext );
|
|
|
|
// don't pass the interface attributes down...
|
|
// save them off elsewhere
|
|
|
|
ChildContext.SetInterfaceContext( &MyContext );
|
|
|
|
CG_LIBRARY * pLib = new CG_LIBRARY(this, MyContext);
|
|
|
|
named_node * pN;
|
|
|
|
CG_CLASS * pLast = NULL;
|
|
CG_CLASS * pChild = 0;
|
|
|
|
while ( ( pN = MemIter.GetNext() ) != 0 )
|
|
{
|
|
switch(pN->NodeKind())
|
|
{
|
|
case NODE_FORWARD:
|
|
{
|
|
node_interface_reference * pIRef = (node_interface_reference *)pN->GetChild();
|
|
if (pIRef)
|
|
{
|
|
if (pIRef->NodeKind() == NODE_INTERFACE_REFERENCE)
|
|
{
|
|
// create a CG_INTEFACE_REFERENCE node that points to this node
|
|
pChild = new CG_INTERFACE_REFERENCE(pIRef, ChildContext);
|
|
// make sure that the interface gets ILxlated.
|
|
CG_CLASS * pRef = pIRef->GetRealInterface()->ILxlate(&ChildContext);
|
|
pChild->SetSibling(pRef);
|
|
}
|
|
else
|
|
{
|
|
if (pIRef->NodeKind() == NODE_COCLASS)
|
|
{
|
|
// don't process this type early
|
|
pChild = NULL;
|
|
}
|
|
else
|
|
{
|
|
pChild = pN->ILxlate(&ChildContext);
|
|
if (pChild && pChild->GetSibling())
|
|
pChild = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pChild = 0;
|
|
}
|
|
}
|
|
break;
|
|
case NODE_INTERFACE:
|
|
{
|
|
pChild = pN->ILxlate(&ChildContext);
|
|
// skip over inherited interfaces
|
|
while (pChild && pChild->GetCGID() == ID_CG_INHERITED_OBJECT_INTERFACE)
|
|
pChild=pChild->GetSibling();
|
|
}
|
|
break;
|
|
default:
|
|
// create the appropriate CG node
|
|
pChild = pN->ILxlate(&ChildContext);
|
|
if (pChild && pChild->GetSibling()) // We must have already entered this one.
|
|
pChild = NULL;
|
|
break;
|
|
}
|
|
// attach the CG_NODE to the end of my child list
|
|
if (NULL != pChild && pChild != pLast)
|
|
{
|
|
if (pLast)
|
|
{
|
|
pLast->SetSibling(pChild);
|
|
}
|
|
else
|
|
{
|
|
pLib->SetChild(pChild);
|
|
}
|
|
pLast = pChild;
|
|
// advance past the end of the list
|
|
while (pLast->GetSibling())
|
|
pLast = pLast->GetSibling();
|
|
}
|
|
}
|
|
|
|
SetCG(FALSE, pLib);
|
|
SetCG(TRUE, pLib);
|
|
|
|
return pLib;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_module::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_module::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("..node_module,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
CG_NDR * pcgModule = NULL;
|
|
CG_CLASS * pCG = NULL;
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
MEM_ITER MemIter( this );
|
|
node_skl * pN;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
XLAT_CTXT ChildContext( MyContext );
|
|
|
|
MyContext.ExtractAttribute( ATTR_GUID );
|
|
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
|
|
MyContext.ExtractAttribute( ATTR_HIDDEN );
|
|
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
|
|
|
|
while (MyContext.ExtractAttribute(ATTR_TYPE));
|
|
// clear member attributes
|
|
while (MyContext.ExtractAttribute(ATTR_MEMBER));
|
|
|
|
// don't pass the interface attributes down...
|
|
// save them off elsewhere
|
|
|
|
ChildContext.SetInterfaceContext( &MyContext );
|
|
|
|
// if we already got spit out, don't do it again...
|
|
if ( GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) ) )
|
|
return NULL;
|
|
|
|
// generate our CG node
|
|
|
|
pcgModule = new CG_MODULE(this, MyContext);
|
|
|
|
// store a pointer to our CG node
|
|
SetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY), pcgModule );
|
|
|
|
//
|
|
// for each of the members.
|
|
//
|
|
|
|
while ( ( pN = MemIter.GetNext() ) != 0 )
|
|
{
|
|
pChildCG = pN->ILxlate( &ChildContext );
|
|
|
|
if ( pChildCG )
|
|
{
|
|
if (NODE_PROC == pN->NodeKind())
|
|
{
|
|
((CG_PROC *)pChildCG)->SetProckind(PROC_STATIC);
|
|
}
|
|
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
|
|
}
|
|
}
|
|
|
|
// consume all the interface attributes
|
|
MyContext.ClearAttributes();
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
pcgModule->SetChild(pCG);
|
|
|
|
return pcgModule;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_coclass::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_coclass::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("..node_coclass,\t%s\n", GetSymName());
|
|
#endif
|
|
CG_NDR * pcgCoclass = NULL;
|
|
CG_CLASS * pCG = NULL;
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
MEM_ITER MemIter( this );
|
|
node_skl * pN;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
XLAT_CTXT ChildContext(MyContext);
|
|
MyContext.ExtractAttribute( ATTR_GUID );
|
|
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
|
|
MyContext.ExtractAttribute( ATTR_HIDDEN );
|
|
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
|
|
|
|
while (MyContext.ExtractAttribute(ATTR_TYPE));
|
|
// clear member attributes
|
|
while (MyContext.ExtractAttribute(ATTR_MEMBER));
|
|
|
|
// don't pass the interface attributes down...
|
|
// save them off elsewhere
|
|
|
|
ChildContext.SetInterfaceContext( &MyContext );
|
|
// if we already got spit out, don't do it again...
|
|
if ( GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) ) )
|
|
return NULL ;
|
|
|
|
// generate our CG node
|
|
|
|
pcgCoclass = new CG_COCLASS(this, MyContext);
|
|
|
|
// store a pointer to our CG node
|
|
SetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY), pcgCoclass );
|
|
|
|
//
|
|
// for every member of the coclass
|
|
//
|
|
|
|
node_skl * pChild = 0;
|
|
while ( ( pN = MemIter.GetNext()) != 0 )
|
|
{
|
|
pChild = pN;
|
|
while(NODE_FORWARD == pChild->NodeKind() || NODE_HREF == pChild->NodeKind())
|
|
{
|
|
pChild = pChild->GetChild();
|
|
if ( !pChild )
|
|
{
|
|
XLAT_CTXT ChildErrContext( pN, &MyContext );
|
|
SemError( pN, ChildErrContext, UNSATISFIED_FORWARD, pN->GetSymName() );
|
|
exit( UNSATISFIED_FORWARD );
|
|
}
|
|
}
|
|
pChildCG = pChild->ILxlate( &ChildContext );
|
|
if (pChild->IsInterfaceOrObject())
|
|
{
|
|
// pChildCG = ((node_interface * )pChild)->GetCG(TRUE);
|
|
pChildCG = new CG_INTERFACE_POINTER(this, (node_interface *)pChild );
|
|
}
|
|
/*
|
|
if ( pChildCG && NODE_DISPINTERFACE == pChild->NodeKind())
|
|
{
|
|
pChildCG = new CG_INTERFACE_POINTER(this, pChild, NULL);
|
|
//((node_dispinterface *) pChild)->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
|
|
}
|
|
*/
|
|
if ( pChildCG )
|
|
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
|
|
}
|
|
|
|
// consume all the interface attributes
|
|
MyContext.ClearAttributes();
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
pcgCoclass->SetChild(pCG);
|
|
|
|
return pcgCoclass;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_dispinterface::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_dispinterface::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("..node_dispinterface,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
CG_NDR * pcgInterface = NULL;
|
|
CG_CLASS * pCG = NULL;
|
|
CG_CLASS * pChildCG = NULL;
|
|
CG_CLASS * pPrevChildCG = NULL;
|
|
CG_CLASS * pcgDispatch = NULL;
|
|
MEM_ITER MemIter( this );
|
|
node_skl * pN;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
XLAT_CTXT BaseContext( MyContext ); // context passed to IDispatch
|
|
XLAT_CTXT ChildContext( MyContext );
|
|
node_guid * pGuid = (node_guid *)
|
|
MyContext.ExtractAttribute( ATTR_GUID );
|
|
GUID_STRS GuidStrs;
|
|
NODE_T ChildKind;
|
|
|
|
node_interface * pBaseIntf;
|
|
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
|
|
MyContext.ExtractAttribute( ATTR_HIDDEN );
|
|
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
|
|
|
|
while (MyContext.ExtractAttribute(ATTR_TYPE));
|
|
// clear member attributes
|
|
while (MyContext.ExtractAttribute(ATTR_MEMBER));
|
|
|
|
if (pGuid)
|
|
GuidStrs = pGuid->GetStrs();
|
|
|
|
// don't pass the interface attributes down...
|
|
// save them off elsewhere
|
|
|
|
BaseContext.SetInterfaceContext( &MyContext );
|
|
ChildContext.SetInterfaceContext( &MyContext );
|
|
|
|
// if we already got spit out, don't do it again...
|
|
if ( GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) ) )
|
|
return NULL;
|
|
|
|
//
|
|
// ILxlate IDispatch
|
|
//
|
|
pcgDispatch = GetIDispatch()->ILxlate(&BaseContext);
|
|
pcgDispatch = ((node_interface *)GetIDispatch())->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
|
|
|
|
// generate our CG node
|
|
|
|
pcgInterface = new CG_DISPINTERFACE(this, GuidStrs,(CG_OBJECT_INTERFACE *)pcgDispatch);
|
|
|
|
// store a pointer to our CG node
|
|
SetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY), pcgInterface );
|
|
|
|
// Either we have a single base interface, or we have no base interface.
|
|
|
|
pN = MemIter.GetNext();
|
|
if (pN)
|
|
{
|
|
ChildKind = pN->NodeKind();
|
|
if (ChildKind == NODE_FORWARD)
|
|
{
|
|
// We have a base interface
|
|
pBaseIntf = (node_interface *)GetMyBaseInterfaceReference();
|
|
// process the base interface
|
|
if (pBaseIntf)
|
|
{
|
|
pChildCG = pBaseIntf->ILxlate(&ChildContext);
|
|
if ( pChildCG )
|
|
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// for each of the procedures.
|
|
//
|
|
|
|
while( pN )
|
|
{
|
|
ChildKind = pN->NodeKind();
|
|
|
|
// proc nodes may hang under node_id's
|
|
if( (ChildKind == NODE_FIELD) ||
|
|
( ChildKind == NODE_PROC ) ||
|
|
( ( ChildKind == NODE_ID ) && ( pN->GetChild()->NodeKind() == NODE_PROC ) ) )
|
|
{
|
|
pChildCG = pN->ILxlate( &ChildContext );
|
|
|
|
if ( pChildCG )
|
|
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
|
|
}
|
|
|
|
pN = MemIter.GetNext();
|
|
}
|
|
|
|
// consume all the interface attributes
|
|
MyContext.ClearAttributes();
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
pcgInterface->SetChild(pCG);
|
|
|
|
return pcgInterface;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_pipe::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_pipe::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("..node_pipe,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
CG_CLASS * pChildCG;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
CG_PIPE * pCG = new CG_PIPE (
|
|
this,
|
|
MyContext
|
|
);
|
|
// if /deny is not specified, ignore [range]
|
|
// if [range] is not ignored, new format string is
|
|
// generated for pipes.
|
|
if ( pCommand->IsSwitchDefined( SWITCH_ROBUST ) )
|
|
{
|
|
pCG->SetRangeAttribute( ( node_range_attr* ) MyContext.ExtractAttribute( ATTR_RANGE ) );
|
|
}
|
|
pChildCG = GetChild()->ILxlate( &MyContext );
|
|
|
|
pContext->ReturnSize( MyContext );
|
|
pCG->SetChild( pChildCG );
|
|
|
|
return pCG;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
// node_safearray::ILxlate
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
CG_CLASS *
|
|
node_safearray::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("..node_safearray,\t%s\n", GetSymName());
|
|
#endif
|
|
|
|
CG_CLASS * pChildCG;
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
CG_SAFEARRAY * pCG = new CG_SAFEARRAY(this, MyContext);
|
|
|
|
// SAFEARRAY, being defined in the public IDL files, has a known
|
|
// alignment of 4. Now the struct etc. that embeds the SAFEARRAY
|
|
// may have a different alignment but the struct code will make it
|
|
// right by choosing min(ZeePee, max(children)).
|
|
// The child of the node is a type specifier from SAFEARRAY(type).
|
|
// The type alias is the LPSAFEARRAY
|
|
|
|
pCG->SetMemoryAlignment( 4 );
|
|
|
|
MyContext.GetMemAlign() = 4;
|
|
pContext->ReturnSize( MyContext );
|
|
|
|
pChildCG = GetChild()->ILxlate( &MyContext );
|
|
|
|
pCG->SetChild( pChildCG );
|
|
|
|
// If the SAFEARRAY was not used in a proxy, just pass up the SAFEARRAY class.
|
|
if ( ! fInProxy )
|
|
return pCG;
|
|
|
|
// If the SAFEARRAY was used in a proxy, pass up the the annoted node for
|
|
// LPSAFEARRAY.
|
|
|
|
CG_NDR *pTypeAliasCG = (CG_NDR*) ( GetTypeAlias()->ILxlate( pContext ) );
|
|
|
|
MIDL_ASSERT( pTypeAliasCG->GetCGID() == ID_CG_USER_MARSHAL );
|
|
|
|
CG_USER_MARSHAL *pUserMarshalCG = (CG_USER_MARSHAL *)pTypeAliasCG;
|
|
|
|
pUserMarshalCG->SetTypeDescGenerator( pCG );
|
|
|
|
return pUserMarshalCG;
|
|
}
|
|
|
|
|
|
CG_CLASS*
|
|
node_async_handle::ILxlate( XLAT_CTXT * pContext )
|
|
{
|
|
#ifdef trace_cg
|
|
printf("..node_async_handle,\t%s\n", GetSymName());
|
|
#endif
|
|
XLAT_CTXT MyContext( this, pContext );
|
|
CG_ASYNC_HANDLE* pAsyncHdl = new CG_ASYNC_HANDLE( this, MyContext );
|
|
|
|
return pAsyncHdl;
|
|
}
|
|
|
|
CG_CLASS*
|
|
node_midl_pragma::ILxlate( XLAT_CTXT* )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
CG_CLASS*
|
|
node_decl_guid::ILxlate( XLAT_CTXT* )
|
|
{
|
|
return 0;
|
|
}
|