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