WindowsXP-SP1/com/rpc/midl/front/nodeskl.cxx
2020-09-30 16:53:49 +02:00

911 lines
24 KiB
C++

/*****************************************************************************/
/** 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);
}
}