/*****************************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1987-1999 **/ /*****************************************************************************/ /***************************************************************************** File : nodeskl.cxx Title : skeletal node build routines History : 04-Aug-1991 VibhasC Created *****************************************************************************/ #pragma warning ( disable : 4514 ) /**************************************************************************** local defines and includes ****************************************************************************/ #include "nulldefs.h" extern "C" { #include #include } #include "allnodes.hxx" #include "gramutil.hxx" #include "cmdana.hxx" #include "attrnode.hxx" #include "ndrtypes.h" #include "lextable.hxx" #include "control.hxx" inline unsigned short ComputeAlignmentForZP( unsigned short Align, unsigned short ZeePee, BOOL IsMustAlign) { return ((Align > ZeePee) && !IsMustAlign) ? ZeePee : Align; } inline unsigned long RoundToAlignment( unsigned long Size, unsigned short Align) { Align--; return (Size + Align) & ~Align; } /**************************************************************************** external data ****************************************************************************/ extern CMD_ARG * pCommand; extern node_e_attr * pErrorAttrNode; extern node_error * pErrorTypeNode; extern SymTable * pBaseSymTbl; extern IDICT * pInterfaceDict; extern ISTACK * pZpStack; extern LexTable * pMidlLexTable; extern CCONTROL * pCompiler; /**************************************************************************** external procs ****************************************************************************/ extern BOOL IsTempName( char * ); extern void ParseError( STATUS_T, char * ); /****************************************************************************/ void MEMLIST::SetMembers( class SIBLING_LIST & MEMLIST ) { pMembers = MEMLIST.Linearize(); } void MEMLIST::MergeMembersToTail( class SIBLING_LIST & MEMLIST ) { AddLastMember( MEMLIST.Linearize() ); } STATUS_T MEMLIST::GetMembers( class type_node_list * MEMLIST ) { named_node * pCur = pMembers; while ( pCur ) { MEMLIST->SetPeer( pCur ); pCur = pCur->GetSibling(); } return (pMembers)? STATUS_OK: I_ERR_NO_MEMBER; }; short MEMLIST::GetNumberOfArguments() { short count = 0; named_node * pNext = pMembers; while ( pNext ) { count++; pNext = pNext->GetSibling(); }; return count; }; // add a new member onto the very tail void MEMLIST::AddLastMember( named_node * pNode ) { named_node * pPrev = NULL; named_node * pCur = pMembers; while ( pCur ) { pPrev = pCur; pCur = pCur->GetSibling(); } // pPrev is now null (empty list) or points to last element of list if ( pPrev ) { pPrev->SetSibling( pNode ); } else { pMembers = pNode; } } // Remove the last member from the tail void MEMLIST::RemoveLastMember() { named_node * pPrev = NULL; named_node * pCur = pMembers; while ( pCur && pCur->GetSibling() ) { pPrev = pCur; pCur = pCur->GetSibling(); } // pPrev is now null (empty list) or points to next to last element of list if ( pPrev ) { pPrev->SetSibling( NULL); } } void MEMLIST::AddSecondMember( named_node * pNode ) { named_node* pFirst = (named_node*)GetFirstMember(); if ( pFirst ) { named_node* pSecond = pFirst->GetSibling(); pFirst->SetSibling( pNode ); pNode->SetSibling( pSecond ); } else { pMembers = pNode; } } /**************************************************************************** node_id: the private memory allocator ****************************************************************************/ // initialize the memory allocators for node_id and node_id_fe FreeListMgr node_id::MyFreeList( sizeof (node_id ) ); FreeListMgr node_id_fe::MyFreeList( sizeof (node_id_fe ) ); FRONT_MEMORY_INFO node_skl::AdjustMemoryInfoForModifiers(FRONT_MEMORY_INFO OrigInfo) { if (!GetModifiers().IsModifierSet(ATTR_DECLSPEC_ALIGN)) return OrigInfo; OrigInfo.IsMustAlign = TRUE; OrigInfo.Align = __max(OrigInfo.Align, GetModifiers().GetDeclspecAlign()); return OrigInfo; } FRONT_MEMORY_INFO node_skl::GetModifiedMemoryInfoFromChild() { node_skl *pChild = GetChild(); MIDL_ASSERT( pChild ); return AdjustMemoryInfoForModifiers( pChild->GetMemoryInfo() ); } FRONT_MEMORY_INFO node_skl::GetInvalidMemoryInfo() { return FRONT_MEMORY_INFO(0, 1, 0); } FRONT_MEMORY_INFO node_enum::GetMemoryInfo() { unsigned long EnumSize = pCommand->GetEnumSize(); return AdjustMemoryInfoForModifiers( FRONT_MEMORY_INFO( EnumSize, (short)EnumSize, 0 ) ); } FRONT_MEMORY_INFO node_pointer::GetMemoryInfo() { unsigned long PointerSize = SIZEOF_MEM_PTR(); return AdjustMemoryInfoForModifiers( FRONT_MEMORY_INFO( PointerSize, (short)PointerSize, 0 ) ); } FRONT_MEMORY_INFO node_safearray::GetMemoryInfo() { unsigned long PointerSize = SIZEOF_MEM_PTR(); return AdjustMemoryInfoForModifiers( FRONT_MEMORY_INFO( PointerSize, (short)PointerSize, 0 ) ); } FRONT_MEMORY_INFO node_union::GetMemoryInfo() { // The size of a union is the size of the largest element rounded // to the largest alignment. FRONT_MEMORY_INFO UnionSize(0, 1, 0); unsigned short ZeePee = GetZeePee(); MEM_ITER MemIter( this ); node_skl * pNode; while ( ( pNode = MemIter.GetNext() ) != NULL ) { FRONT_MEMORY_INFO TempSize = pNode->GetMemoryInfo(); // Merge in the size of the new union arm. UnionSize.Size = __max(UnionSize.Size, TempSize.Size); UnionSize.Align = __max(UnionSize.Align, TempSize.Align); UnionSize.IsMustAlign = (UnionSize.IsMustAlign || TempSize.IsMustAlign); } // Add padding to end of union. UnionSize = AdjustMemoryInfoForModifiers(UnionSize); UnionSize.Align = ComputeAlignmentForZP( UnionSize.Align, ZeePee, UnionSize.IsMustAlign ); UnionSize.Size = RoundToAlignment( UnionSize.Size, UnionSize.Align ); return UnionSize; } FRONT_MEMORY_INFO node_array::GetMemoryInfo() { // The size of an array is the size of the array element times the element count. FRONT_MEMORY_INFO ArraySize = GetChild()->GetMemoryInfo(); unsigned long ArrayElements; if ( pUpperBound && ( pUpperBound != (expr_node *) -1) ) { ArrayElements = (ulong)pUpperBound->Evaluate(); } else { // A conformant array is not sized. ArrayElements = 0; } ArraySize.Size *= ArrayElements; return AdjustMemoryInfoForModifiers(ArraySize); } FRONT_MEMORY_INFO node_struct::GetMemoryInfo() { // The alignment of a structure is the largest alignment of all the members. // Each structure is aligned according to the following rules. // 1. If the field is a must align, the field is aligned to the Alignment. // 2. If the field is not a must align, the field is aligned to min(Zp, Alignment). MEM_ITER MemIter( this ); unsigned short ZeePee = GetZeePee(); FRONT_MEMORY_INFO StructSize(0,1,0); node_skl * pNode; while ( ( pNode = MemIter.GetNext() ) != 0 ) { FRONT_MEMORY_INFO FieldSize = pNode->GetMemoryInfo(); FieldSize.Align = ComputeAlignmentForZP( FieldSize.Align, ZeePee, FieldSize.IsMustAlign ); StructSize.Size = RoundToAlignment( StructSize.Size, FieldSize.Align ); // StructSize.Size now contains the offset of the field. // Merge in the attributes from the member StructSize.Size += FieldSize.Size; StructSize.Align = __max( FieldSize.Align, StructSize.Align ); StructSize.IsMustAlign = ( StructSize.IsMustAlign || FieldSize.IsMustAlign ); } // Add padding to end of structure. StructSize = AdjustMemoryInfoForModifiers( StructSize ); StructSize.Align = ComputeAlignmentForZP( StructSize.Align, ZeePee, StructSize.IsMustAlign ); StructSize.Size = RoundToAlignment( StructSize.Size, StructSize.Align ); return StructSize; } FRONT_MEMORY_INFO node_def::GetMemoryInfo() { FRONT_MEMORY_INFO TypedefSize; node_represent_as *pRep = (node_represent_as *)GetAttribute(ATTR_REPRESENT_AS); node_user_marshal *pUserMarshall = (node_user_marshal *)GetAttribute(ATTR_USER_MARSHAL); node_cs_char *pCSChar = (node_cs_char *) GetAttribute(ATTR_CSCHAR); if (!pUserMarshall && !pRep && !pCSChar) { // Just use the modified child sizes. return GetModifiedMemoryInfoFromChild(); } if (pCSChar) { MIDL_ASSERT( NULL != pCSChar->GetUserType() ); return AdjustMemoryInfoForModifiers( pCSChar->GetUserType()->GetMemoryInfo() ); } // If both user_marshal and represent_as are specified, use represent_as and let semantic // analysis flag the error. if (pUserMarshall) pRep = pUserMarshall; node_skl *pNode = pRep->GetRepresentationType(); if (!pNode) { // unknown type. Use 0 as the size. TypedefSize.Init(0, 1, 0); } else { TypedefSize = pNode->GetMemoryInfo(); } return AdjustMemoryInfoForModifiers(TypedefSize); } FRONT_MEMORY_INFO node_label::GetMemoryInfo() { return AdjustMemoryInfoForModifiers( FRONT_MEMORY_INFO(sizeof(short), (short)sizeof(short), 0) ); } FRONT_MEMORY_INFO node_base_type::GetMemoryInfo() { unsigned long size; switch( NodeKind() ) { case NODE_FLOAT: size = sizeof(float); break; case NODE_DOUBLE: size = sizeof(double); break; case NODE_FLOAT80: size = 16; break; //BUG, BUG double check once //VC supports this case NODE_FLOAT128: size = 16; break; case NODE_HYPER: size = sizeof(__int64); break; case NODE_INT64: size = sizeof(__int64); break; case NODE_INT128: size = 16; break; case NODE_INT3264: size = SIZEOF_MEM_INT3264(); break; case NODE_INT32: size = sizeof(long); break; case NODE_LONG: size = sizeof(long); break; case NODE_LONGLONG: size = sizeof(LONGLONG); break; case NODE_SHORT: size = sizeof(short); break; case NODE_INT: size = sizeof(int); break; case NODE_SMALL: size = sizeof(char); break; case NODE_CHAR: size = sizeof(char); break; case NODE_BOOLEAN: size = sizeof(char); break; case NODE_BYTE: size = sizeof(char); break; case NODE_HANDLE_T: size = SIZEOF_MEM_PTR(); break; case NODE_VOID: return AdjustMemoryInfoForModifiers(FRONT_MEMORY_INFO(0, 1, 0)); default: size = 0; MIDL_ASSERT(0); } return AdjustMemoryInfoForModifiers(FRONT_MEMORY_INFO(size, (short)size, 0)); } FRONT_MEMORY_INFO node_href::GetMemoryInfo() { node_skl *pChild = Resolve(); MIDL_ASSERT(pChild); return AdjustMemoryInfoForModifiers(pChild->GetMemoryInfo()); } /*************************************************************************** GetBasicType: Get the basic type of the typenode ***************************************************************************/ node_skl * node_skl::GetBasicType() { node_skl * pChildPtr; switch( NodeKind() ) { case NODE_STRUCT: case NODE_ENUM: case NODE_UNION: return this; case NODE_ID: return GetChild(); default: if ( ( pChildPtr = GetChild() ) != 0 ) { if ( pChildPtr->NodeKind() == NODE_DEF || pChildPtr->NodeKind() == NODE_FORWARD || pChildPtr->NodeKind() == NODE_HREF ) return pChildPtr->GetBasicType(); return pChildPtr; } return this; } } /*************************************************************************** GetMyInterfaceNode: Get the interface node for the typenode ***************************************************************************/ node_interface * node_skl::GetMyInterfaceNode() { return (node_interface *) pInterfaceDict->GetElement( IntfKey ); } void node_interface::ResetCGIfNecessary() { if ( !fIs2ndCodegen && pCompiler->GetPassNumber() == NDR64_ILXLAT_PASS ) { fIs2ndCodegen = TRUE; SetCG(TRUE,NULL); SetCG(FALSE,NULL); } } node_file * node_skl::GetDefiningFile() { if (GetMyInterfaceNode()) return GetMyInterfaceNode()->GetFileNode(); else return NULL; } node_skl* node_skl::GetDuplicateGuid ( node_guid* pGuid, SymTable* pUUIDTable ) { node_skl* pDuplicate = 0; if ( pGuid ) { char * GuidStr = pGuid->GetGuidString(); SymKey SKey(GuidStr, NAME_DEF); if ( !pUUIDTable->SymInsert( SKey, 0, (named_node*) this) ) { pDuplicate = pUUIDTable->SymSearch( SKey ); } } return ( pDuplicate == this ) ? 0 : pDuplicate; } /***************************************************************************** utility functions *****************************************************************************/ BOOL COMPARE_ATTR( ATTR_VECTOR & A1, ATTR_VECTOR & A2 ) { int i; for( i = 0; i < MAX_ATTR_SUMMARY_ELEMENTS; ++i ) { if( (A1[ i ] & A2[ i ] ) != A2[i] ) return FALSE; } return TRUE; } void OR_ATTR( ATTR_VECTOR & A1, ATTR_VECTOR & A2 ) { int i; for( i= 0; i < MAX_ATTR_SUMMARY_ELEMENTS; ++i ) { A1[ i ] |= A2[ i ]; } } void XOR_ATTR( ATTR_VECTOR & A1, ATTR_VECTOR & A2 ) { int i; for( i= 0; i < MAX_ATTR_SUMMARY_ELEMENTS; ++i ) { A1[ i ] ^= A2[ i ]; } } void CLEAR_ATTR( ATTR_VECTOR & A1 ) { int i; for( i= 0; i < MAX_ATTR_SUMMARY_ELEMENTS; ++i ) { A1[ i ] = 0; } } void SET_ALL_ATTR( ATTR_VECTOR & A1 ) { int i; for( i= 0; i < MAX_ATTR_SUMMARY_ELEMENTS; ++i ) { A1[ i ] = 0xffffffff; } } ATTR_T CLEAR_FIRST_SET_ATTR ( ATTR_VECTOR & A) { int i; unsigned long mask; short at; for ( i = 0; i < MAX_ATTR_SUMMARY_ELEMENTS; ++i ) { for ( at = 0, mask = 1; mask != 0; ++at, mask = mask<<1 ) { if ( mask & A[i] ) { A[i] &= ~mask; return (ATTR_T) (at + ( i * 32 )); } } } return ATTR_NONE; } BOOL node_base_type::IsUnsigned() { // make obvious choices if ( FInSummary( ATTR_UNSIGNED ) ) return TRUE; if ( FInSummary( ATTR_SIGNED ) ) return FALSE; // unspec'd char is always unsigned if ( NodeKind() == NODE_CHAR ) { return TRUE; } // unspec'd small is always signed else if ( NodeKind() == NODE_SMALL ) { return FALSE; } // the cracks... return FALSE; } EXPR_VALUE node_base_type::ConvertMyKindOfValueToEXPR_VALUE( EXPR_VALUE value ) { // make obvious choice if ( FInSummary( ATTR_UNSIGNED ) ) return value; // small values are irrelevant if ( (value & 0xffffff80) == 0 ) return value; // handle default signedness // simple type should be converted to int in expression evaluation. switch ( NodeKind() ) { case NODE_CHAR: if ( !FInSummary( ATTR_SIGNED ) ) return value; // fall through to sign extend case NODE_SMALL: { signed int ch = (signed int) value; return (EXPR_VALUE) ch; } case NODE_SHORT: { signed int sh = (signed int) value; return (EXPR_VALUE) sh; } case NODE_LONG: case NODE_INT32: case NODE_INT: { signed long lng = (signed long) value; return (EXPR_VALUE) lng; } case NODE_INT3264: { if ( ! pCommand->Is64BitEnv() ) { signed long lng = (signed long) value; return (EXPR_VALUE) lng; } } } return value; } BOOL named_node::IsNamedNode() { return ( ( pName ) && !IsTempName( pName ) ); }; // return the transmit_as type (or NULL) node_skl * node_def::GetTransmittedType() { ta * pXmit = (ta *) GetAttribute( ATTR_TRANSMIT ); /* Rkk just in case */ if ( !pXmit ) pXmit = (ta *) GetAttribute( ATTR_WIRE_MARSHAL ); // allow for transitive xmit_as if ( !pXmit && ( GetChild()->NodeKind() == NODE_DEF ) ) return ((node_def*)GetChild())->GetTransmittedType(); return (pXmit) ? pXmit->GetType() : NULL; } // return the represent_as type (or NULL) char * node_def::GetRepresentationName() { node_represent_as * pRep = (node_represent_as *) GetAttribute( ATTR_REPRESENT_AS ); if ( !pRep ) pRep = (node_represent_as *) GetAttribute( ATTR_USER_MARSHAL ); return (pRep) ? pRep->GetRepresentationName() : NULL; } // link self on as new top node void node_pragma_pack::Push( node_pragma_pack *& pTop ) { pStackLink = pTop; pTop = this; } // search for matching push and pop it off, returning new ZP unsigned short node_pragma_pack::Pop( node_pragma_pack *& pTop ) { unsigned short result = 0; if ( pString ) { while ( pTop->PackType != PRAGMA_PACK_GARBAGE ) { if ( pTop->pString && !strcmp( pTop->pString, pString ) ) { result = pTop->usPackingLevel; pTop = pTop->pStackLink; return result; } pTop = pTop->pStackLink; } } else { if ( pTop->PackType != PRAGMA_PACK_GARBAGE ) { result = pTop->usPackingLevel; pTop = pTop->pStackLink; } } return result; } // routines to save the pragma stack across files class PRAGMA_FILE_STACK_ELEMENT { public: node_pragma_pack * pPackStack; unsigned short SavedZp; PRAGMA_FILE_STACK_ELEMENT( node_pragma_pack * pSt, unsigned short usZp ) { pPackStack = pSt; SavedZp = usZp; } }; void PushZpStack( node_pragma_pack * & PackStack, unsigned short & CurrentZp ) { PRAGMA_FILE_STACK_ELEMENT * pSave = new PRAGMA_FILE_STACK_ELEMENT ( PackStack, CurrentZp ); pZpStack->Push( (IDICTELEMENT) pSave ); // make new zp stack and start new file with command line Zp PackStack = new node_pragma_pack( NULL, pCommand->GetZeePee(), PRAGMA_PACK_GARBAGE ); CurrentZp = pCommand->GetZeePee(); } // restore the Zp stack and current Zp on returning from imported file void PopZpStack( node_pragma_pack * & PackStack, unsigned short & CurrentZp ) { PRAGMA_FILE_STACK_ELEMENT * pSaved = (PRAGMA_FILE_STACK_ELEMENT *) pZpStack->Pop(); PackStack = pSaved->pPackStack; CurrentZp = pSaved->SavedZp; } BOOL MODIFIER_SET::IsFlagAModifier(ATTR_T flag) const { return (flag >= ATTR_CPORT_ATTRIBUTES_START && flag <= ATTR_CPORT_ATTRIBUTES_END); } BOOL MODIFIER_SET::IsModifierSet(ATTR_T flag) const { return (BOOL)( ModifierBits & SetModifierBit( flag ) ); } BOOL MODIFIER_SET::AnyModifiersSet() const { return ModifierBits != 0; } void MODIFIER_SET::SetModifier(ATTR_T flag) { ModifierBits |= SetModifierBit( flag ); } void MODIFIER_SET::ClearModifier(ATTR_T flag) { unsigned _int64 ModifierMask = SetModifierBit( flag ); ModifierBits &= ~ModifierMask; if (ATTR_DECLSPEC_ALIGN == flag) Align = 0; } void MODIFIER_SET::SetDeclspecAlign( unsigned short NewAlign) { SetModifier( ATTR_DECLSPEC_ALIGN); Align = NewAlign; } unsigned short MODIFIER_SET::GetDeclspecAlign() const { if ( !IsModifierSet( ATTR_DECLSPEC_ALIGN ) ) return 1; return Align; } void MODIFIER_SET::SetDeclspecUnknown(char *pNewUnknownTxt) { pUnknownTxt = pMidlLexTable->LexInsert(pNewUnknownTxt); SetModifier( ATTR_DECLSPEC_UNKNOWN ); return; } char *MODIFIER_SET::GetDeclspecUnknown() const { if ( !IsModifierSet( ATTR_DECLSPEC_UNKNOWN ) ) return " "; return pUnknownTxt; } void MODIFIER_SET::Clear() { ModifierBits = 0; Align = 0; pUnknownTxt = 0; } void MODIFIER_SET::Merge(const MODIFIER_SET & MergeModifierSet) { if ( MergeModifierSet.IsModifierSet( ATTR_DECLSPEC_ALIGN ) ) { if (! IsModifierSet( ATTR_DECLSPEC_ALIGN ) ) { Align = MergeModifierSet.Align; } else { Align = __max(MergeModifierSet.Align, Align); } } if (MergeModifierSet.pUnknownTxt) { if (!pUnknownTxt) { pUnknownTxt = MergeModifierSet.pUnknownTxt; } else { size_t StrSize = strlen(MergeModifierSet.pUnknownTxt); StrSize += strlen(pUnknownTxt) + 1; char *pNewText = new char[StrSize]; strcpy(pNewText, pUnknownTxt); strcat(pNewText, MergeModifierSet.pUnknownTxt); pUnknownTxt = pMidlLexTable->LexInsert(pNewText); delete[] pNewText; } } ModifierBits |= MergeModifierSet.ModifierBits; } void MODIFIER_SET::PrintDebugInfo() const { printf("Modifiers: 0x%I64X\n", ModifierBits); printf("Align: %u\n", Align); if (pUnknownTxt) { printf("UnknownTxt: %s\n", pUnknownTxt); } }