mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
};
|
|
|
|
|