Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2238 lines
67 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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;
}