Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

2460 lines
74 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989 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"
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
extern CMD_ARG * pCommand;
extern BOOL IsTempName( char *);
extern ccontrol * pCompiler;
extern REUSE_DICT * pReUseDict;
extern REUSE_DICT * pLocalReUseDict;
extern SymTable * pBaseSymTbl;
/****************************************************************************
* definitions
***************************************************************************/
// #define trace_cg
void
AddToCGFileList( CG_FILE *& pCGList, CG_FILE * pFile )
{
if (pFile)
{
pFile->SetSibling( pCGList );
pCGList = pFile;
}
}
//--------------------------------------------------------------------
//
// 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_PROXY_DEF_FILE * pProxyDefCG = NULL;
CG_IID_FILE * pIidCG = NULL;
CG_TYPELIBRARY_FILE * pLibCG = NULL;
CG_COM_METHODS_FILE * pComMthCG = NULL;
CG_COM_HDR_FILE * pComHdrCG = NULL;
CG_COM_IUNKNOWN_FILE * pComIUnkCG = NULL;
CG_DLL_SERVER_FILE * pDllSvrCG = NULL;
CG_DLL_SERVER_DEF_FILE * pDllSvrDefCG = NULL;
CG_EXE_SERVER_FILE * pExeSvrCG = NULL;
CG_EXE_SERVER_MAIN_FILE * pExeMainCG = NULL;
CG_SERVER_REG_FILE * pRegCG = NULL;
CG_TEST_CLIENT_FILE * pCtestCG = 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 HasComClass = FALSE;
BOOL HasComServerExe = FALSE;
BOOL HasComServerDll = FALSE;
BOOL HasRemoteProc = FALSE;
BOOL HasRemoteObjectProc = FALSE;
BOOL HasDefs = FALSE;
BOOL HasLibrary = FALSE;
#ifdef trace_cg
printf("..node_file\n");
#endif
// don't process for imported stuff
if ( ImportLevel > 0 )
{
return NULL;
}
// at this point, there should be no more attributes...
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_COM_CLASS:
HasComClass = TRUE;
HasObjectInterface = TRUE;
break;
case ID_CG_COM_SERVER_EXE:
HasComServerExe = TRUE;
break;
case ID_CG_COM_SERVER_DLL:
HasComServerDll = 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 COM class
// then generate a server file, and ctest file
if ( HasComClass &&
(pChildCG != NULL) ) // if proxy file desired
{
char * pComHdrName;
ITERATOR * pFList;
if ( HasComClass )
{
pComHdrName = pCommand->GetServerHeaderFName();
pFList = NULL;
}
else
{
pFList = pFileList;
pComHdrName = NULL;
}
pComMthCG = new CG_COM_METHODS_FILE(
this,
( pCommand->GenerateServerFile() ) ?
pCommand->GetComServerFName():
NULL,
pFileList,
pComHdrName
);
pComMthCG->SetChild( pChildCG );
pComIUnkCG = new CG_COM_IUNKNOWN_FILE(
this,
( pCommand->GenerateServerUnkFile() ) ?
pCommand->GetServerUnkFName():
NULL,
pFileList,
pComHdrName
);
pComIUnkCG->SetChild( pChildCG );
// note: if there is no other header, get the imports
pComHdrCG = new CG_COM_HDR_FILE(
this,
( pCommand->GenerateServerHeaderFile() ) ?
pComHdrName:
NULL,
(HasDefs) ? NULL : pFileList,
(HasDefs) ? pHdrName : NULL
);
pComHdrCG->SetChild( pChildCG );
}
// If the IDL file contains at least one COM class
// then generate a ctest file
if ( (HasComServerDll || HasComServerExe ) &&
(pChildCG != NULL) ) // if proxy file desired
{
char * pComHdrName;
ITERATOR * pFList;
if ( HasComClass )
{
pComHdrName = pCommand->GetServerHeaderFName();
pFList = NULL;
}
else
{
pFList = pFileList;
pComHdrName = NULL;
}
pCtestCG = new CG_TEST_CLIENT_FILE(
this,
( pCommand->GenerateTestFile() ) ?
pCommand->GetTestClientFName():
NULL,
pComHdrName
);
pCtestCG->SetChild( pChildCG );
pRegCG = new CG_SERVER_REG_FILE(
this,
( pCommand->GenerateServerRegFile() ) ?
pCommand->GetServerRegFName():
NULL
);
pRegCG->SetChild( pChildCG );
}
// If the IDL file contains at least one server dll
// then generate a the dll files
if ( HasComServerDll &&
(pChildCG != NULL) ) // if proxy file desired
{
char * pComHdrName;
ITERATOR * pFList;
if ( HasComClass )
{
pComHdrName = pCommand->GetServerHeaderFName();
pFList = NULL;
}
else
{
pFList = pFileList;
pComHdrName = NULL;
}
pDllSvrCG = new CG_DLL_SERVER_FILE(
this,
( pCommand->GenerateDllServerClassGenFile() ) ?
pCommand->GetDllClassGenFName():
NULL,
pFList,
pComHdrName
);
pDllSvrCG->SetChild( pChildCG );
pDllSvrDefCG = new CG_DLL_SERVER_DEF_FILE(
this,
( pCommand->GenerateDllServerDefFile() ) ?
pCommand->GetDllServerDefFName():
NULL
);
pDllSvrDefCG->SetChild( pChildCG );
}
// If the IDL file contains at least one server exe
// then generate a the exe files
if ( HasComServerExe &&
(pChildCG != NULL) ) // if proxy file desired
{
char * pComHdrName;
ITERATOR * pFList;
if ( HasComClass )
{
pComHdrName = pCommand->GetServerHeaderFName();
pFList = NULL;
}
else
{
pFList = pFileList;
pComHdrName = NULL;
}
pExeSvrCG = new CG_EXE_SERVER_FILE(
this,
( pCommand->GenerateExeServerFile() ) ?
pCommand->GetExeServerFName():
NULL,
pFList,
pComHdrName
);
pExeSvrCG->SetChild( pChildCG );
pExeMainCG = new CG_EXE_SERVER_MAIN_FILE(
this,
( pCommand->GenerateExeServerMainFile() ) ?
pCommand->GetExeServerMainFName():
NULL,
pFList,
pComHdrName
);
pExeMainCG->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) )
{
pLibCG = new CG_TYPELIBRARY_FILE(
this,
// BUGBUG - eventually need to base this on a flag like the others
pCommand->GetTypeLibraryFName());
pLibCG->SetChild( pChildCG );
}
/////////////////////////////////////////////////////////////////////
// glue all the parts together by tacking onto the head of the list.
// the final order is:
// CStub - SStub - Proxy - IID - Hdr
pCGList = NULL;
AddToCGFileList( pCGList, pHCG );
AddToCGFileList( pCGList, pDllSvrCG );
AddToCGFileList( pCGList, pDllSvrDefCG );
AddToCGFileList( pCGList, pExeSvrCG );
AddToCGFileList( pCGList, pExeMainCG );
AddToCGFileList( pCGList, pComHdrCG );
AddToCGFileList( pCGList, pComMthCG );
AddToCGFileList( pCGList, pComIUnkCG );
AddToCGFileList( pCGList, pRegCG );
AddToCGFileList( pCGList, pCtestCG );
AddToCGFileList( pCGList, pIidCG );
AddToCGFileList( pCGList, pProxyDefCG );
AddToCGFileList( pCGList, pProxyCG );
AddToCGFileList( pCGList, pSCG );
AddToCGFileList( pCGList, pCCG );
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 );
}
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 = (BOOL)
MyContext.ExtractAttribute( ATTR_ENCODE );
BOOL HasDecode = (BOOL)
MyContext.ExtractAttribute( ATTR_DECODE );
node_call_as * pCallAs = (node_call_as *)
MyContext.ExtractAttribute( ATTR_CALL_AS );
BOOL fLocal = (BOOL )
MyContext.ExtractAttribute( ATTR_LOCAL ) ||
pIntfCtxt->FInSummary( ATTR_LOCAL );
BOOL fLocalCall = IsCallAsTarget();
BOOL fInherited;
unsigned short SavedProcCount = 0;
unsigned short SavedCallbackProcCount = 0;
MyContext.ExtractAttribute(ATTR_ENTRY);
node_constant_attr * pID = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_ID);
node_constant_attr * pHC = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
node_constant_attr * pHSC = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
node_text_attr * pHelpStr = (node_text_attr *)MyContext.ExtractAttribute(ATTR_HELPSTRING);
MyContext.ExtractAttribute(ATTR_IDLDESCATTR);
MyContext.ExtractAttribute(ATTR_FUNCDESCATTR);
MyContext.ExtractAttribute( ATTR_HIDDEN );
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef trace_cg
printf("..node_proc\n");
#endif
BOOL fBindable = FALSE;
BOOL fDisplayBind = FALSE;
BOOL fDefaultBind = FALSE;
BOOL fRequestEdit = FALSE;
BOOL fPropGet = FALSE;
BOOL fPropPut = FALSE;
BOOL fPropPutRef = FALSE;
BOOL fRetVal = FALSE;
BOOL fVararg = FALSE;
BOOL fSource = FALSE;
BOOL fDefaultVtable = FALSE;
BOOL fRestricted = FALSE;
BOOL fHookOleLocal = FALSE;
BOOL fSupressHeader = FALSE;
// get member attributes
node_member_attr * pMA;
while (pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER))
{
switch (pMA->GetAttr())
{
case MATTR_BINDABLE:
fBindable = TRUE;
break;
case MATTR_DISPLAYBIND:
fDisplayBind = TRUE;
break;
case MATTR_DEFAULTBIND:
fDefaultBind = TRUE;
break;
case MATTR_REQUESTEDIT:
fRequestEdit = TRUE;
break;
case MATTR_PROPGET:
fPropGet = TRUE;
break;
case MATTR_PROPPUT:
fPropPut = TRUE;
break;
case MATTR_PROPPUTREF:
fPropPutRef = TRUE;
break;
case MATTR_RETVAL:
fRetVal = TRUE;
break;
case MATTR_VARARG:
fVararg = TRUE;
break;
case MATTR_SOURCE:
fSource = TRUE;
break;
case MATTR_DEFAULTVTABLE:
fDefaultVtable = TRUE;
break;
case MATTR_RESTRICTED:
fRestricted = TRUE;
break;
case MATTR_USESGETLASTERROR:
case MATTR_IMMEDIATEBIND:
case MATTR_NONBROWSABLE:
case MATTR_UIDEFAULT:
case MATTR_DEFAULTCOLLELEM:
case MATTR_REPLACEABLE:
break;
default:
assert(!"Illegal attribute found on name_proc during ILxlate");
break;
}
}
// do my attribute parsing...
fHasCallback = (BOOL) MyContext.ExtractAttribute( ATTR_CALLBACK );
fObject = ((BOOL) 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 = (BOOL) 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;
BOOL fImported = GetDefiningFile()->GetImportLevel() != 0;
if (fLocal && pCommand->IsHookOleEnabled() && !fImported)
fHookOleLocal = TRUE;
// determine if the proc is local and
// determine the proc number (local procs don't bump the number)
if (fLocalCall || (fLocal && !fObject))
{
if (pCommand->IsHookOleEnabled() && !fImported)
{
fHookOleLocal = TRUE;
fSupressHeader = TRUE;
ProcNum = (pIntf->GetProcCount());
}
else
{
// return without making anything
return NULL;
}
}
else
{
if ( fHasCallback )
{
ProcNum = ( pIntf ->GetCallBackProcCount() )++;
}
else
{
ProcNum = ( pIntf ->GetProcCount() )++;
}
}
if (fHookOleLocal)
{
MyContext.SetAncestorBits(IL_IN_LOCAL);
}
if ( fLocal && fObject && !MyContext.AnyAncestorBits(IL_IN_LIBRARY) && !(pCommand->IsHookOleEnabled() && !fImported))
{
if ( pIntf->IsValidRootInterface() )
{
pCG = new CG_IUNKNOWN_OBJECT_PROC( ProcNum,
this,
GetDefiningFile()->GetImportLevel() > 0,
GetOptimizationFlags() );
}
else
{
pCG = new CG_LOCAL_OBJECT_PROC( ProcNum,
this,
GetDefiningFile()->GetImportLevel() > 0,
GetOptimizationFlags() );
}
goto done;
}
SavedProcCount = pIntf->GetProcCount();
SavedCallbackProcCount = pIntf->GetCallBackProcCount();
// add the return type
if ( HasReturn() )
{
node_skl * pReturnType = GetReturnType();
CG_CLASS * pRetCG;
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...
assert( !MyContext.HasAttributes() );
pContext->ReturnSize( MyContext );
if ( HasAParameter() )
{
//
// for each of the parameters, call the core transformer.
//
while ( pN = (node_param *) MemIter.GetNext() )
{
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
// 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;
};
pPrevChildCG = pChildCG;
}
}
#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( GetOptimizationFlags() |
OPTIMIZE_THUNKED_INTERPRET );
}
else if ( pCallAs )
{
SetOptimizationFlags( GetOptimizationFlags() |
OPTIMIZE_THUNKED_INTERPRET );
}
else if ( pReturnCG ) // check the return type
{
CG_NDR * pRetTypeCG = (CG_NDR *) pReturnCG->GetChild();
if ( pRetTypeCG->GetCGID() != ID_CG_CONTEXT_HDL )
{
if ( ( pRetTypeCG->GetWireSize() > 4 ) ||
( !pRetTypeCG->IsSimpleType() &&
!pRetTypeCG->IsPointer() ) )
SetOptimizationFlags( 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
);
}
else if ( fObject )
{
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
);
}
else
{
pCG = new CG_OBJECT_PROC(
ProcNum,
this,
(CG_HANDLE *) pBinding,
(CG_PARAM *) pBindingParam,
HasAtLeastOneIn(),
HasAtLeastOneOut(),
HasAtLeastOneShipped(),
fHasStatuses,
fHasFullPointer,
pReturnCG,
GetOptimizationFlags(),
OpBits
);
}
}
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
);
}
else
{
pCG = new CG_PROC(
ProcNum,
this,
(CG_HANDLE *) pBinding,
(CG_PARAM *) pBindingParam,
HasAtLeastOneIn(),
HasAtLeastOneOut(),
HasAtLeastOneShipped(),
fHasStatuses,
fHasFullPointer,
pReturnCG,
GetOptimizationFlags(),
OpBits
);
}
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) ) );
// mark if in a HookOle only proc
if (fHookOleLocal)
pCG->SetHookOleLocal();
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() );
// at this point, there should be no more attributes...
assert( !MyContext.HasAttributes() );
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 %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;
while (pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER));
MyContext.ExtractAttribute(ATTR_IDLDESCATTR);
MyContext.ExtractAttribute(ATTR_FLCID);
MyContext.ExtractAttribute(ATTR_DEFAULTVALUE);
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
if( MyContext.ExtractAttribute( ATTR_IN ) )
{
F |= IN_PARAM;
}
if( MyContext.ExtractAttribute( ATTR_OUT ) )
{
F |= OUT_PARAM;
}
// default to in
if ( F == 0 )
F |= IN_PARAM;
if ( MyContext.FInSummary( ATTR_SWITCH_IS ) )
{
node_switch_is * pAttr = (node_switch_is *)
MyContext.ExtractAttribute( ATTR_SWITCH_IS );
pSwitchExpr = pAttr->GetExpr();
}
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
// 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 );
#ifdef trace_cg
printf("..node_param return %s\n",GetSymName());
fflush(stdout);
#endif
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() )
*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;
char * pName = GetSymName();
BOOL fInheritedIntf = NULL;
MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
MyContext.ExtractAttribute( ATTR_HIDDEN );
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef trace_cg
printf("..node_interface\n");
#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();
}
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);
}
// 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 = GetDefiningFile()->GetImportLevel() != 0;
// if they specified LOCAL, don't generate any CG nodes (except for object)
if ( MyContext.FInSummary(ATTR_LOCAL) && !fObject && !(pCommand->IsHookOleEnabled() && !fImported))
{
return pResultCG;
}
//
// for each of the procedures.
//
while( pN = MemIter.GetNext() )
{
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 (pTarget)
((CG_PROC *)pChildCG)->SetCallAsCG(pTarget);
if ( pChildCG )
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
}
}
// make sure we don't have too many procs
if ( fObject && fInheritedIntf && ( GetProcCount() > 64 ) )
{
// complain about too many delegated routines
SemError(this, MyContext, TOO_MANY_DELEGATED_PROCS, NULL);
}
// 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_object::ILxlate
//
// Notes: This function returns either a CG_INTERFACE or a
// CG_OBJECT_INTERFACE node.
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_object::ILxlate( XLAT_CTXT * pContext )
{
CG_NDR * pcgInterface = NULL;
CG_NDR * pResultCG;
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();
node_interface * pBaseIntf;
node_interface_reference * pBaseIntfRef;
CG_OBJECT_INTERFACE * pBaseCG = NULL;
CG_OBJECT_INTERFACE * pOldestCG = NULL;
CG_OBJECT_INTERFACE * pCurrentFirstCG = NULL;
CG_OBJECT_INTERFACE * pPrevLastCG = NULL;
char * pName = GetSymName();
ITERATOR * pBaseCGList = new ITERATOR;
type_node_list * pBaseIntfList = GetMyBaseInterfaceList();
while(MyContext.ExtractAttribute(ATTR_CUSTOM));
#ifdef trace_cg
printf("..node_object\n");
#endif
if (pGuid)
GuidStrs = pGuid->GetStrs();
// 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 the interface's CG node first
// object interfaces need to have their base classes generated, too
pBaseIntfList->Init();
while( (pBaseIntfList->GetNext( (void **)&pBaseIntfRef ) == STATUS_OK ) )
{
pBaseIntf = pBaseIntfRef->GetRealInterface();
pBaseCG = (CG_OBJECT_INTERFACE *) pBaseIntf->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
if ( !pBaseCG )
{
XLAT_CTXT BaseCtxt( &ChildContext );
BaseCtxt.SetInterfaceContext( &BaseCtxt );
pCurrentFirstCG = (CG_OBJECT_INTERFACE *)
pBaseIntf->ILxlate( &BaseCtxt );
AddToCGList( pCurrentFirstCG, (CG_CLASS**) &pOldestCG, (CG_CLASS**) &pPrevLastCG );
// advance to my base class/interface's CG node
pBaseCG = pPrevLastCG;
}
ITERATOR_INSERT( *pBaseCGList, pBaseCG );
}
// make absolutely sure that the following interfaces are also generated:
static char * NeededItfs[] =
{
"IUnknown",
"IClassFactory",
0
};
node_interface_reference * pNeededIntfRef;
node_interface * pNeededIntf;
char ** ppName = NeededItfs;
CG_CLASS * pItsCG;
for ( ppName = NeededItfs; *ppName ; ppName++ )
{
SymKey SKey( *ppName, NAME_DEF );
pNeededIntfRef = (node_interface_reference *) pBaseSymTbl->SymSearch( SKey );
assert ( pNeededIntfRef );
pNeededIntf = pNeededIntfRef->GetRealInterface();
assert ( pNeededIntf );
pItsCG = (CG_OBJECT_INTERFACE *) pNeededIntf->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
if ( !pItsCG )
{
XLAT_CTXT BaseCtxt( &ChildContext );
BaseCtxt.SetInterfaceContext( &BaseCtxt );
pCurrentFirstCG = (CG_OBJECT_INTERFACE *)
pNeededIntf->ILxlate( &BaseCtxt );
AddToCGList( pCurrentFirstCG, (CG_CLASS**) &pOldestCG, (CG_CLASS**) &pPrevLastCG );
}
}
// generate our CG node
if ( GetFileNode()->GetImportLevel() > 0 )
{
pcgInterface = new CG_INHERITED_OBJECT_INTERFACE(this,
GuidStrs,
FALSE,
FALSE,
pBaseCG );
}
else
{
pcgInterface = new CG_COM_CLASS(this,
GuidStrs,
FALSE,
FALSE,
pBaseCGList);
}
// store a pointer to our CG node
SetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY), pcgInterface );
// start the procnum counting over
GetProcCount() = 0;
GetCallBackProcCount() = 0;
// if we generated a bunch of new inherited interfaces, link us to the end
// of the list, and return the list
pResultCG = pcgInterface;
if ( pPrevLastCG )
{
pResultCG = pOldestCG;
pPrevLastCG->SetSibling( pcgInterface );
}
//
// for each of the procedures.
//
while( pN = MemIter.GetNext() )
{
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 ) ) ) )
{
pChildCG = pN->ILxlate( &ChildContext );
if ( pChildCG )
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
}
}
// consume all the interface attributes
MyContext.ClearAttributes();
pContext->ReturnSize( MyContext );
pcgInterface->SetChild(pCG);
return pResultCG;
};
//--------------------------------------------------------------------
//
// node_com_server::ILxlate
//
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_com_server::ILxlate( XLAT_CTXT * pContext )
{
XLAT_CTXT MyContext( this, pContext );
CG_NDR * pResultCG = NULL;
XLAT_CTXT ChildContext( MyContext );
ITERATOR * pClassCGList = new ITERATOR;
node_object * pClass;
CG_CLASS * pClassCG;
node_interface_reference * pClassRef;
// don't pass the interface attributes down...
// save them off elsewhere
ChildContext.SetInterfaceContext( &MyContext );
pClassList->Init();
// make a list of CG_COM_CLASS nodes
while( (pClassList->GetNext( (void **)&pClassRef ) == STATUS_OK ) )
{
pClass = (node_object *) pClassRef->GetRealInterface();
pClassCG = pClass->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
if ( !pClassCG )
{
XLAT_CTXT ClsCtxt( &ChildContext );
ClsCtxt.SetInterfaceContext( &ClsCtxt );
pClassCG = pClass->ILxlate( &ClsCtxt );
while ( pClassCG && pClassCG->GetSibling() )
pClassCG = pClassCG->GetSibling();
}
if ( pClassCG )
ITERATOR_INSERT( *pClassCGList, pClassCG );
}
if ( IsDll() )
{
pResultCG = new CG_COM_SERVER_DLL( this, pClassCGList );
}
else
{
pResultCG = new CG_COM_SERVER_EXE( this, pClassCGList );
}
#if 0
CG_NDR * pcgInterface = NULL;
CG_CLASS * pCG = NULL;
CG_CLASS * pChildCG = NULL;
CG_CLASS * pPrevChildCG = NULL;
MEM_ITER MemIter( this );
node_skl * pN;
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();
node_interface * pBaseIntf;
node_interface_reference * pBaseIntfRef;
CG_OBJECT_INTERFACE * pBaseCG = NULL;
CG_OBJECT_INTERFACE * pOldestCG = NULL;
CG_OBJECT_INTERFACE * pCurrentFirstCG = NULL;
CG_OBJECT_INTERFACE * pPrevLastCG = NULL;
char * pName = GetSymName();
type_node_list * pBaseIntfList = GetMyBaseInterfaceList();
#ifdef trace_cg
printf("..node_com_server\n");
#endif
if (pGuid)
GuidStrs = pGuid->GetStrs();
// 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 the interface's CG node first
// object interfaces need to have their base classes generated, too
pBaseIntfList->Init();
while( (pBaseIntfList->GetNext( (void **)&pBaseIntfRef ) == STATUS_OK ) )
{
pBaseIntf = pBaseIntfRef->GetRealInterface();
pBaseCG = (CG_OBJECT_INTERFACE *) pBaseIntf->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
if ( !pBaseCG )
{
XLAT_CTXT BaseCtxt( &ChildContext );
BaseCtxt.SetInterfaceContext( &BaseCtxt );
pCurrentFirstCG = (CG_OBJECT_INTERFACE *)
pBaseIntf->ILxlate( &BaseCtxt );
AddToCGList( pCurrentFirstCG, (CG_CLASS**) &pOldestCG, (CG_CLASS**) &pPrevLastCG );
// advance to my base class/interface's CG node
pBaseCG = pPrevLastCG;
}
ITERATOR_INSERT( *pBaseCGList, pBaseCG );
}
// make absolutely sure that the following interfaces are also generated:
static char * NeededItfs[] =
{
"IUnknown",
"IClassFactory",
0
};
node_interface_reference * pNeededIntfRef;
node_interface * pNeededIntf;
char ** ppName = NeededItfs;
CG_CLASS * pItsCG;
for ( ppName = NeededItfs; *ppName ; ppName++ )
{
SymKey SKey( *ppName, NAME_DEF );
pNeededIntfRef = (node_interface_reference *) pBaseSymTbl->SymSearch( SKey );
assert ( pNeededIntfRef );
pNeededIntf = pNeededIntfRef->GetRealInterface();
assert ( pNeededIntf );
pItsCG = (CG_OBJECT_INTERFACE *) pNeededIntf->GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
if ( !pItsCG )
{
XLAT_CTXT BaseCtxt( &ChildContext );
BaseCtxt.SetInterfaceContext( &BaseCtxt );
pCurrentFirstCG = (CG_OBJECT_INTERFACE *)
pNeededIntf->ILxlate( &BaseCtxt );
AddToCGList( pCurrentFirstCG, (CG_CLASS**) &pOldestCG, (CG_CLASS**) &pPrevLastCG );
}
}
// generate our CG node
if ( GetFileNode()->GetImportLevel() > 0 )
{
pcgInterface = new CG_INHERITED_OBJECT_INTERFACE(this,
GuidStrs,
FALSE,
FALSE,
pBaseCG );
}
else
{
pcgInterface = new CG_COM_CLASS(this,
GuidStrs,
FALSE,
FALSE,
pBaseCGList);
}
// store a pointer to our CG node
SetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY), pcgInterface );
// start the procnum counting over
GetProcCount() = 0;
GetCallBackProcCount() = 0;
// if we generated a bunch of new inherited interfaces, link us to the end
// of the list, and return the list
pResultCG = pcgInterface;
if ( pPrevLastCG )
{
pResultCG = pOldestCG;
pPrevLastCG->SetSibling( pcgInterface );
}
//
// for each of the procedures.
//
while( pN = MemIter.GetNext() )
{
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 ) ) ) )
{
pChildCG = pN->ILxlate( &ChildContext );
if ( pChildCG )
AddToCGList( pChildCG, &pCG, &pPrevChildCG );
}
}
pcgInterface->SetChild(pCG);
#endif // 0
// consume all the interface attributes
MyContext.ClearAttributes();
pContext->ReturnSize( MyContext );
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;
node_skl * pMyParent = pContext->GetParent();
#ifdef trace_cg
printf("..node_interface_reference\n");
#endif
// gaj - tbd
// pCG = new CG_INTERFACE_POINTER( pMyParent,
pCG = new CG_INTERFACE_POINTER( this,
GetChild(),
NULL );
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\n");
#endif
pCG = (CG_CLASS *) new CG_SOURCE( this );
//
// for each of the children.
//
while ( pN = MemIter.GetNext() )
{
pChildCG = pN->ILxlate( &MyContext );
if ( pChildCG )
{
if (pPrevChildCG)
{
pPrevChildCG->SetSibling( pChildCG );
}
else
{
pCG->SetChild(pChildCG);
};
pPrevChildCG = pChildCG;
while ( pNew = pPrevChildCG->GetSibling() )
pPrevChildCG = pNew;
}
}
pContext->ReturnSize( MyContext );
return pCG;
};
//--------------------------------------------------------------------
//
// node_echo_string::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_echo_string::ILxlate( XLAT_CTXT * pContext )
{
#ifdef trace_cg
printf("..node_echo_string\n");
#endif
return NULL;
};
//--------------------------------------------------------------------
//
// node_error::ILxlate
//
// Notes:
//
//
//
//--------------------------------------------------------------------
CG_CLASS *
node_error::ILxlate( XLAT_CTXT * pContext )
{
#ifdef trace_cg
printf("..node_error\n");
#endif
return NULL;
};
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
pCompiler->SetPassNumber( ILXLAT_PASS );
pReUseDict = new REUSE_DICT;
if (pCommand->IsHookOleEnabled())
pLocalReUseDict = 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\n");
#endif
XLAT_CTXT MyContext( this, pContext);
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;
while (pN = MemIter.GetNext())
{
switch(pN->NodeKind())
{
case NODE_FORWARD:
{
node_interface_reference * pIRef = (node_interface_reference *)pN->GetChild();
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;
}
}
}
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\n");
#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 );
node_guid * pGuid = (node_guid *)
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())
{
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\n");
#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);
node_guid * pGuid = (node_guid *) 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 GetCG( MyContext.AnyAncestorBits(IL_IN_LIBRARY) );
// 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
//
while( pN = MemIter.GetNext())
{
node_skl * pChild = pN;
while(NODE_FORWARD == pChild->NodeKind() || NODE_HREF == pChild->NodeKind())
{
pChild = pChild->GetChild();
}
pChildCG = pChild->ILxlate( &ChildContext );
if (pChild->IsInterfaceOrObject())
{
// pChildCG = ((node_interface * )pChild)->GetCG(TRUE);
pChildCG = new CG_INTERFACE_POINTER(this, pChild, NULL);
}
/*
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\n");
#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_implicit * pImpHdl = NULL;
CG_HANDLE * pImpHdlCG = NULL;
NODE_T ChildKind;
node_interface * pBaseIntf;
CG_OBJECT_INTERFACE * pBaseCG = NULL;
CG_OBJECT_INTERFACE * pOldestCG = NULL;
CG_OBJECT_INTERFACE * pCurrentFirstCG = NULL;
CG_OBJECT_INTERFACE * pPrevLastCG = NULL;
char * pName = GetSymName();
ITERATOR * pBaseCGList = new ITERATOR;
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\n");
#endif
CG_CLASS * pChildCG;
XLAT_CTXT MyContext( this, pContext );
CG_PIPE * pCG = new CG_PIPE(this, MyContext);
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\n");
#endif
CG_CLASS * pChildCG;
XLAT_CTXT MyContext( this, pContext );
CG_SAFEARRAY * pCG = new CG_SAFEARRAY(this, MyContext);
pChildCG = GetChild()->ILxlate( &MyContext );
pContext->ReturnSize( MyContext );
pCG->SetChild( pChildCG );
return pCG;
};