/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989-1999 Microsoft Corporation Module Name: cgcls.hxx Abstract: class definitions for code generation entities for midl. Notes: A code generation entity is a transformed form of the type graph. This form is a much closer representation of what goes on the wire. History: VibhasC Jul-29-1993 Created. ----------------------------------------------------------------------------*/ #ifndef __CGCLS_HXX__ #define __CGCLS_HXX__ /**************************************************************************** * include files ***************************************************************************/ #include "nulldefs.h" extern "C" { #include } #include "mapset.hxx" #include "allnodes.hxx" #include "cgvisitor.hxx" #include "cgcommon.hxx" #include "ccb.hxx" #include "ilanaly.hxx" class ANALYSIS_INFO; ///////////////////////////////////////////////////////////////////////////// // define a type which returns the code generation status. ///////////////////////////////////////////////////////////////////////////// typedef enum _cg_status { CG_OK // everything was hunky dory. ,CG_NOT_LAYED_OUT // I got an HREFTYPE to an incomplete ITypeInfo. // I will not be able to call LayOut. ,CG_REF_NOT_LAYED_OUT // I got an HREFTYPE to a reference (ptr) to an incomplete ITypeInfo // I will be able to call LayOut but I must then try to get my // dependencies to call LayOut. } CG_STATUS; // // Enumerate the different cg classes. This is purely for dump purposes. If // we add a new CG class, we add the enumerator here. typedef enum _idcg { ID_CG_ERROR ,ID_CG_SOURCE ,ID_CG_FILE ,ID_CG_BT ,ID_CG_INT3264 ,ID_CG_ENUM ,ID_CG_ERROR_STATUS_T ,ID_CG_PROC ,ID_CG_CALLBACK_PROC ,ID_CG_OBJECT_PROC ,ID_CG_INHERITED_OBJECT_PROC ,ID_CG_LOCAL_OBJECT_PROC ,ID_CG_TYPE_ENCODE ,ID_CG_TYPE_ENCODE_PROC ,ID_CG_ENCODE_PROC ,ID_CG_PARAM ,ID_CG_RETURN ,ID_CG_PTR ,ID_CG_IGN_PTR ,ID_CG_BC_PTR ,ID_CG_STRING_PTR ,ID_CG_STRUCT_STRING_PTR ,ID_CG_SIZE_STRING_PTR ,ID_CG_SIZE_PTR ,ID_CG_LENGTH_PTR // we don't seem to use it, rkk, 9/98 ,ID_CG_SIZE_LENGTH_PTR ,ID_CG_INTERFACE_PTR ,ID_CG_STRUCT ,ID_CG_VAR_STRUCT ,ID_CG_CONF_STRUCT ,ID_CG_CONF_VAR_STRUCT ,ID_CG_COMPLEX_STRUCT ,ID_CG_ENCAP_STRUCT ,ID_CG_FIELD ,ID_CG_UNION ,ID_CG_UNION_FIELD ,ID_CG_CASE ,ID_CG_DEFAULT_CASE ,ID_CG_ARRAY ,ID_CG_CONF_ARRAY ,ID_CG_VAR_ARRAY ,ID_CG_CONF_VAR_ARRAY ,ID_CG_STRING_ARRAY ,ID_CG_CONF_STRING_ARRAY ,ID_CG_PRIMITIVE_HDL ,ID_CG_GENERIC_HDL ,ID_CG_CONTEXT_HDL ,ID_CG_TRANSMIT_AS ,ID_CG_REPRESENT_AS ,ID_CG_USER_MARSHAL ,ID_CG_INTERFACE ,ID_CG_OBJECT_INTERFACE ,ID_CG_INHERITED_OBJECT_INTERFACE ,ID_CG_HRESULT ,ID_CG_TYPELIBRARY_FILE ,ID_CG_INTERFACE_REFERENCE ,ID_CG_MODULE ,ID_CG_DISPINTERFACE ,ID_CG_ASYNC_HANDLE ,ID_CG_COCLASS ,ID_CG_LIBRARY ,ID_CG_SAFEARRAY ,ID_CG_TYPEDEF ,ID_CG_ID ,ID_CG_PIPE ,ID_CG_RANGE ,ID_CG_CS_ARRAY ,ID_CG_CS_TAG ,ID_CG_IIDIS_INTERFACE_PTR ,ID_CG_PAD } ID_CG; //////////////////////////////////////////////////////////////////////////// // The general code generation class object. //////////////////////////////////////////////////////////////////////////// class CG_CLASS; class CG_ITERATOR; class CG_CLASS { private: class CG_CLASS * pChild; class CG_CLASS * pSibling; BOOL fLayedOut; BOOL fReadyForLayOut; BOOL fDepsLayedOut; CG_ILANALYSIS_INFO ILAnalysisInfo; public: CG_CLASS() { SetSibling( (CG_CLASS *)0 ); SetChild( (CG_CLASS *)0 ); fLayedOut = FALSE; fReadyForLayOut = FALSE; fDepsLayedOut = FALSE; } CG_CLASS( CG_CLASS *pC, CG_CLASS *pS ) { SetSibling( pS ); SetChild( pC ); fLayedOut = FALSE; fReadyForLayOut = FALSE; fDepsLayedOut = FALSE; } // // Get and set child and sibling. // CG_CLASS * GetChild() { return pChild; } CG_CLASS * GetNonGenericHandleChild() { CG_CLASS * pC = GetChild(); if( pC->GetCGID() == ID_CG_GENERIC_HDL ) { pC = pC->GetChild(); } return pC; } CG_CLASS * SetChild( CG_CLASS *p ) { return (pChild = p ); } CG_CLASS * GetSibling() { return pSibling; } CG_CLASS * SetSibling( CG_CLASS * p ) { return (pSibling = p); } short GetMembers( ITERATOR& I ); short GetMembers( CG_ITERATOR& I ); BOOL HasMembers() { return ( NULL != GetChild() ); } void SetMembers( ITERATOR & I ); CG_CLASS * GetLastSibling(); PNAME GetName() { return (PNAME)( GetType()->GetSymName() ); } #ifdef MIDL_INTERNAL // // debug methods. // void Dump( const char *pTitle = NULL); #endif // MIDL_INTERNAL virtual CG_STATUS GenCode( CCB * ) { return CG_OK; } virtual CG_STATUS GenTypeInfo( CCB * ) { return CG_OK; } virtual CG_STATUS GetTypeDesc(TYPEDESC * &ptd, CCB * pCCB); virtual void * CheckImportLib() { return NULL; } BOOL IsLayedOut() { return fLayedOut; } void LayedOut() { fLayedOut = TRUE; } BOOL AreDepsLayedOut() { return fDepsLayedOut; } void DepsLayedOut() { fDepsLayedOut = TRUE; } void ClearDepsLayedOut() { fDepsLayedOut = FALSE; } BOOL IsReadyForLayOut() { return fReadyForLayOut; } void ReadyForLayOut() { fReadyForLayOut = TRUE; } virtual unsigned long LayOut() { #ifdef __TRACE_LAYOUT__ printf("LayOut, %s\n", GetType()->GetSymName()); #endif return 0; } CG_ILANALYSIS_INFO* GetILAnalysisInfo() { return &ILAnalysisInfo; } // // miscellaneous methods. // virtual ID_CG GetCGID() { return ID_CG_ERROR; } virtual void Visit( CG_VISITOR *pVisitor ) = 0; virtual node_skl * GetType() { return (node_skl *)0; } // // IsXXX methods // virtual BOOL IsArray() { return FALSE; } virtual BOOL IsPointer() { return FALSE; } // true in CG_INTERFACE_POINTER and CG_IIDIS_INTERFACE_POINTER only virtual BOOL IsInterfacePointer() { return FALSE; } virtual BOOL IsStruct() { return FALSE; } virtual BOOL IsUnion() { return FALSE; } virtual BOOL IsXmitRepOrUserMarshal() { return FALSE; } virtual BOOL IsObject() { return FALSE; } virtual BOOL HasAFixedBufferSize() { return FALSE; } void * operator new ( size_t size ) { return AllocateOnceNew( size ); } void operator delete( void * ptr ) { AllocateOnceDelete( ptr ); } }; class CG_ITERATOR { private: CG_CLASS * pFirst; CG_CLASS * pCurrent; public: CG_ITERATOR( CG_CLASS * pStart = NULL ) { SetList( pStart ); } void SetList( CG_CLASS * pStart ) { pFirst = pStart; pCurrent = pStart; } STATUS_T Init( void ) { pCurrent = pFirst; return STATUS_OK; } STATUS_T GetNext( void ** ppReturn ) { if( pCurrent) { (*ppReturn) = pCurrent; pCurrent = pCurrent->GetSibling(); return STATUS_OK; } // null out the return if the list was empty if ( !pFirst ) (*ppReturn) = NULL; return I_ERR_NO_PEER; } void * PeekThis() { if( pCurrent ) { return pCurrent; } else return (void *)0; } short GetCount( void ) { CG_CLASS * pTmp = pFirst; short count = 0; while ( pTmp ) { count++; pTmp = pTmp->GetSibling(); } return count; } STATUS_T Discard() { SetList( NULL ); return STATUS_OK; } }; // tuck this away here, so that it goes blazingly fast inline short CG_CLASS::GetMembers( CG_ITERATOR& I ) { I.SetList( GetChild() ); return I.GetCount(); } class CG_CLONEABLE { virtual CG_CLASS * Clone() = 0; }; #endif // __CGCLS_HXX__