836 lines
27 KiB
C++
836 lines
27 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1993-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
frmtstr.hxx
|
|
|
|
Abstract:
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
History:
|
|
|
|
DKays Oct-1993 Created.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
#ifndef __FRMTSTR_HXX__
|
|
#define __FRMTSTR_HXX__
|
|
|
|
extern "C"
|
|
{
|
|
#include <memory.h>
|
|
}
|
|
|
|
#include "ndrtypes.h"
|
|
#include "stream.hxx"
|
|
#include "cgcommon.hxx"
|
|
#include "dict.hxx"
|
|
|
|
// #define RKK_FRAG_OPT 1
|
|
|
|
class RepAsPadExprDict;
|
|
class RepAsSizeDict;
|
|
class CG_NDR;
|
|
|
|
#if defined(_AMD64_) || defined(_IA64_) // winnt
|
|
#define UNALIGNED __unaligned // winnt
|
|
#else // winnt
|
|
#define UNALIGNED // winnt
|
|
#endif // winnt
|
|
|
|
// Global defined in frmtstr.cxx
|
|
extern char * pNdrRoutineNames[];
|
|
|
|
// This has to be an even number.
|
|
#define DEFAULT_FORMAT_STRING_SIZE 1024
|
|
|
|
|
|
// Format string entry type
|
|
// If you add anything here, be sure that it works not only when outputting,
|
|
// but also when optimizing out fragments via FRMTREG::Compare.
|
|
//
|
|
typedef enum
|
|
{
|
|
FS_FORMAT_CHARACTER,
|
|
FS_POINTER_FORMAT_CHARACTER,
|
|
FS_SMALL,
|
|
FS_SHORT,
|
|
FS_LONG,
|
|
FS_SHORT_OFFSET,
|
|
FS_SHORT_TYPE_OFFSET,
|
|
FS_SHORT_STACK_OFFSET,
|
|
FS_SMALL_STACK_SIZE,
|
|
FS_PAD_MACRO,
|
|
FS_SIZE_MACRO,
|
|
FS_UNKNOWN_STACK_SIZE,
|
|
FS_OLD_PROC_FLAG_BYTE,
|
|
FS_Oi2_PROC_FLAG_BYTE,
|
|
FS_EXT_PROC_FLAG_BYTE,
|
|
FS_PARAM_FLAG_SHORT,
|
|
FS_MAGIC_UNION_SHORT,
|
|
FS_CORR_TYPE_BYTE,
|
|
FS_CORR_FLAG_SHORT,
|
|
FS_CONTEXT_HANDLE_FLAG_BYTE
|
|
} FORMAT_STRING_ENTRY_TYPE;
|
|
|
|
|
|
// (Stack) Offset Dictionary
|
|
//---------------------------
|
|
//
|
|
// It keeps track of stack or field offsets for parallel win32 platforms.
|
|
// The x86 stack offset is stored both directly in the format string itself (as
|
|
// a short for 32b implementation) and in the dictionary as a long.
|
|
// The true long value is used when optimizing.
|
|
// Other offsets are kept in the dictionary under the key which is the position
|
|
// of the x86 stack offset in the format string
|
|
//
|
|
// Note that field offsets may be negative, as for some objects like open structs,
|
|
// the correlation descriptor's offset is relative to the position of the
|
|
// array field in the struct.
|
|
// The format string offset (the position) on the other hand is always absolute,
|
|
// we use long only for convenience in dictionary comparisons.
|
|
//
|
|
typedef struct
|
|
{
|
|
long FormatStringOffset; // Note, this is not an x86 offset.
|
|
// This is the key for this dictionary.
|
|
long X86Offset;
|
|
} OffsetDictElem;
|
|
|
|
|
|
class OffsetDictionary : Dictionary
|
|
{
|
|
public :
|
|
OffsetDictionary() : Dictionary()
|
|
{
|
|
}
|
|
|
|
|
|
OffsetDictElem * LookupOffset( long Position )
|
|
{
|
|
OffsetDictElem DictElem;
|
|
OffsetDictElem * pDictElem;
|
|
Dict_Status DictStatus;
|
|
|
|
DictElem.FormatStringOffset = Position;
|
|
|
|
DictStatus = Dict_Find( &DictElem );
|
|
#if defined(RKK_FRAG_OPT)
|
|
if (DictStatus != SUCCESS )
|
|
{
|
|
printf("LookupOffset Offset=%d\n", Position );
|
|
}
|
|
#endif
|
|
MIDL_ASSERT( DictStatus == SUCCESS );
|
|
|
|
pDictElem = (OffsetDictElem *) Dict_Item();
|
|
|
|
return pDictElem;
|
|
}
|
|
|
|
|
|
virtual
|
|
SSIZE_T Compare( pUserType p1, pUserType p2 )
|
|
{
|
|
return ((OffsetDictElem *)p1)->FormatStringOffset -
|
|
((OffsetDictElem *)p2)->FormatStringOffset;
|
|
}
|
|
|
|
void Insert( long Position,
|
|
long X86Offset)
|
|
{
|
|
OffsetDictElem * pElem;
|
|
OffsetDictElem * pElemSave;
|
|
|
|
#if defined(RKK_FRAG_OPT)
|
|
if ( Position < 0 )
|
|
printf("Insert negative offset %d\n", Position );
|
|
#endif
|
|
|
|
pElemSave = pElem = new OffsetDictElem;
|
|
|
|
pElem->FormatStringOffset = Position;
|
|
pElem->X86Offset = X86Offset;
|
|
|
|
//
|
|
// Delete any entries which currently match, that is
|
|
// entries with the same FormatStringOffset key. This
|
|
// can happen because of format string compression.
|
|
//
|
|
while ( Dict_Delete( (pUserType *) &pElem ) == SUCCESS )
|
|
;
|
|
|
|
Dict_Insert( pElemSave );
|
|
}
|
|
};
|
|
|
|
|
|
// Type Offset Dictionary
|
|
//---------------------------
|
|
//
|
|
// It keeps track of type offsets, both absolute and relative.
|
|
// The reason we use a dictionary is to allow proper fragment optimization for
|
|
// for 32b implementation where a type offset has to be in short32 range while
|
|
// keeping it as a long permits the best optimization possible.
|
|
// Note that for 32b there is only one type offset regardless of the platform.
|
|
//
|
|
// The format string offset (the position) on the other hand is always absolute,
|
|
// we use long only for convenience in dictionary comparisons.
|
|
//
|
|
typedef struct
|
|
{
|
|
long Position; // FormatStringOffset is the key for this dictionary.
|
|
long TypeOffset;
|
|
} TypeOffsetDictElem;
|
|
|
|
|
|
class TypeOffsetDictionary : Dictionary
|
|
{
|
|
public :
|
|
TypeOffsetDictionary() : Dictionary()
|
|
{
|
|
}
|
|
|
|
|
|
TypeOffsetDictElem *LookupOffset( long Position )
|
|
{
|
|
TypeOffsetDictElem DictElem;
|
|
TypeOffsetDictElem * pDictElem;
|
|
Dict_Status DictStatus;
|
|
|
|
DictElem.Position = Position;
|
|
|
|
DictStatus = Dict_Find( &DictElem );
|
|
#if defined(RKK_FRAG_OPT)
|
|
if (DictStatus != SUCCESS )
|
|
{
|
|
printf("LookupOffset Position=%d\n", Position );
|
|
}
|
|
#endif
|
|
MIDL_ASSERT( DictStatus == SUCCESS );
|
|
|
|
pDictElem = (TypeOffsetDictElem *) Dict_Item();
|
|
|
|
return pDictElem;
|
|
}
|
|
|
|
|
|
virtual
|
|
SSIZE_T Compare( pUserType p1, pUserType p2 )
|
|
{
|
|
return ((TypeOffsetDictElem *)p1)->Position -
|
|
((TypeOffsetDictElem *)p2)->Position;
|
|
}
|
|
|
|
|
|
void Insert( long Position, long TypeOffset )
|
|
{
|
|
TypeOffsetDictElem * pElem;
|
|
TypeOffsetDictElem * pElemSave;
|
|
|
|
#if defined(RKK_FRAG_OPT)
|
|
if ( Position < 0 )
|
|
printf("Insert negative offset %d\n", Position );
|
|
#endif
|
|
|
|
pElemSave = pElem = new TypeOffsetDictElem;
|
|
|
|
pElem->Position = Position;
|
|
pElem->TypeOffset = TypeOffset;
|
|
|
|
//
|
|
// Delete any entries which currently match, that is
|
|
// entries with the same FormatStringOffset key. This
|
|
// can happen because of format string compression.
|
|
//
|
|
while ( Dict_Delete( (pUserType *) &pElem ) == SUCCESS )
|
|
;
|
|
|
|
Dict_Insert( pElemSave );
|
|
}
|
|
};
|
|
|
|
|
|
// (Unknown) StackSize Dictionary
|
|
//-------------------------------
|
|
//
|
|
// It keeps track of unknown stack sizes related to unknown represent_as() types.
|
|
// At the place where we have to generate the stack size in the output file,
|
|
// we use the type name to generate a size_of() expression.
|
|
//
|
|
// The format string offset (the position) is always absolute,
|
|
// we use longs only for convenience in dictionary comparisons.
|
|
|
|
typedef struct
|
|
{
|
|
long FormatStringOffset; // used as the key
|
|
char * pTypeName;
|
|
} StackSizeDictElem;
|
|
|
|
|
|
class StackSizeDictionary : Dictionary
|
|
{
|
|
|
|
public :
|
|
|
|
StackSizeDictionary() : Dictionary()
|
|
{
|
|
}
|
|
|
|
virtual
|
|
SSIZE_T Compare( pUserType p1, pUserType p2 )
|
|
{
|
|
return ((StackSizeDictElem *)p1)->FormatStringOffset -
|
|
((StackSizeDictElem *)p2)->FormatStringOffset;
|
|
}
|
|
|
|
char * LookupTypeName( long Offset )
|
|
{
|
|
StackSizeDictElem DictElem;
|
|
StackSizeDictElem * pDictElem;
|
|
Dict_Status DictStatus;
|
|
|
|
DictElem.FormatStringOffset = Offset;
|
|
|
|
DictStatus = Dict_Find( &DictElem );
|
|
MIDL_ASSERT( DictStatus == SUCCESS );
|
|
|
|
pDictElem = (StackSizeDictElem *) Dict_Item();
|
|
|
|
return pDictElem->pTypeName;
|
|
}
|
|
|
|
void Insert( long FormatStringOffset, char * pTypeName )
|
|
{
|
|
StackSizeDictElem * pElem;
|
|
StackSizeDictElem * pElemSave;
|
|
|
|
pElem = pElemSave = new StackSizeDictElem;
|
|
|
|
pElem->FormatStringOffset = FormatStringOffset;
|
|
pElem->pTypeName = pTypeName;
|
|
|
|
//
|
|
// Delete any entries which currently match, this
|
|
// can happen because of format string compression.
|
|
//
|
|
while ( Dict_Delete( (pUserType *) &pElem ) == SUCCESS )
|
|
;
|
|
|
|
Dict_Insert( pElemSave );
|
|
}
|
|
};
|
|
|
|
|
|
// CommentDictionary
|
|
//-------------------------------
|
|
//
|
|
// It keeps track of comments that can be attached to a given format string
|
|
// position.
|
|
// Note that for any offset position, we may have several comments.
|
|
//
|
|
// The format string offset (the position) is always absolute,
|
|
// we use longs only for convenience in dictionary comparisons.
|
|
|
|
typedef struct _CommentDictElem
|
|
{
|
|
struct _CommentDictElem * Next;
|
|
long FormatStringOffset; // used as the key
|
|
char * Comment;
|
|
} CommentDictElem;
|
|
|
|
class CommentDictionary : Dictionary
|
|
{
|
|
|
|
public :
|
|
|
|
CommentDictionary() : Dictionary()
|
|
{
|
|
}
|
|
|
|
virtual
|
|
SSIZE_T Compare( pUserType p1, pUserType p2 )
|
|
{
|
|
return ((CommentDictElem *)p1)->FormatStringOffset -
|
|
((CommentDictElem *)p2)->FormatStringOffset;
|
|
}
|
|
|
|
char * GetComments( long Offset );
|
|
|
|
void Insert( long FormatStringOffset, char * Comment );
|
|
};
|
|
|
|
|
|
//---------------------------------------
|
|
// FormatReg Dictionary is used to keep track of format string fragments
|
|
// that can be collapsed (optimized out).
|
|
|
|
class FRMTREG_DICT;
|
|
|
|
|
|
//---------------------------------------
|
|
// Format string
|
|
//---------------------------------------
|
|
|
|
class FORMAT_STRING
|
|
{
|
|
|
|
unsigned char * pBuffer; // Format string buffer.
|
|
unsigned char * pBufferType; // Entry type for each position.
|
|
// - indicates the meaning
|
|
|
|
unsigned long BufferSize; // Total current allocated buffer size.
|
|
unsigned long CurrentOffset; // Current offset in the format string buffer.
|
|
unsigned long LastOffset; // The last valid format string buffer index.
|
|
|
|
|
|
OffsetDictionary OffsetDict; // Stack offsets at a position
|
|
TypeOffsetDictionary TypeOffsetDict; // Type offsets at a position
|
|
StackSizeDictionary UnknownStackSizeDict; // Unknown type at a position
|
|
CommentDictionary CommentDict; // Comments at a position
|
|
|
|
FRMTREG_DICT * pReuseDict; // Fragment optimization dictionary.
|
|
//
|
|
// This class is a friend as its Compare method accesses pBuffer, pBufferType
|
|
// as well as OffsetDictionary in order to optimize fragments.
|
|
//
|
|
friend class FRMTREG_DICT;
|
|
|
|
|
|
//
|
|
// Increment CurrentOffset and update LastOffset if needed.
|
|
//
|
|
void
|
|
IncrementOffset( long increment )
|
|
{
|
|
CurrentOffset += increment;
|
|
if ( CurrentOffset > LastOffset )
|
|
LastOffset = CurrentOffset;
|
|
}
|
|
|
|
public:
|
|
|
|
FORMAT_STRING();
|
|
|
|
~FORMAT_STRING()
|
|
{
|
|
delete pBuffer;
|
|
delete pBufferType;
|
|
}
|
|
|
|
//
|
|
// Align the buffer correctly. If the current offset is odd then
|
|
// insert a pad format character.
|
|
//
|
|
void
|
|
Align()
|
|
{
|
|
if ( CurrentOffset % 2 )
|
|
PushFormatChar( FC_PAD );
|
|
}
|
|
|
|
void AddComment( long FormatOffset, char * Comment )
|
|
{
|
|
CommentDict.Insert( FormatOffset, Comment );
|
|
}
|
|
|
|
//
|
|
// Add a format char at the current offset.
|
|
//
|
|
void
|
|
PushFormatChar( FORMAT_CHARACTER fc )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_FORMAT_CHARACTER;
|
|
pBuffer[CurrentOffset] = (unsigned char)fc;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Add a pointer format char at the current offset.
|
|
//
|
|
void
|
|
PushPointerFormatChar( unsigned char fc )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_POINTER_FORMAT_CHARACTER;
|
|
pBuffer[CurrentOffset] = fc;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a byte at the current offset.
|
|
//
|
|
void
|
|
PushByte( long b )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_SMALL;
|
|
pBuffer[CurrentOffset] = (unsigned char) b;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a byte with old proc attributes at the current offset
|
|
//
|
|
void PushOldProcFlagsByte( long b )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_OLD_PROC_FLAG_BYTE;
|
|
pBuffer[CurrentOffset] = (unsigned char) b;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a byte with old proc attributes at the current offset
|
|
//
|
|
void PushOi2ProcFlagsByte( long b )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_Oi2_PROC_FLAG_BYTE;
|
|
pBuffer[CurrentOffset] = (unsigned char) b;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a byte with NT5 extended proc attributes at the current offset
|
|
//
|
|
void PushExtProcFlagsByte( long b )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_EXT_PROC_FLAG_BYTE;
|
|
pBuffer[CurrentOffset] = (unsigned char) b;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a context handle flags byte
|
|
//
|
|
void PushContextHandleFlagsByte( long b )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_CONTEXT_HANDLE_FLAG_BYTE;
|
|
pBuffer[CurrentOffset] = (unsigned char) b;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a byte with a correlation type (first byte of a correlation desc).
|
|
//
|
|
void PushCorrelationTypeByte( long b )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_CORR_TYPE_BYTE;
|
|
pBuffer[CurrentOffset] = (unsigned char) b;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a short at the current offset.
|
|
//
|
|
void
|
|
PushShort( short s )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_SHORT;
|
|
pBufferType[CurrentOffset+1] = FS_SMALL;
|
|
*((short UNALIGNED *)(pBuffer + CurrentOffset)) = s;
|
|
|
|
IncrementOffset(2);
|
|
}
|
|
//
|
|
// Push a short with parameter attributes at the current offset.
|
|
//
|
|
void PushParamFlagsShort( short s )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_PARAM_FLAG_SHORT;
|
|
pBufferType[CurrentOffset+1] = FS_SMALL;
|
|
*((short UNALIGNED *)(pBuffer + CurrentOffset)) = s;
|
|
|
|
IncrementOffset(2);
|
|
}
|
|
|
|
//
|
|
// Push a short with the new, robust related, correlation flags.
|
|
//
|
|
void PushCorrelationFlagsShort( short s )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_CORR_FLAG_SHORT;
|
|
pBufferType[CurrentOffset+1] = FS_SMALL;
|
|
*((short UNALIGNED *)(pBuffer + CurrentOffset)) = s;
|
|
|
|
IncrementOffset(2);
|
|
}
|
|
|
|
//
|
|
// Push a short at the current offset.
|
|
//
|
|
void
|
|
PushShort( long s )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_SHORT;
|
|
pBufferType[CurrentOffset+1] = FS_SMALL;
|
|
*((short UNALIGNED *)(pBuffer + CurrentOffset)) = (short) s;
|
|
|
|
IncrementOffset(2);
|
|
}
|
|
|
|
//
|
|
// Push a long at the current offset.
|
|
//
|
|
void
|
|
PushLong( long l )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_LONG;
|
|
pBufferType[CurrentOffset+1] = FS_SMALL;
|
|
pBufferType[CurrentOffset+2] = FS_SMALL;
|
|
pBufferType[CurrentOffset+3] = FS_SMALL;
|
|
*((long UNALIGNED *)(pBuffer + CurrentOffset)) = l;
|
|
|
|
IncrementOffset(4);
|
|
}
|
|
|
|
//
|
|
// Push a pad macro marker at the current offset.
|
|
//
|
|
void
|
|
PushByteWithPadMacro()
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[ CurrentOffset ] = FS_PAD_MACRO;
|
|
pBuffer[ CurrentOffset ] = 0;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push a size macro marker at the current offset.
|
|
//
|
|
void
|
|
PushShortWithSizeMacro()
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[ CurrentOffset ] = FS_SIZE_MACRO;
|
|
pBufferType[CurrentOffset+1] = FS_SMALL;
|
|
pBuffer[ CurrentOffset ] = 0;
|
|
|
|
IncrementOffset(2);
|
|
}
|
|
|
|
//
|
|
// Push a format char at the specified offset.
|
|
//
|
|
void
|
|
PushFormatChar( FORMAT_CHARACTER fc, long offset )
|
|
{
|
|
pBufferType[offset] = FS_FORMAT_CHARACTER;
|
|
pBuffer[offset] = (unsigned char)fc;
|
|
}
|
|
|
|
//
|
|
// Push a short at the specified offset.
|
|
// Used only in unions to emit magic byte followed by simple type or
|
|
// to emit -1 as a marker for no default arm.
|
|
//
|
|
void PushMagicUnionShort( short s, long offset )
|
|
{
|
|
pBufferType[ offset ] = FS_MAGIC_UNION_SHORT;
|
|
pBufferType[ offset+1] = FS_SMALL;
|
|
*((short UNALIGNED *)(pBuffer + offset)) = s;
|
|
}
|
|
|
|
//
|
|
// Push a short at the specified offset.
|
|
// Used primarily to push offsets internal to a type descriptor, for example
|
|
// an offset to pointer layout. These are treated as plain shorts as they
|
|
// never change and should not be mistaken for a relative type offset.
|
|
//
|
|
void PushShort( long s, long offset )
|
|
{
|
|
pBufferType[ offset ] = FS_SHORT;
|
|
pBufferType[ offset+1] = FS_SMALL;
|
|
*((short UNALIGNED *)(pBuffer + offset)) = (short) s;
|
|
}
|
|
|
|
//
|
|
// Push a long at the specified offset. Used only for union case values.
|
|
//
|
|
void PushLong( long l, long offset )
|
|
{
|
|
pBufferType[ offset ] = FS_LONG;
|
|
pBufferType[ offset+1] = FS_SMALL;
|
|
pBufferType[ offset+2] = FS_SMALL;
|
|
pBufferType[ offset+3] = FS_SMALL;
|
|
*((long UNALIGNED *)(pBuffer + offset)) = l;
|
|
}
|
|
|
|
//
|
|
// Push a short offset at the current offset.
|
|
// This is the relative type offset within the type string.
|
|
// For 32b code, this needs to be a value within a signed short.
|
|
//
|
|
void PushShortOffset( long s );
|
|
void PushShortOffset( long s, long offset );
|
|
|
|
//
|
|
// Push a short type-fmt-string offset at the current offset.
|
|
// This is used as the offset from a parameter into type format string.
|
|
// For 32b code, this needs to be a value within an unsigned short.
|
|
//
|
|
void PushShortTypeOffset( long s );
|
|
|
|
//
|
|
// Push a stack offset.
|
|
// Needs to be relative for non-top level objects.
|
|
//
|
|
void PushShortStackOffset( long X86Offset );
|
|
|
|
//
|
|
// Push a stack size or an unsigned stack offset. This is absolute value.
|
|
// Used for proc stack size and parameter offsets.
|
|
//
|
|
void PushUShortStackOffsetOrSize( long X86Offset );
|
|
|
|
//
|
|
// Push a parameter stack size expressed as the number of ints required
|
|
// for the parameter on the stack.
|
|
//
|
|
// The old -Oi parameter descriptor is the only place where this is used.
|
|
//
|
|
void
|
|
PushSmallStackSize( char StackSize )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_SMALL_STACK_SIZE;
|
|
pBuffer[CurrentOffset] = StackSize;
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Push an unknown rep as stack size. We need the type name so we can
|
|
// spit out a 'sizeof' in the format string.
|
|
//
|
|
// The old -Oi parameter descriptor is the only place where this is used.
|
|
//
|
|
void
|
|
PushUnknownStackSize( char * pTypeName )
|
|
{
|
|
CheckSize();
|
|
|
|
pBufferType[CurrentOffset] = FS_UNKNOWN_STACK_SIZE;
|
|
UnknownStackSizeDict.Insert( (long) CurrentOffset, pTypeName );
|
|
|
|
IncrementOffset(1);
|
|
}
|
|
|
|
//
|
|
// Get a FORMAT_CHARACTER at a specific offset in the format string.
|
|
//
|
|
FORMAT_CHARACTER
|
|
GetFormatChar( long offset )
|
|
{
|
|
return (FORMAT_CHARACTER) pBuffer[offset];
|
|
}
|
|
|
|
//
|
|
// Get a short at a specific offset in the format string.
|
|
//
|
|
short
|
|
GetFormatShort( long offset )
|
|
{
|
|
return *(short UNALIGNED *)(pBuffer + offset);
|
|
}
|
|
|
|
//
|
|
// Get the current format string offset.
|
|
//
|
|
long
|
|
GetCurrentOffset()
|
|
{
|
|
return (long)CurrentOffset;
|
|
}
|
|
|
|
//
|
|
// Set the current format string offset. This discards
|
|
// everything after (and including) the new offset from the format string
|
|
//
|
|
void SetCurrentOffset( long NewOffset )
|
|
{
|
|
LastOffset = (unsigned long)NewOffset;
|
|
CurrentOffset = (unsigned long)NewOffset;
|
|
}
|
|
|
|
//
|
|
// Output the format string structure to the given stream.
|
|
//
|
|
void Output( ISTREAM * pStream,
|
|
char * pTypeName,
|
|
char * pName,
|
|
RepAsPadExprDict * pPadDict,
|
|
RepAsSizeDict * pSizeDict );
|
|
|
|
void OutputExprEvalFormatString(ISTREAM *pStream);
|
|
|
|
//
|
|
// Get the fragment re-use dictionary
|
|
//
|
|
FRMTREG_DICT * GetReuseDict()
|
|
{
|
|
return pReuseDict;
|
|
}
|
|
|
|
//
|
|
// Optimize a fragment away
|
|
//
|
|
|
|
long OptimizeFragment( CG_NDR * pNode );
|
|
|
|
//
|
|
// Register a fragment, but don't delete it
|
|
//
|
|
|
|
unsigned short RegisterFragment( CG_NDR * pNode );
|
|
|
|
private :
|
|
|
|
//
|
|
// Check if a bigger buffer needs to be allocated.
|
|
//
|
|
void CheckSize();
|
|
|
|
};
|
|
|
|
#endif
|