1574 lines
51 KiB
C
1574 lines
51 KiB
C
/** compact7.c - basic compaction routine and initialization routines
|
|
* for C7 style Codeview information.
|
|
*/
|
|
|
|
#include "compact.h"
|
|
|
|
|
|
#define INDEXLIST 10
|
|
#define FIELDLIST 11
|
|
#define METHODLIST 12
|
|
|
|
extern CV_typ_t MaxIndex;
|
|
extern CV_typ_t usCurFirstNonPrim; // The current first non primitive type index
|
|
extern ulong ulCVTypeSignature; // The signature from the modules type segment
|
|
|
|
static CV_typ_t _fastcall C7GetCompactedIndexRecur (CV_typ_t OldIndex);
|
|
|
|
ushort recursive;
|
|
|
|
typedef struct {
|
|
ushort sym; // Old C7 Symbol record type
|
|
void (_fastcall *pfcn) (void);
|
|
} C7fixupsymfcn;
|
|
|
|
typedef CV_typ_t (_fastcall *pCompactFcnType)(CV_typ_t);
|
|
|
|
LOCAL pCompactFcnType GetCompactedIndexFcn[] = {
|
|
C6GetCompactedIndexRecur,
|
|
C7GetCompactedIndexRecur,
|
|
};
|
|
|
|
LOCAL void IndexLeaf (plfIndex plfInd, TENTRY *OldEntry);
|
|
INLINE void SaveOffset (TENTRY *OldEntry, ushort index);
|
|
|
|
#if DBG
|
|
#pragma optimize("", off)
|
|
CV_typ_t breakindex;
|
|
void IndexBreak (CV_typ_t index)
|
|
{
|
|
int i;
|
|
|
|
if (index == breakindex) {
|
|
i = 0;
|
|
}
|
|
}
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
|
|
COUNTER (cnt_PackPreComp1);
|
|
COUNTER (cnt_PackPreComp2);
|
|
|
|
void
|
|
PackPreComp(
|
|
PMOD pMod
|
|
)
|
|
{
|
|
ushort i;
|
|
OMFPreCompMap *pMap;
|
|
TENTRY *OldEntry;
|
|
uchar *TypeString;
|
|
plfArgList plf;
|
|
CV_typ_t forward;
|
|
|
|
DASSERT(maxPreComp != 0);
|
|
|
|
// allocate the precompiled types mapping table
|
|
|
|
pMod->PreCompSize = sizeof (OMFPreCompMap) +
|
|
(maxPreComp - CV_FIRST_NONPRIM) * sizeof (CV_typ_t);
|
|
if ((pMod->PreCompAddr = (ulong)TrapMalloc (pMod->PreCompSize)) == (ulong) NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
pMap = (OMFPreCompMap *) pMod->PreCompAddr;
|
|
memset (pMap, 0, pMod->PreCompSize);
|
|
pMap->signature = pMod->signature;
|
|
pMap->cTypes = maxPreComp - CV_FIRST_NONPRIM;
|
|
pMap->FirstType = CV_FIRST_NONPRIM;
|
|
for (i = 0; i < maxPreComp - CV_FIRST_NONPRIM; i++) {
|
|
COUNT (cnt_PackPreComp1);
|
|
OldEntry = GetTypeEntry (i, &forward);
|
|
if (OldEntry->flags.IsInserted || OldEntry->flags.IsMatched) {
|
|
pMap->map[i] = OldEntry->CompactedIndex;
|
|
continue;
|
|
}
|
|
TypeString = OldEntry->TypeString;
|
|
switch (((TYPPTR)TypeString)->leaf) {
|
|
case LF_CLASS:
|
|
case LF_STRUCTURE:
|
|
case LF_UNION:
|
|
case LF_ENUM:
|
|
case LF_MODIFIER:
|
|
case LF_POINTER:
|
|
case LF_ARRAY:
|
|
case LF_PROCEDURE:
|
|
case LF_MFUNCTION:
|
|
case LF_VTSHAPE:
|
|
case LF_COBOL0:
|
|
case LF_COBOL1:
|
|
case LF_BARRAY:
|
|
case LF_LABEL:
|
|
case LF_NULL:
|
|
case LF_BITFIELD: // The index in a bitfield is a primitive, don't call GetCompactedIndex
|
|
case LF_DEFARG:
|
|
case LF_DIMARRAY: /* need to consider these types as well, JK */
|
|
case LF_DIMCONU:
|
|
case LF_DIMCONLU:
|
|
case LF_DIMVARU:
|
|
case LF_DIMVARLU:
|
|
case LF_REFSYM:
|
|
pMap->map[i] = C7GetCompactedIndex ((CV_typ_t) (i + CV_FIRST_NONPRIM));
|
|
break;
|
|
|
|
case LF_ARGLIST:
|
|
plf = (plfArgList)&(((TYPPTR)TypeString)->leaf);
|
|
pMap->map[i] = CompactList ((CV_typ_t)(i + CV_FIRST_NONPRIM), plf->count);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#if DBG
|
|
for (i = 0; i < maxPreComp - CV_FIRST_NONPRIM; i++) {
|
|
if (pMap->map[i] == T_NOTYPE) {
|
|
COUNT (cnt_PackPreComp2);
|
|
OldEntry = GetTypeEntry (i, &forward);
|
|
TypeString = OldEntry->TypeString;
|
|
if ((((TYPPTR)TypeString)->leaf != LF_FIELDLIST) &&
|
|
(pMap->map[i] = OldEntry->CompactedIndex) == T_NOTYPE) {
|
|
// fieldlists get moved into a single list
|
|
DASSERT (FALSE);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// clear maximum precomp index so remainder of packing will work correctly
|
|
|
|
maxPreComp = 0;
|
|
}
|
|
|
|
static INLINE void
|
|
UpdateSmallIndexUnion(
|
|
TENTRY *OldEntry,
|
|
uchar offset
|
|
)
|
|
{
|
|
if (recursive) {
|
|
OldEntry->IndexUnion.Index[OldEntry->Count++] = offset;
|
|
}
|
|
}
|
|
|
|
typedef struct FwdRefChain_t {
|
|
CV_typ_t index;
|
|
HSFWD *pHash;
|
|
struct FwdRefChain_t *pNext;
|
|
} FwdRefChain_t;
|
|
|
|
typedef FwdRefChain_t *pFwdRefChain_t;
|
|
|
|
static pFwdRefChain_t pFwdRefHead = NULL;
|
|
static pFwdRefChain_t pFwdRefTail = NULL;
|
|
|
|
void _fastcall
|
|
AddFwdRef(
|
|
CV_typ_t OldIndex,
|
|
HSFWD *pHash
|
|
)
|
|
{
|
|
pFwdRefChain_t pFwdRef = (pFwdRefChain_t) Alloc(sizeof(FwdRefChain_t));
|
|
|
|
pFwdRef->index = OldIndex;
|
|
pFwdRef->pHash = pHash;
|
|
pFwdRef->pNext = NULL;
|
|
if (pFwdRefHead == NULL) {
|
|
DASSERT(pFwdRefTail == NULL);
|
|
pFwdRefHead = pFwdRefTail = pFwdRef;
|
|
}
|
|
else {
|
|
pFwdRefTail->pNext = pFwdRef;
|
|
pFwdRefTail = pFwdRef;
|
|
}
|
|
}
|
|
|
|
INLINE void
|
|
CompactClassStruct(
|
|
TENTRY *OldEntry
|
|
)
|
|
{
|
|
|
|
TYPPTR pType = (TYPPTR)OldEntry->TypeString;
|
|
CV_typ_t type;
|
|
plfClass plf = (plfClass)&pType->leaf;
|
|
// Compact vshape index
|
|
|
|
type = C7GetCompactedIndexRecur (plf->vshape);
|
|
plf = (plfClass)&pType->leaf;
|
|
plf->vshape = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfClass, vshape) + LNGTHSZ));
|
|
|
|
// Compact LF_FIELDLIST index
|
|
|
|
type = CompactList (plf->field, plf->count);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfClass)&pType->leaf;
|
|
plf->field = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfClass, field) + LNGTHSZ));
|
|
|
|
// Don't compact derivation list, this will be generated
|
|
// later in the compaction process
|
|
|
|
}
|
|
|
|
INLINE void
|
|
CompactUnion(
|
|
TENTRY *OldEntry
|
|
)
|
|
{
|
|
|
|
TYPPTR pType = (TYPPTR)OldEntry->TypeString;
|
|
CV_typ_t type;
|
|
plfClass plf = (plfClass)&pType->leaf;
|
|
|
|
type = CompactList (plf->field, plf->count);
|
|
plf = (plfClass)&pType->leaf;
|
|
plf->field = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfUnion, field) + LNGTHSZ));
|
|
|
|
}
|
|
|
|
INLINE void
|
|
CompactEnum(
|
|
TENTRY *OldEntry
|
|
)
|
|
{
|
|
|
|
TYPPTR pType = (TYPPTR)OldEntry->TypeString;
|
|
CV_typ_t type;
|
|
plfEnum plf = (plfEnum)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->utype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfEnum)&pType->leaf;
|
|
plf->utype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfEnum, utype) + LNGTHSZ));
|
|
type = CompactList (plf->field, plf->count);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfEnum)&pType->leaf;
|
|
plf->field = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfEnum, field) + LNGTHSZ));
|
|
|
|
}
|
|
|
|
void _fastcall
|
|
PickUpFwdRefs(
|
|
void
|
|
)
|
|
{
|
|
pFwdRefChain_t pChain, pOldChain;
|
|
TENTRY *OldEntry;
|
|
CV_typ_t type;
|
|
TYPPTR pType;
|
|
|
|
pChain = pFwdRefHead;
|
|
|
|
while (pChain) {
|
|
OldEntry = GetTypeEntry ((CV_typ_t)(pChain->index - usCurFirstNonPrim), &type);
|
|
DASSERT(OldEntry->flags.IsMatched);
|
|
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
switch (pType->leaf) {
|
|
|
|
case LF_STRUCTURE:
|
|
case LF_CLASS:
|
|
CompactClassStruct(OldEntry);
|
|
break;
|
|
|
|
case LF_UNION:
|
|
CompactUnion(OldEntry);
|
|
break;
|
|
|
|
case LF_ENUM:
|
|
CompactEnum(OldEntry);
|
|
break;
|
|
|
|
default:
|
|
DASSERT(FALSE);
|
|
|
|
}
|
|
|
|
if (!(pChain->pHash->SatisfyFwdRef)) {
|
|
memmove ((uchar *)(pChain->pHash->pType) + sizeof (ushort),
|
|
(uchar *)pType + sizeof(ushort),
|
|
__min(pType->len, pChain->pHash->pType->len));
|
|
pChain->pHash->SatisfyFwdRef = TRUE;
|
|
}
|
|
|
|
pOldChain = pChain;
|
|
pChain = pChain->pNext;
|
|
|
|
free(pOldChain);
|
|
}
|
|
|
|
pFwdRefHead = pFwdRefTail = NULL;
|
|
}
|
|
|
|
/** C7GetCompactedIndex - get global type index for C7 type index
|
|
*
|
|
* index = C7GetCompactedIndex (OldIndex)
|
|
*
|
|
* Entry OldIndex = module level uncompacted index
|
|
*
|
|
* Exit full type tree indexed by OldIndex compacted into
|
|
* global table
|
|
*
|
|
* Return index of type string in global types table
|
|
*/
|
|
|
|
extern ushort StackPointer;
|
|
|
|
COUNTER (cnt_C7GetCompactedIndex1);
|
|
COUNTER (cnt_C7GetCompactedIndex2);
|
|
|
|
CV_typ_t _fastcall
|
|
C7GetCompactedIndex(
|
|
CV_typ_t OldIndex
|
|
)
|
|
{
|
|
CV_typ_t retval;
|
|
|
|
retval = C7GetCompactedIndexRecur(OldIndex);
|
|
PickUpFwdRefs();
|
|
|
|
return(retval);
|
|
}
|
|
|
|
static CV_typ_t _fastcall
|
|
C7GetCompactedIndexRecur(
|
|
CV_typ_t OldIndex
|
|
)
|
|
{
|
|
TENTRY *OldEntry;
|
|
CV_typ_t OldRecursiveRoot;
|
|
HSFWD *pHash;
|
|
uchar i = 0;
|
|
CV_typ_t forward;
|
|
TYPPTR pType;
|
|
CV_typ_t type;
|
|
|
|
if (CV_IS_PRIMITIVE (OldIndex)) {
|
|
// primitive index
|
|
recursive = FALSE;
|
|
return (OldIndex);
|
|
}
|
|
if (OldIndex >= MaxIndex + CV_FIRST_NONPRIM) {
|
|
// type index is not within limits
|
|
recursive = FALSE;
|
|
return (T_NOTTRANS);
|
|
}
|
|
BreakOnIndex (OldIndex);
|
|
|
|
// get table entry
|
|
|
|
COUNT (cnt_C7GetCompactedIndex1);
|
|
OldEntry = GetTypeEntry ((CV_typ_t)(OldIndex - CV_FIRST_NONPRIM), &forward);
|
|
DASSERT (OldEntry != NULL);
|
|
DASSERT (OldEntry->flags.IsNewFormat);
|
|
|
|
if (OldEntry->flags.IsInserted || OldEntry->flags.IsMatched ||
|
|
OldEntry->flags.IsPreComp) {
|
|
recursive = FALSE;
|
|
return (OldEntry->CompactedIndex);
|
|
}
|
|
else if (OldEntry->flags.IsDone) {
|
|
TENTRY *TmpEntry1 = OldEntry;
|
|
TENTRY *TmpEntry2;
|
|
|
|
while (TRUE) {
|
|
COUNT (cnt_C7GetCompactedIndex2);
|
|
TmpEntry2 = GetTypeEntry ((CV_typ_t)(TmpEntry1->CompactedIndex - CV_FIRST_NONPRIM),
|
|
&forward);
|
|
if (!TmpEntry2->flags.IsDone) {
|
|
break;
|
|
}
|
|
DASSERT (TmpEntry2 != NULL);
|
|
TmpEntry1 = TmpEntry2;
|
|
}
|
|
|
|
// If we're out of types, don't bother with the stack
|
|
|
|
if (NoMoTypes) {
|
|
recursive = FALSE;
|
|
TmpEntry2->flags.IsMatched = TRUE;
|
|
TmpEntry2->CompactedIndex = T_NOTYPE;
|
|
return (T_NOTYPE);
|
|
} else {
|
|
recursive = TRUE;
|
|
DASSERT(StackPointer != 0);
|
|
SetRecursiveRoot (TmpEntry1->CompactedIndex);
|
|
return (OldIndex);
|
|
}
|
|
}
|
|
else if (NoMoTypes) {
|
|
recursive = FALSE;
|
|
OldEntry->flags.IsMatched = TRUE;
|
|
OldEntry->CompactedIndex = T_NOTYPE;
|
|
return (T_NOTYPE);
|
|
}
|
|
else if (OldEntry->flags.IsBeingDone) {
|
|
// Since this type is currently in the process of being compacted
|
|
// this type must eventually reference its own index. I.e. This
|
|
// is a recursive type.
|
|
|
|
recursive = TRUE; // Currently working on a recursive type.
|
|
|
|
// Set RecursiveRoot (the recursive index number we're currently looking
|
|
// for) to the deepest recursion level we have seen so far.
|
|
|
|
if (forward != T_NOTYPE) {
|
|
SetRecursiveRoot (forward);
|
|
}
|
|
else {
|
|
SetRecursiveRoot (OldIndex);
|
|
}
|
|
return (OldIndex);
|
|
}
|
|
else {
|
|
OldEntry->flags.IsBeingDone = TRUE; // being done
|
|
#if DBG
|
|
if (DbArray[6]) {
|
|
printf("Packing Local: 0x%4.4x\n", OldIndex);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Push (OldIndex);
|
|
|
|
OldRecursiveRoot = RecursiveRoot;
|
|
RecursiveRoot = 0;
|
|
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
switch (pType->leaf) {
|
|
case LF_LABEL:
|
|
case LF_BITFIELD: // The index in a bitfield is a primitive, don't call GetCompactedIndex
|
|
case LF_COBOL1:
|
|
case LF_NULL:
|
|
case LF_VTSHAPE:
|
|
case LF_REFSYM:
|
|
// These are valid leafs that don't have any type indexes that need
|
|
// compacting.
|
|
break;
|
|
|
|
case LF_COBOL0:
|
|
{
|
|
plfCobol0 plf = (plfCobol0)&pType->leaf;
|
|
|
|
|
|
type = C7GetCompactedIndexRecur (plf->type);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfCobol0)&pType->leaf;
|
|
plf->type = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfCobol0, type) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
|
|
case LF_MODIFIER:
|
|
{
|
|
plfModifier plf = (plfModifier)&pType->leaf;
|
|
|
|
DASSERT (plf->attr.MOD_unused == 0);
|
|
type = C7GetCompactedIndexRecur (plf->type);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfModifier)&pType->leaf;
|
|
plf->type = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfModifier, type) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_BARRAY:
|
|
{
|
|
plfBArray plf = (plfBArray)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->utype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfBArray)&pType->leaf;
|
|
plf->utype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfBArray, utype) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
|
|
case LF_POINTER:
|
|
{
|
|
DASSERT (i == 0);
|
|
CompactPtr (OldEntry);
|
|
break;
|
|
}
|
|
|
|
case LF_STRUCTURE:
|
|
case LF_CLASS:
|
|
{
|
|
plfClass plf = (plfClass)&pType->leaf;
|
|
|
|
plf->property.packed = FALSE; //M00Debug
|
|
DASSERT (plf->property.reserved == 0);
|
|
if (plf->property.fwdref) {
|
|
DASSERT (plf->property.packed == FALSE);
|
|
DASSERT (plf->property.ctor == FALSE);
|
|
DASSERT (plf->property.ovlops == FALSE);
|
|
DASSERT (plf->property.cnested == FALSE);
|
|
DASSERT (plf->property.opassign == FALSE);
|
|
DASSERT (plf->property.opcast == FALSE);
|
|
DASSERT (plf->vshape == T_NOTYPE);
|
|
DASSERT (plf->count == 0);
|
|
DASSERT (plf->field == T_NOTYPE);
|
|
|
|
fwdref:
|
|
// we have a forward reference, first see if it is
|
|
// defined later in this module or in the global table.
|
|
|
|
switch (FindFwdRef (OldEntry, &pHash, TRUE)){
|
|
case FWD_none:
|
|
break;
|
|
|
|
case FWD_local:
|
|
// definition found in this module
|
|
Pop ();
|
|
OldEntry->flags.IsForward = TRUE;
|
|
OldEntry->ForwardIndex = pHash->index;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
return (C7GetCompactedIndexRecur (pHash->index));
|
|
|
|
case FWD_global:
|
|
// definition found in global table
|
|
Pop ();
|
|
recursive = FALSE;
|
|
OldEntry->flags.IsDone = TRUE;
|
|
OldEntry->flags.IsMatched = TRUE;
|
|
DASSERT (pHash->index >= CV_FIRST_NONPRIM);
|
|
OldEntry->CompactedIndex = pHash->index;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
return (pHash->index);
|
|
|
|
case FWD_globalfwd:
|
|
// forward reference found in global table
|
|
|
|
Pop ();
|
|
recursive = FALSE;
|
|
OldEntry->flags.IsDone = TRUE;
|
|
OldEntry->flags.IsMatched = TRUE;
|
|
DASSERT (pHash->index >= CV_FIRST_NONPRIM);
|
|
OldEntry->CompactedIndex = pHash->index;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
return (pHash->index);
|
|
}
|
|
break;
|
|
}
|
|
else {
|
|
// see if the def'd structure had already packed global
|
|
// forward ref
|
|
|
|
if (FindFwdRef (OldEntry, &pHash, FALSE) == FWD_globalfwd){
|
|
Pop();
|
|
AddFwdRef(OldIndex, pHash);
|
|
recursive = FALSE;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
OldEntry->flags.IsMatched = TRUE;
|
|
return(OldEntry->CompactedIndex = pHash->index);
|
|
}
|
|
}
|
|
|
|
CompactClassStruct(OldEntry);
|
|
break;
|
|
}
|
|
|
|
case LF_UNION:
|
|
{
|
|
plfUnion plf = (plfUnion)&pType->leaf;
|
|
|
|
plf->property.packed = FALSE; //M00Debug
|
|
DASSERT (plf->property.reserved == 0);
|
|
if (plf->property.fwdref) {
|
|
DASSERT (plf->property.packed == FALSE);
|
|
DASSERT (plf->property.ctor == FALSE);
|
|
DASSERT (plf->property.ovlops == FALSE);
|
|
DASSERT (plf->property.cnested == FALSE);
|
|
DASSERT (plf->property.opassign == FALSE);
|
|
DASSERT (plf->property.opcast == FALSE);
|
|
DASSERT (plf->count == 0);
|
|
DASSERT (plf->field == T_NOTYPE);
|
|
goto fwdref;
|
|
}
|
|
else {
|
|
// see if the def'd structure had already packed global
|
|
// forward ref
|
|
|
|
if (FindFwdRef (OldEntry, &pHash, FALSE) == FWD_globalfwd){
|
|
Pop();
|
|
AddFwdRef(OldIndex, pHash);
|
|
recursive = FALSE;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
OldEntry->flags.IsMatched = TRUE;
|
|
return(OldEntry->CompactedIndex = pHash->index);
|
|
}
|
|
}
|
|
|
|
CompactUnion(OldEntry);
|
|
break;
|
|
}
|
|
|
|
case LF_ENUM:
|
|
{
|
|
plfEnum plf = (plfEnum)&pType->leaf;
|
|
|
|
plf->property.packed = FALSE; //M00Debug
|
|
DASSERT (plf->property.reserved == 0);
|
|
if (plf->property.fwdref) {
|
|
DASSERT (plf->property.packed == FALSE);
|
|
DASSERT (plf->property.ctor == FALSE);
|
|
DASSERT (plf->property.ovlops == FALSE);
|
|
DASSERT (plf->property.cnested == FALSE);
|
|
DASSERT (plf->property.opassign == FALSE);
|
|
DASSERT (plf->property.opcast == FALSE);
|
|
//DASSERT (plf->utype == 0);
|
|
DASSERT (plf->count == 0);
|
|
DASSERT (plf->field == T_NOTYPE);
|
|
goto fwdref;
|
|
}
|
|
else {
|
|
// see if the def'd structure had already packed global
|
|
// forward ref
|
|
|
|
if (FindFwdRef (OldEntry, &pHash, FALSE) == FWD_globalfwd){
|
|
Pop();
|
|
AddFwdRef(OldIndex, pHash);
|
|
recursive = FALSE;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
OldEntry->flags.IsMatched = TRUE;
|
|
return(OldEntry->CompactedIndex = pHash->index);
|
|
}
|
|
}
|
|
|
|
CompactEnum(OldEntry);
|
|
break;
|
|
}
|
|
|
|
case LF_ARRAY:
|
|
{
|
|
plfArray plf = (plfArray)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->elemtype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfArray)&pType->leaf;
|
|
plf->elemtype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfArray, elemtype) + LNGTHSZ));
|
|
type = C7GetCompactedIndexRecur (plf->idxtype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfArray)&pType->leaf;
|
|
plf->idxtype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfArray, idxtype) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_PROCEDURE:
|
|
{
|
|
plfProc plf = (plfProc)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->rvtype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfProc)&pType->leaf;
|
|
plf->rvtype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfProc, rvtype) + LNGTHSZ));
|
|
type = CompactList (plf->arglist, plf->parmcount);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfProc)&pType->leaf;
|
|
plf->arglist = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfProc, arglist) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_MFUNCTION:
|
|
{
|
|
plfMFunc plf = (plfMFunc)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->rvtype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfMFunc)&pType->leaf;
|
|
plf->rvtype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfMFunc, rvtype) + LNGTHSZ));
|
|
type = C7GetCompactedIndexRecur (plf->classtype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfMFunc)&pType->leaf;
|
|
plf->classtype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfMFunc, classtype) + LNGTHSZ));
|
|
type = C7GetCompactedIndexRecur (plf->thistype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfMFunc)&pType->leaf;
|
|
plf->thistype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfMFunc, thistype) + LNGTHSZ));
|
|
type = CompactList (plf->arglist, plf->parmcount);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfMFunc)&pType->leaf;
|
|
plf->arglist = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfMFunc, arglist) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_DEFARG:
|
|
{
|
|
plfDefArg plf = (plfDefArg)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->type);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfDefArg)&pType->leaf;
|
|
plf->type = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfDefArg, type) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_DIMARRAY: /* 7/23/92 by JK */
|
|
{
|
|
lfDimArray *plf = (lfDimArray *)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->utype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (lfDimArray *)&pType->leaf;
|
|
plf->utype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfDimArray, utype) + LNGTHSZ));
|
|
type = C7GetCompactedIndexRecur (plf->diminfo);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (lfDimArray *)&pType->leaf;
|
|
plf->diminfo = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfDimArray, diminfo) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_DIMCONU:
|
|
case LF_DIMCONLU:
|
|
{
|
|
lfDimCon *plf = (lfDimCon *)&pType->leaf;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->typ);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (lfDimCon *)&pType->leaf;
|
|
plf->typ = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfDimCon, typ) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case LF_DIMVARU:
|
|
case LF_DIMVARLU:
|
|
{
|
|
lfDimVar *plf = (lfDimVar *)&pType->leaf;
|
|
int count;
|
|
|
|
type = C7GetCompactedIndexRecur (plf->typ);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (lfDimVar *)&pType->leaf;
|
|
plf->typ = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfDimVar, typ) + LNGTHSZ));
|
|
count = plf->rank;
|
|
if(pType->leaf == LF_DIMVARLU) {
|
|
count *= 2;
|
|
}
|
|
while(count--) {
|
|
type = C7GetCompactedIndexRecur(((CV_typ_t *)plf->dim)[count]);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (lfDimVar *)&pType->leaf;
|
|
((CV_typ_t *)plf->dim)[count] = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof(lfDimVar,dim[count*sizeof(CV_typ_t)]) + LNGTHSZ));
|
|
}
|
|
break;
|
|
}
|
|
|
|
case LF_OEM:
|
|
{
|
|
lfOEM *plf = (lfOEM *)&pType->leaf;
|
|
int count;
|
|
|
|
for (count = plf->count; count; count--) {
|
|
type = C7GetCompactedIndexRecur(((CV_typ_t *)plf->index)[count]);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (lfOEM *)&pType->leaf;
|
|
((CV_typ_t *)plf->index)[count] = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof(lfOEM,index[count*sizeof(CV_typ_t)]) + LNGTHSZ));
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
ErrorExit (ERR_TYPE, FormatMod(pCurMod), NULL);
|
|
break;
|
|
}
|
|
}
|
|
Pop ();
|
|
|
|
if (RecursiveRoot == OldIndex) {
|
|
// This type eventually references it's own type index
|
|
// We have compacted every type this type references except this one
|
|
// and possibly some recursive types that reference this type.
|
|
// Now check the special global table used for recursive indexes and
|
|
// see if this type matches it. If a match is not found put the
|
|
// new recursive type in the global table.
|
|
|
|
recursive = FALSE;
|
|
|
|
// Restore the recursive root we were using before we had to call
|
|
// ourselves. The call may have modified it by compacting a
|
|
// recursive type.
|
|
OldEntry->CompactedIndex = GetRecursiveIndex (OldEntry, OldIndex);
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
return (OldEntry->CompactedIndex);
|
|
}
|
|
else if (RecursiveRoot != 0) {
|
|
recursive = TRUE;
|
|
OldEntry->CompactedIndex = RecursiveRoot;
|
|
SetRecursiveRoot (OldRecursiveRoot);
|
|
OldEntry->flags.IsDone = TRUE;
|
|
return (OldIndex);
|
|
}
|
|
else {
|
|
// We are not compacting a type that references itself.
|
|
// So just try to find a matching string in the global table.
|
|
|
|
recursive = FALSE;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
OldEntry->flags.IsInserted = TRUE;
|
|
MatchIndex (OldEntry);
|
|
return (OldEntry->CompactedIndex);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** CompactPtr - A subfunction of GetCompactedIndex used to compact C7
|
|
* style pointer and based pointer type records.
|
|
*
|
|
* CompactPtr (OldEntry)
|
|
*
|
|
* Entry OldEntry - The entry information for the index.
|
|
*
|
|
* Exit OldEntry->TypeString - new C7 style LF_POINTER string
|
|
* containing compacted indexes.
|
|
* OldEntry->IndexUnion - Contains recursive index info.
|
|
*
|
|
* Return The number of entries in the IndexUnion
|
|
*/
|
|
|
|
|
|
uchar _fastcall
|
|
CompactPtr(
|
|
TENTRY *OldEntry
|
|
)
|
|
{
|
|
TYPPTR pType;
|
|
plfPointer plf;
|
|
CV_typ_t *pIndex;
|
|
pCompactFcnType pCompactFcn;
|
|
CV_typ_t type;
|
|
|
|
// Setup pointer to call C6GetCompactedIndex or C7GetCompactedIndexRecur
|
|
// This allows both of these routines to share this code
|
|
|
|
pCompactFcn = GetCompactedIndexFcn[ulCVTypeSignature];
|
|
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfPointer)&pType->leaf;
|
|
|
|
// Compact the type index of the underlying type
|
|
|
|
type = pCompactFcn (plf->utype);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfPointer)&pType->leaf;
|
|
plf->utype = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfPointer, utype) + LNGTHSZ));
|
|
|
|
switch (plf->attr.ptrmode){
|
|
case CV_PTR_MODE_PTR:
|
|
{
|
|
switch (plf->attr.ptrtype) {
|
|
case CV_PTR_BASE_VAL:
|
|
case CV_PTR_BASE_SEGVAL:
|
|
case CV_PTR_BASE_ADDR:
|
|
case CV_PTR_BASE_SEGADDR:
|
|
{
|
|
ushort usOff; // offset of index within the symbol
|
|
|
|
// The variable length data is a complete symbol record,
|
|
// so compact the index within the symbol.
|
|
|
|
// Get the offset to the index
|
|
switch (((SYMPTR)(plf->pbase.Sym))->rectyp) {
|
|
case S_REGISTER:
|
|
usOff = offsetof (lfPointer, pbase.Sym) +
|
|
offsetof (REGSYM, typind) + LNGTHSZ;
|
|
break;
|
|
|
|
case S_BPREL16:
|
|
usOff = offsetof (lfPointer, pbase.Sym) +
|
|
offsetof (BPRELSYM16, typind) + LNGTHSZ;
|
|
break;
|
|
|
|
case S_BPREL32:
|
|
usOff = offsetof (lfPointer, pbase.Sym) +
|
|
offsetof (BPRELSYM32, typind) + LNGTHSZ;
|
|
break;
|
|
|
|
case S_LDATA16:
|
|
case S_GDATA16:
|
|
usOff = offsetof (lfPointer, pbase.Sym) +
|
|
offsetof (DATASYM16, typind) + LNGTHSZ;
|
|
break;
|
|
|
|
case S_LDATA32:
|
|
case S_GDATA32:
|
|
case S_LTHREAD32:
|
|
case S_GTHREAD32:
|
|
usOff = offsetof (lfPointer, pbase.Sym) +
|
|
offsetof (DATASYM32, typind) + LNGTHSZ;
|
|
break;
|
|
|
|
default:
|
|
DASSERT (FALSE);
|
|
break;
|
|
|
|
}
|
|
pIndex = (CV_typ_t *)(OldEntry->TypeString + usOff);
|
|
type = pCompactFcn (*pIndex);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfPointer)&pType->leaf;
|
|
pIndex = (CV_typ_t *)(OldEntry->TypeString + usOff);
|
|
*pIndex = type;
|
|
DASSERT (usOff < 255);
|
|
UpdateSmallIndexUnion(OldEntry, (uchar)usOff);
|
|
break;
|
|
}
|
|
|
|
case CV_PTR_BASE_TYPE:
|
|
{
|
|
type = pCompactFcn (plf->pbase.btype.index);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfPointer)&pType->leaf;
|
|
plf->pbase.btype.index = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfPointer, pbase.btype.index) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
// These are valid but have nothing to compact
|
|
case CV_PTR_BASE_SEG:
|
|
case CV_PTR_NEAR:
|
|
case CV_PTR_FAR:
|
|
case CV_PTR_HUGE:
|
|
case CV_PTR_NEAR32:
|
|
case CV_PTR_FAR32:
|
|
case CV_PTR_BASE_SELF:
|
|
{
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DASSERT (FALSE);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CV_PTR_MODE_PMEM:
|
|
case CV_PTR_MODE_PMFUNC:
|
|
{
|
|
type = pCompactFcn (plf->pbase.pm.pmclass);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfPointer)&pType->leaf;
|
|
plf->pbase.pm.pmclass = type;
|
|
UpdateSmallIndexUnion(OldEntry,
|
|
(uchar)(offsetof (lfPointer, pbase.pm.pmclass) + LNGTHSZ));
|
|
break;
|
|
}
|
|
|
|
case CV_PTR_MODE_REF:
|
|
{
|
|
break; // No variant
|
|
}
|
|
|
|
default:
|
|
{
|
|
DASSERT (FALSE);
|
|
break;
|
|
}
|
|
}
|
|
return ((uchar)OldEntry->Count); // UNDONE: Loss of Precision???
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* CompactList
|
|
*
|
|
* Similar to GetCompactedIndex, except it is for type index lists
|
|
* of structures or procedures, field specification lists, or
|
|
* method lists
|
|
*
|
|
* If necessary this function will call GetCompactedIndex. It uses
|
|
* ulCvTypeSignature to determine whether to call the C6 or C7 version
|
|
* of this routine. It also uses usCurFirstNonPrim which will either
|
|
* be 512 or 0x1000.
|
|
*
|
|
*/
|
|
|
|
COUNTER (cnt_CompactList1);
|
|
COUNTER (cnt_CompactList2);
|
|
|
|
CV_typ_t _fastcall
|
|
CompactList(
|
|
CV_typ_t OldIndex,
|
|
ushort Count
|
|
)
|
|
{
|
|
TENTRY *OldEntry;
|
|
TYPPTR pType;
|
|
CV_typ_t OldRecursiveRoot;
|
|
ushort index = 0;
|
|
ushort usElNum;
|
|
pCompactFcnType pCompactFcn;
|
|
CV_typ_t forward;
|
|
CV_typ_t type;
|
|
ushort offset;
|
|
|
|
DASSERT (OldIndex >= usCurFirstNonPrim);
|
|
|
|
DASSERT (OldIndex < MaxIndex + usCurFirstNonPrim || (OldIndex == ZEROARGTYPE));
|
|
COUNT (cnt_CompactList1);
|
|
OldEntry = GetTypeEntry ((CV_typ_t)(OldIndex - usCurFirstNonPrim), &forward);
|
|
DASSERT (OldEntry != NULL);
|
|
DASSERT (OldEntry->flags.IsNewFormat);
|
|
|
|
if (OldEntry->flags.IsInserted || OldEntry->flags.IsMatched ||
|
|
OldEntry->flags.IsPreComp) {
|
|
recursive = FALSE;
|
|
return (OldEntry->CompactedIndex);
|
|
}
|
|
else if (OldEntry->flags.IsDone) {
|
|
TENTRY *TmpEntry1 = OldEntry;
|
|
TENTRY *TmpEntry2;
|
|
CV_typ_t dummy;
|
|
|
|
while (TRUE) {
|
|
COUNT (cnt_CompactList2);
|
|
TmpEntry2 = GetTypeEntry ((CV_typ_t)(TmpEntry1->CompactedIndex - CV_FIRST_NONPRIM),
|
|
&dummy);
|
|
if (!TmpEntry2->flags.IsDone) {
|
|
break;
|
|
}
|
|
DASSERT (TmpEntry2 != NULL);
|
|
TmpEntry1 = TmpEntry2;
|
|
}
|
|
|
|
recursive = TRUE;
|
|
SetRecursiveRoot (TmpEntry1->CompactedIndex);
|
|
return (OldIndex);
|
|
}
|
|
else if (OldEntry->flags.IsBeingDone) {
|
|
// recursive?
|
|
recursive = TRUE;
|
|
SetRecursiveRoot (OldIndex); // put it on stack
|
|
return (OldIndex); // return
|
|
}
|
|
else {
|
|
OldEntry->flags.IsBeingDone = TRUE; // being done
|
|
#if DBG
|
|
if (DbArray[6]) {
|
|
printf("Packing Local: 0x%4.4x\n", OldIndex);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Push (OldIndex);
|
|
OldRecursiveRoot = RecursiveRoot;
|
|
RecursiveRoot = 0;
|
|
pType = (TYPPTR) OldEntry->TypeString;
|
|
|
|
|
|
// Setup pointer to call C6GetCompactedIndex or C7GetCompactedIndexRecur
|
|
// This allows both of these routines to share this code
|
|
|
|
DASSERT (ulCVTypeSignature < sizeof (GetCompactedIndexFcn) / sizeof (GetCompactedIndexFcn[0]));
|
|
pCompactFcn = GetCompactedIndexFcn[ulCVTypeSignature];
|
|
OldEntry->Count = 0;
|
|
switch (pType->leaf){
|
|
case LF_ARGLIST:
|
|
{
|
|
plfArgList plf = (plfArgList)&pType->leaf;
|
|
for (usElNum = 0; usElNum < Count; usElNum++) {
|
|
|
|
// Call C6GetCompactedIndex or C7GetCompactedIndexRecur
|
|
|
|
type = pCompactFcn (plf->arg[usElNum]);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (plfArgList)&pType->leaf;
|
|
plf->arg[usElNum] = type;
|
|
index = (uchar *)&(plf->arg[usElNum]) - (uchar *)pType;
|
|
SaveOffset (OldEntry, index);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case LF_METHODLIST:
|
|
{
|
|
pmlMethod plf;
|
|
|
|
offset = 0;
|
|
for (usElNum = 0; usElNum < Count; usElNum++) {
|
|
|
|
// Call C6GetCompactedIndex or C7GetCompactedIndexRecur
|
|
|
|
plf = (pmlMethod)(((uchar *)&((plfMethod)pType)->mList) + offset);
|
|
type = pCompactFcn (plf->index);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
plf = (pmlMethod)(((uchar *)&((plfMethod)pType)->mList) + offset);
|
|
plf->index = type;
|
|
index = (uchar *)&(plf->index) - OldEntry->TypeString;
|
|
|
|
if (plf->attr.mprop == CV_MTintro){
|
|
// Move past fixed length structure + offset
|
|
offset += sizeof (mlMethod) + sizeof (long);
|
|
}
|
|
else {
|
|
// Move past fixed length structure
|
|
offset += sizeof (mlMethod);
|
|
}
|
|
if (index != 0){
|
|
SaveOffset (OldEntry, index);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
case LF_FIELDLIST:
|
|
{
|
|
uchar *pField;
|
|
|
|
offset = 0;
|
|
for (usElNum = Count; usElNum > 0; usElNum--) {
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
index = 0;
|
|
switch (((plfEasy)(pField + offset))->leaf) {
|
|
case LF_MEMBER:
|
|
{
|
|
plfMember plf = (plfMember)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfMember)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += offsetof (lfMember, offset);
|
|
offset += C7SizeOfNumeric (pField + offset);
|
|
offset += *(pField + offset) + 1;
|
|
break;
|
|
}
|
|
|
|
case LF_BCLASS:
|
|
{
|
|
plfBClass plf = (plfBClass)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfBClass)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += offsetof (lfBClass, offset);
|
|
offset += C7SizeOfNumeric (pField + offset);
|
|
break;
|
|
}
|
|
|
|
case LF_VBCLASS:
|
|
case LF_IVBCLASS:
|
|
{
|
|
plfVBClass plf = (plfVBClass)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfVBClass)(pField + offset);
|
|
plf->index = type;
|
|
SaveOffset (OldEntry,
|
|
(ushort)((uchar *)(&(plf->index)) - (uchar *)pType));
|
|
type = pCompactFcn (plf->vbptr);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfVBClass)(pField + offset);
|
|
plf->vbptr = type;
|
|
SaveOffset (OldEntry,
|
|
(ushort)((uchar *)(&(plf->vbptr)) - (uchar *)pType));
|
|
offset += offsetof (lfVBClass, vbpoff);
|
|
offset += C7SizeOfNumeric (pField + offset);
|
|
offset += C7SizeOfNumeric (pField + offset);
|
|
break;
|
|
}
|
|
|
|
case LF_FRIENDCLS:
|
|
{
|
|
plfFriendCls plf = (plfFriendCls)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfFriendCls)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += sizeof (lfFriendCls);
|
|
break;
|
|
}
|
|
|
|
case LF_FRIENDFCN:
|
|
{
|
|
plfFriendFcn plf = (plfFriendFcn)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfFriendFcn)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += sizeof (lfFriendFcn) + plf->Name[0];;
|
|
break;
|
|
}
|
|
|
|
case LF_STMEMBER:
|
|
{
|
|
plfSTMember plf = (plfSTMember)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfSTMember)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += sizeof (lfSTMember) + plf->Name[0];
|
|
break;
|
|
}
|
|
|
|
case LF_VFUNCTAB:
|
|
{
|
|
plfVFuncTab plf = (plfVFuncTab)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->type);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfVFuncTab)(pField + offset);
|
|
plf->type = type;
|
|
index = (uchar *)(&(plf->type)) - (uchar *)pType;
|
|
offset += sizeof (lfVFuncTab);
|
|
break;
|
|
}
|
|
|
|
case LF_METHOD:
|
|
{
|
|
plfMethod plf = (plfMethod)(pField + offset);
|
|
|
|
type = CompactList (plf->mList, plf->count);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfMethod)(pField + offset);
|
|
plf->mList = type;
|
|
index = (uchar *)(&(plf->mList)) - (uchar *)pType;
|
|
offset += sizeof (lfMethod) + plf->Name[0];
|
|
|
|
// FieldList count includes sum of LF_METHOD counts.
|
|
|
|
usElNum -= plf->count - 1;
|
|
break;
|
|
}
|
|
|
|
case LF_ONEMETHOD:
|
|
{
|
|
plfOneMethod plf = (plfOneMethod)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfOneMethod)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += offsetof (lfOneMethod, vbaseoff);
|
|
offset += (plf->attr.mprop == CV_MTintro) ?
|
|
sizeof(long) : 0;
|
|
offset += *(pField + offset) + 1;
|
|
break;
|
|
}
|
|
|
|
case LF_ENUMERATE:
|
|
{
|
|
plfEnumerate plf = (plfEnumerate)(pField + offset);
|
|
|
|
offset += offsetof (lfEnumerate, value);
|
|
offset += C7SizeOfNumeric (pField + offset);
|
|
offset += *(pField + offset) + 1;
|
|
break;
|
|
}
|
|
|
|
case LF_NESTTYPE:
|
|
{
|
|
plfNestType plf = (plfNestType)(pField + offset);
|
|
|
|
type = pCompactFcn (plf->index);
|
|
DASSERT ((uchar *)pType == OldEntry->TypeString);
|
|
pType = (TYPPTR)OldEntry->TypeString;
|
|
pField = (uchar *)&pType->data;
|
|
plf = (plfNestType)(pField + offset);
|
|
plf->index = type;
|
|
index = (uchar *)(&(plf->index)) - (uchar *)pType;
|
|
offset += sizeof (lfNestType) + plf->Name[0];
|
|
break;
|
|
}
|
|
|
|
// When a LF_FIELDLIST is continued to another type. Compact this
|
|
// information by appending the second type to the first.
|
|
case LF_INDEX:
|
|
{
|
|
IndexLeaf ((plfIndex)(pField + offset), OldEntry);
|
|
pType = (TYPPTR)(OldEntry->TypeString);
|
|
pField = (uchar *)&pType->data;
|
|
usElNum++; // no decrement for this one
|
|
break;
|
|
}
|
|
|
|
|
|
default:
|
|
DASSERT (FALSE && *pField);
|
|
break;
|
|
}
|
|
|
|
// Skip any pad bytes if not last field
|
|
|
|
if (usElNum > 1) {
|
|
if (*(pField + offset) >= LF_PAD0){
|
|
offset += *(pField + offset) & 0x0F;
|
|
}
|
|
}
|
|
|
|
if (index != 0) {
|
|
SaveOffset (OldEntry, index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Pop ();
|
|
|
|
if (RecursiveRoot == OldIndex) {
|
|
// This type eventually references it's own type index
|
|
// We have compacted every type this type references except this one
|
|
// and possibly some recursive types that reference this type.
|
|
// Now check the special global table used for recursive indexes and
|
|
// see if this type matches it. If a match is not found put the
|
|
// new recursive type in the global table.
|
|
|
|
recursive = FALSE;
|
|
|
|
// Restore the recursive root we were using before we had to call
|
|
// ourselves. The call may have modified it by compacting a
|
|
// recursive type.
|
|
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
OldEntry->CompactedIndex = GetRecursiveIndex (OldEntry, OldIndex);
|
|
return (OldEntry->CompactedIndex);
|
|
}
|
|
else if (RecursiveRoot != 0) {
|
|
recursive = TRUE;
|
|
OldEntry->CompactedIndex = RecursiveRoot;
|
|
SetRecursiveRoot (OldRecursiveRoot);
|
|
OldEntry->flags.IsDone = TRUE;
|
|
return (OldIndex);
|
|
}
|
|
else {
|
|
// We are not compacting a type that references itself.
|
|
// So just try to find a matching string in the global table.
|
|
|
|
recursive = FALSE;
|
|
RecursiveRoot = OldRecursiveRoot;
|
|
OldEntry->flags.IsInserted = TRUE;
|
|
MatchIndex (OldEntry);
|
|
return (OldEntry->CompactedIndex);
|
|
}
|
|
}
|
|
|
|
LOCAL void _fastcall
|
|
SaveOffset1(
|
|
TENTRY *OldEntry,
|
|
ushort index
|
|
)
|
|
{
|
|
ushort i;
|
|
uchar *GlobalString;
|
|
ushort *IndexString;
|
|
|
|
if ((index > 0xff) || (OldEntry->Count >= RECURSE_INC)) {
|
|
if (!(OldEntry->flags.LargeList)) {
|
|
IndexString = (ushort *) CAlloc(sizeof(ushort) * 2 * RECURSE_INC);
|
|
GlobalString = (uchar *) CAlloc(sizeof(uchar) * 8 * RECURSE_INC);
|
|
for (i = 0; i < OldEntry->Count; i++) {
|
|
(IndexString)[i] = OldEntry->IndexUnion.Index[i];
|
|
}
|
|
GlobalString[0] = OldEntry->GlobalIndex;
|
|
OldEntry->IndexUnion.IndexString = IndexString;
|
|
OldEntry->GlobalIndexString = GlobalString;
|
|
}
|
|
else
|
|
if ((OldEntry->Count % (RECURSE_INC * 2)) == 0) {
|
|
IndexString = (ushort *) CAlloc(sizeof(ushort) * (OldEntry->Count + (RECURSE_INC * 2)));
|
|
|
|
for (i = 0; i < OldEntry->Count; i++) {
|
|
IndexString[i] = OldEntry->IndexUnion.IndexString[i];
|
|
}
|
|
|
|
free(OldEntry->IndexUnion.IndexString);
|
|
OldEntry->IndexUnion.IndexString = IndexString;
|
|
|
|
if ((OldEntry->Count % 8) == 0) {
|
|
GlobalString =
|
|
(uchar *) CAlloc(sizeof(uchar) * (OldEntry->Count + (RECURSE_INC * 2)));
|
|
|
|
for (i = 0; i < OldEntry->Count % 8; i++) {
|
|
GlobalString[i] = OldEntry->GlobalIndexString[i];
|
|
}
|
|
|
|
free(OldEntry->GlobalIndexString);
|
|
OldEntry->GlobalIndexString = GlobalString;
|
|
}
|
|
}
|
|
OldEntry->IndexUnion.IndexString[OldEntry->Count] = index;
|
|
OldEntry->flags.LargeList = TRUE;
|
|
}
|
|
else {
|
|
OldEntry->IndexUnion.Index[OldEntry->Count] = (uchar)index;
|
|
}
|
|
OldEntry->Count++;
|
|
}
|
|
|
|
INLINE void
|
|
SaveOffset(
|
|
TENTRY *OldEntry,
|
|
ushort index
|
|
)
|
|
{
|
|
if (recursive) {
|
|
SaveOffset1(OldEntry, index);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** IndexLeaf - handle an index leaf
|
|
*
|
|
* Appends the referenced type information to the type that referenced
|
|
* it.
|
|
*
|
|
* IndexLeaf (plfInd, OldEntry)
|
|
*
|
|
* Entry plfInd = Pointer to the index leaf within OldEntry->TypeString
|
|
* OldEntry = Old Type entry that references another type.
|
|
* This type entry will be a LF_FIELDLIST.
|
|
*
|
|
* Exit OldEntry->String points to an alloced string containing the
|
|
* original string with the index leaf replaced by the list data
|
|
* from the referenced type.
|
|
*/
|
|
|
|
LOCAL void
|
|
IndexLeaf(
|
|
plfIndex plfInd,
|
|
TENTRY *OldEntry
|
|
)
|
|
{
|
|
TENTRY *RefEntry; // Entry for continuation of the list
|
|
uchar *RefString; // Type string for the continuation of list
|
|
ushort i;
|
|
ushort length;
|
|
uchar * NewString;
|
|
CV_typ_t forward;
|
|
|
|
DASSERT (MaxIndex > plfInd->index - usCurFirstNonPrim);
|
|
RefEntry = GetTypeEntry ((CV_typ_t)(plfInd->index - usCurFirstNonPrim), &forward);
|
|
DASSERT (RefEntry != NULL);
|
|
DASSERT (forward == T_NOTYPE);
|
|
RefString = RefEntry->TypeString;
|
|
DASSERT (RefString != NULL);
|
|
DASSERT (((TYPPTR)RefString)->leaf == ((TYPPTR)(OldEntry->TypeString))->leaf);
|
|
|
|
// Calculate the length of the existing string excluding the Index field
|
|
|
|
i = (uchar *)plfInd - (uchar *)OldEntry->TypeString;
|
|
|
|
// Calculate the length of the field list data in the reference string
|
|
|
|
length = ((TYPPTR)RefString)->len - sizeof(((TYPPTR)RefString)->leaf);
|
|
|
|
// Allocate the string, and copy the original string into the new one
|
|
// and append the referenced field list data to the old string
|
|
|
|
if ((i + length) > POOL2SIZE) {
|
|
NewString = (uchar *) Alloc(i + length);
|
|
}
|
|
else if ((i + length) > POOLSIZE) {
|
|
NewString = (uchar *) Pool2Alloc();
|
|
}
|
|
else {
|
|
NewString = (uchar *) PoolAlloc();
|
|
}
|
|
memcpy (NewString, OldEntry->TypeString, i);
|
|
FreeAllocStrings (OldEntry);
|
|
OldEntry->TypeString = NewString;
|
|
if ((i + length) > POOL2SIZE) {
|
|
OldEntry->flags.IsMalloced = TRUE;
|
|
}
|
|
else if ((i + length) > POOLSIZE) {
|
|
OldEntry->flags.IsPool2 = TRUE;
|
|
}
|
|
else {
|
|
OldEntry->flags.IsPool = TRUE;
|
|
}
|
|
memcpy ((uchar *)NewString + i, ((TYPPTR)RefString)->data, length);
|
|
|
|
// set length of combined string to length of old string
|
|
// - sizeof (index leaf) + length of new string
|
|
|
|
((TYPPTR)(OldEntry->TypeString))->len += length - sizeof (lfIndex);
|
|
}
|