|
|
/*****************************************************************************/ /** 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 <stdio.h>
#include <string.h>
}
#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); } }
|