mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
757 lines
17 KiB
757 lines
17 KiB
/*****************************************************************************/
|
|
/** Microsoft LAN Manager **/
|
|
/** Copyright(c) Microsoft Corp., 1987-1990 **/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************
|
|
File : nodeskl.cxx
|
|
Title : skeletal node build routines
|
|
History :
|
|
04-Aug-1991 VibhasC Created
|
|
|
|
*****************************************************************************/
|
|
/****************************************************************************
|
|
local defines and includes
|
|
****************************************************************************/
|
|
|
|
#include "nulldefs.h"
|
|
extern "C"
|
|
{
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
}
|
|
|
|
#include "allnodes.hxx"
|
|
#include "gramutil.hxx"
|
|
#include "cmdana.hxx"
|
|
|
|
#define BASETYPEALIGN( Size ) ((Size >= ZeePee) || (Size == 0)) ? ZeePee : Size
|
|
|
|
#define ADJUST_OFFSET(Offset, M, AlignFactor) \
|
|
Offset += (M = Offset % AlignFactor) ? (AlignFactor-M) : 0
|
|
|
|
/****************************************************************************
|
|
external data
|
|
****************************************************************************/
|
|
|
|
extern unsigned short EnumSize;
|
|
extern CMD_ARG * pCommand;
|
|
extern node_e_attr * pErrorAttrNode;
|
|
extern node_error * pErrorTypeNode;
|
|
extern SymTable * pBaseSymTbl;
|
|
extern IDICT * pInterfaceDict;
|
|
extern ISTACK * pZpStack;
|
|
|
|
/****************************************************************************
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
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 ) );
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
GetSize:
|
|
return the size of the type represented by this type node. This function
|
|
should return the size of basic types for basic types nodes, the size
|
|
of return type if the node is a proc node. Structures/Unions/Arrays have
|
|
their own routines to return size, since alignment plays a part.
|
|
****************************************************************************/
|
|
|
|
unsigned long
|
|
node_skl::GetSize(
|
|
unsigned long CurOffset,
|
|
unsigned short ZeePee)
|
|
{
|
|
NODE_T NodeType;
|
|
unsigned long Mod;
|
|
unsigned long CurOffsetSave = CurOffset;
|
|
unsigned long CurAlign;
|
|
node_skl * pChildPtr;
|
|
unsigned long MySize;
|
|
|
|
if ( ZeePee == 0 )
|
|
{
|
|
ZeePee = pCommand->GetZeePee();
|
|
};
|
|
|
|
NodeType = NodeKind();
|
|
|
|
|
|
switch( NodeType )
|
|
{
|
|
case NODE_FLOAT: MySize = sizeof(float); goto calc;
|
|
case NODE_DOUBLE: MySize = sizeof(double); goto calc;
|
|
case NODE_HYPER: MySize = sizeof(LONGLONG); goto calc;
|
|
case NODE_INT64: MySize = sizeof(LONGLONG); goto calc;
|
|
case NODE_LONG: MySize = sizeof(long); goto calc;
|
|
case NODE_LONGLONG: MySize = sizeof(LONGLONG); goto calc;
|
|
|
|
case NODE_ENUM: MySize = EnumSize; goto calc;
|
|
case NODE_LABEL:
|
|
case NODE_SHORT: MySize = sizeof(short); goto calc;
|
|
case NODE_INT: MySize = sizeof(int); goto calc;
|
|
|
|
case NODE_SMALL: MySize = sizeof(char); goto calc;
|
|
case NODE_CHAR: MySize = sizeof(char); goto calc;
|
|
case NODE_BOOLEAN: MySize = sizeof(char); goto calc;
|
|
case NODE_BYTE: MySize = sizeof(char); goto calc;
|
|
case NODE_POINTER: MySize = sizeof(char *) ; goto calc;
|
|
case NODE_HANDLE_T: MySize = sizeof( long ); goto calc;
|
|
calc:
|
|
CurAlign = BASETYPEALIGN( MySize );
|
|
|
|
CurAlign = GetMscAlign(ZeePee);
|
|
ADJUST_OFFSET(CurOffset, Mod, CurAlign);
|
|
CurOffset += MySize;
|
|
return CurOffset - CurOffsetSave;
|
|
|
|
case NODE_FORWARD:
|
|
case NODE_VOID:
|
|
case NODE_ERROR:
|
|
case NODE_ECHO_STRING:
|
|
|
|
return 0;
|
|
default:
|
|
|
|
pChildPtr = GetBasicType();
|
|
|
|
if(pChildPtr && pChildPtr != this)
|
|
{
|
|
return pChildPtr->GetSize(CurOffset, ZeePee);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
unsigned long
|
|
node_array::GetSize(
|
|
unsigned long CurOffset,
|
|
unsigned short ZeePee )
|
|
{
|
|
node_skl * pNode;
|
|
long CurAlign;
|
|
long Mod,CurOffsetSave;
|
|
unsigned long ArraySize = 0;
|
|
|
|
if ( ZeePee == 0 )
|
|
{
|
|
ZeePee = pCommand->GetZeePee();
|
|
};
|
|
|
|
/**
|
|
** a conformant array is not sized
|
|
**/
|
|
|
|
if ( pUpperBound && ( pUpperBound != (expr_node *) -1) )
|
|
{
|
|
ArraySize = pUpperBound->Evaluate();
|
|
};
|
|
|
|
/**
|
|
** the array may be nested in a struct, adjust the start adddress
|
|
** of the array
|
|
**/
|
|
|
|
CurAlign = GetMscAlign(ZeePee);
|
|
ADJUST_OFFSET(CurOffset, Mod, CurAlign);
|
|
|
|
/**
|
|
** the size of the array element may be odd (like if the array element
|
|
** is a structure of odd size). Calculate the size of the element,
|
|
** adjust the offset for the alignment, and calculate the array size
|
|
**/
|
|
|
|
CurOffsetSave = CurOffset;
|
|
pNode = GetChild();
|
|
CurOffset += pNode->GetSize(CurOffset, ZeePee);
|
|
|
|
ADJUST_OFFSET(CurOffset, Mod, CurAlign);
|
|
return (CurOffset- CurOffsetSave) * ( ArraySize );
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
GetLargestElement:
|
|
return the largest element of the type subgraph underneath this node.
|
|
This call is really meaningful in case of structures where the aligment
|
|
of the structure is the aligment of the largest element in the structure.
|
|
For the rest this is the largest element of the child. If this is a
|
|
pointer node, the largest element is this node itself (why did we do
|
|
this special case ??? , Dont remember. )
|
|
****************************************************************************/
|
|
|
|
node_skl *
|
|
node_skl::GetLargestElement()
|
|
{
|
|
node_skl *pNode;
|
|
if( (pNode = GetChild()) && (NodeKind() != NODE_POINTER) )
|
|
return pNode->GetLargestElement();
|
|
return this;
|
|
}
|
|
|
|
node_skl *
|
|
node_skl::GetLargestNdr()
|
|
{
|
|
node_skl *pNode;
|
|
if( (pNode = GetChild()) && (NodeKind() != NODE_POINTER) )
|
|
return pNode->GetLargestNdr();
|
|
return this;
|
|
}
|
|
|
|
/****************************************************************************
|
|
GetMscAlign:
|
|
return the alignment of the type in memory. MscAlign is Microsoft C
|
|
alignment (the name is because of historic reasons )
|
|
|
|
****************************************************************************/
|
|
unsigned short
|
|
node_skl::GetMscAlign(unsigned short ZeePee)
|
|
{
|
|
NODE_T NodeType = NodeKind();
|
|
node_skl * pChildPtr;
|
|
unsigned short MySize;
|
|
|
|
if ( ZeePee == 0 )
|
|
{
|
|
ZeePee = pCommand->GetZeePee();
|
|
};
|
|
|
|
switch( NodeType )
|
|
{
|
|
case NODE_FLOAT: MySize = sizeof( float ); goto calc;
|
|
case NODE_DOUBLE: MySize = sizeof( double ); goto calc;
|
|
case NODE_HYPER: MySize = sizeof( LONGLONG ); goto calc;
|
|
case NODE_INT64: MySize = sizeof( LONGLONG ); goto calc;
|
|
case NODE_LONG: MySize = sizeof( long ); goto calc;
|
|
case NODE_LONGLONG: MySize = sizeof( LONGLONG ); goto calc;
|
|
case NODE_SHORT: MySize = sizeof( short ); goto calc;
|
|
case NODE_INT: MySize = sizeof( int ); goto calc;
|
|
case NODE_SMALL: MySize = sizeof( char ); goto calc;
|
|
case NODE_CHAR: MySize = sizeof( char ); goto calc;
|
|
case NODE_BOOLEAN: MySize = sizeof( char ); goto calc;
|
|
case NODE_BYTE: MySize = sizeof( char ); goto calc;
|
|
case NODE_POINTER: MySize = sizeof( char * ); goto calc;
|
|
case NODE_LABEL: MySize = sizeof( int ); goto calc;
|
|
case NODE_HANDLE_T: MySize = sizeof( long ); goto calc;
|
|
calc:
|
|
return BASETYPEALIGN( MySize );
|
|
|
|
case NODE_ENUM:
|
|
|
|
return BASETYPEALIGN( EnumSize );
|
|
|
|
case NODE_ERROR:
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
pChildPtr =
|
|
((NodeType == NODE_STRUCT) || (NodeType == NODE_UNION) ) ?
|
|
GetLargestElement() : GetChild();
|
|
if( pChildPtr )
|
|
return pChildPtr->GetMscAlign(ZeePee);
|
|
return 1;
|
|
|
|
}
|
|
}
|
|
/****************************************************************************
|
|
GetNdrAlign:
|
|
return the alignment of the type according to the ndr.
|
|
****************************************************************************/
|
|
unsigned short
|
|
node_skl::GetNdrAlign()
|
|
{
|
|
NODE_T NodeType = NodeKind();
|
|
node_skl * pChildPtr;
|
|
|
|
switch( NodeType )
|
|
{
|
|
case NODE_HYPER:
|
|
case NODE_LONGLONG:
|
|
case NODE_INT64:
|
|
return 8;
|
|
case NODE_LONG:
|
|
return 4;
|
|
case NODE_ENUM:
|
|
return 2;
|
|
case NODE_LABEL:
|
|
case NODE_SHORT:
|
|
return 2;
|
|
case NODE_INT:
|
|
return sizeof(int); /* GetAligns should really never be called
|
|
on ints, isnt it ? */
|
|
case NODE_CHAR:
|
|
case NODE_SMALL:
|
|
case NODE_BOOLEAN:
|
|
case NODE_BYTE:
|
|
return 1;
|
|
case NODE_POINTER:
|
|
return 4;
|
|
case NODE_DOUBLE:
|
|
return 8;
|
|
case NODE_FLOAT:
|
|
return 4;
|
|
case NODE_HANDLE_T:
|
|
return 4;
|
|
|
|
case NODE_ERROR:
|
|
assert( FALSE );
|
|
return 0;
|
|
case NODE_DEF:
|
|
if ( ((node_def *)this)->FInSummary( ATTR_TRANSMIT ) )
|
|
{
|
|
ta * pTrans = (ta *)
|
|
((node_def *)this)->GetAttribute( ATTR_TRANSMIT );
|
|
return pTrans->GetType()->GetNdrAlign();
|
|
}
|
|
else if ( ((node_def *)this)->FInSummary( ATTR_WIRE_MARSHAL ) )
|
|
{
|
|
/* RKK node ? */
|
|
ta * pTrans = (ta *)
|
|
((node_def *)this)->GetAttribute( ATTR_WIRE_MARSHAL );
|
|
return pTrans->GetType()->GetNdrAlign();
|
|
}
|
|
else
|
|
return GetChild()->GetNdrAlign();
|
|
default:
|
|
if ( (NodeType == NODE_STRUCT ) || (NodeType == NODE_UNION) )
|
|
{
|
|
if( ((node_struct *) this)->IsEncapsulatedStruct() )
|
|
{
|
|
node_en_struct *p = (node_en_struct *) this;
|
|
pChildPtr = p->GetSwitchField();
|
|
}
|
|
else
|
|
pChildPtr = GetLargestNdr();
|
|
}
|
|
else
|
|
pChildPtr = GetChild();
|
|
|
|
if( pChildPtr )
|
|
return pChildPtr->GetNdrAlign();
|
|
return 1;
|
|
|
|
}
|
|
}
|
|
/***************************************************************************
|
|
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() )
|
|
{
|
|
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 );
|
|
}
|
|
|
|
node_file *
|
|
node_skl::GetDefiningFile()
|
|
{
|
|
if (GetMyInterfaceNode())
|
|
return GetMyInterfaceNode()->GetFileNode();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
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
|
|
switch ( NodeKind() )
|
|
{
|
|
case NODE_CHAR:
|
|
if ( !FInSummary( ATTR_SIGNED ) )
|
|
return value;
|
|
// fall through to sign extend
|
|
case NODE_SMALL:
|
|
{
|
|
signed char ch = (signed char) value;
|
|
return (EXPR_VALUE) ch;
|
|
}
|
|
case NODE_SHORT:
|
|
{
|
|
signed short sh = (signed short) value;
|
|
return (EXPR_VALUE) sh;
|
|
}
|
|
case NODE_LONG:
|
|
case NODE_INT:
|
|
{
|
|
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;
|
|
|
|
}
|