Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

3490 lines
95 KiB

/** tables.c - build and maintain internal tables
*
* string hash routines, type hash routines, and
* compacted segment information
*/
#include <ctype.h>
#include "compact.h"
#include "writebuf.h"
#define CB_ATOMIC 8100 // 8100 gives room for 8 allocs + header in 1 segment
#if defined (DOS)
#define INDEXBLOCKSIZE 256 // table size multiple
#define TYPEBLOCKSIZE 0x4000 // size of compacted types sub table
#define SYMBLOCKSIZE 4096
#define NameHashBlockSize 4096
#define OffHashBlockSize 4096
#define MINHASH 6 // minimum size of hash table
#define HASH_STRING 256 // String hash table size
#define HASH_TYPE 256 // Type hash table size
#define HASH_SYM 256 // Symbol hash table size
#define HASH_COMDAT 128 // ComDat hash table size
#define HASH_NAME 128 // Globals subsection hash size
#define HASH_FWD 128 // hash size for forward definition
#else
#define INDEXBLOCKSIZE (_HEAP_MAXREQ / sizeof (TENTRY))
// module type index pointer table multiple
#define TYPEBLOCKSIZE 0x7f00 // size of compacted types sub table
#define SYMBLOCKSIZE 4096 //
#define NameHashBlockSize 4096
#define OffHashBlockSize 4096
#define MINHASH 6 // minimum size of hash table
#define HASH_STRING 4096 // String hash table size
#define HASH_TYPE 4096 // Type hash table size
#define HASH_SYM 4096 // Symbol hash table size
#define HASH_COMDAT 4096 // ComDat hash table size
#define HASH_NAME 4096 // Globals subsection hash size
#define HASH_FWD 512 // hash size for forward definition
#endif
#define DLIST_INC 20 // number of derived classes
#define DCLASS_INC 128 // number of structures
// This hash table is used to hash local structures, class, unions
// and enums so that they can be quickly found for satisfying forward
// references. The hash is the sum of characters in the name.
HSFWD **HTLocalFwd = NULL;
HSFWD **HTGlobalFwd = NULL;
// This hash table is used to hash recursive type records that have
// been added to the global symbol table. The hash is the sum of bytes
// of all bytes that do not contain a recursive type index.
typedef struct HSTYPE {
uchar *Type;
CV_typ_t GlobalIndex;
struct HSTYPE *Next;
} HSTYPE;
HSTYPE **HTType = NULL;
ushort *HTTypeCnt = NULL;
// This hash table is used to hash non-recursive type records that have
// been added to the global symbol table. The hasf is the sum of bytes
// of all bytes in the type record.
typedef struct HSSTRING {
CV_typ_t CompactedIndex;
TYPPTR TypeString;
struct HSSTRING *Next;
} HSSTRING;
HSSTRING **HTString = NULL;
ushort *HTStringCnt = NULL;
// These hash tables are used to hash the public symbols and the module
// level symbols that have been moved from the module to the global
// symbol table.
typedef struct GLOBALSYM {
struct GLOBALSYM *Next;
uint indName;
ulong sumName;
uchar Sym[];
} GLOBALSYM;
GLOBALSYM **HTSym = NULL;
GLOBALSYM **HTPub = NULL;
typedef struct HSCOMDAT {
ushort Seg;
ulong Offset;
ushort Type;
ushort Sum;
struct HSCOMDAT *Next;
uchar Name[1];
} HSCOMDAT;
HSCOMDAT **HTComDat = NULL;
typedef struct DCLASS {
ushort BClass; // base class type index
ushort Count; // number of classes derived from this class
ushort Max; // maximum list size
ushort *List; // pointer to list of derived classes
} DCLASS;
typedef DCLASS *PDCLASS;
#define cBucketSize 10
#define cbMaxAlloc 0xFFE0
#define culEct (cBucketSize + cBucketSize / 4)
#define OVFL_C (cBucketSize / 2)
// Entry in the Chain Overflow Table
// This structure is used when the number of entries hashed to a
// single bucket exceeds the estimate of cBucketSize
typedef struct _OVFL {
struct _OVFL *pOvflNext; // pointer to next chain
ulong rgulSymbol [OVFL_C]; // array of symbol offsets
} OVFL;
typedef OVFL *POVFL;
// Entry int the Chain Table
typedef struct _ECT {
ushort culSymbol; // count of symbols in chain
POVFL pOvflNext; // pointer to overflow chain
ulong rgulSymbol[culEct]; // array of symbol offsets
} ECT;
typedef ECT *PECT;
#define cectMax (cbMaxAlloc / sizeof (ECT)) // maximum chains per segment
#define cecetMax (cbMaxAlloc / sizeof (OVFL)) // maximum extended chains per seg
#define cpecetMax 10
LOCAL void AddDerivationListsToTypeSegment (void);
LOCAL ushort StringHash (uchar *);
bool_t IdenticalTypes (TYPPTR, TYPPTR);
LOCAL void AddToDerivationList (CV_typ_t, CV_typ_t);
LOCAL int TypeHash (TENTRY *);
LOCAL int ComDatHash (uchar *, ushort *);
LOCAL void CleanUpModuleIndexTable (void);
LOCAL GPS_t InGlobalSym (SYMPTR);
LOCAL void BuildHash (LPFNHASH, ushort *, ulong *, VBuf *, ulong, GLOBALSYM **);
LOCAL void BuildSort (ushort *, ulong *, VBuf *, ulong, GLOBALSYM **);
LOCAL void AddTypeEntry (uchar *, bool_t, bool_t, bool_t, CV_typ_t, ushort);
LOCAL void InitModTypeTable (void);
LOCAL void MapPreComp (plfPreComp);
LOCAL PMOD FindModule (char *);
LOCAL FWD_t FindLocalFwd (ushort, char *, HSFWD **);
LOCAL FWD_t FindGlobalFwd (ushort, char *, HSFWD **);
LOCAL void HashFwd (TYPPTR, CV_typ_t, HSFWD **);
LOCAL ushort SubHash (TENTRY *OldEntry, int iitem);
PDCLASS DLists;
ushort NextInDerivation = 0;
ushort MaxDerivation;
uchar **GlobalIndexTable = NULL;
GTYPE RgGType[65536];
ushort errIndex;
CV_typ_t NewIndex = CV_FIRST_NONPRIM; // start for new types
ushort LastGlobalTableIndex; // last possible index
ushort AddNewSymbols; // need to add typedefs?
ulong cGlobalSym = 0; // total number of global symbols
ulong cbGlobalSym = 0; // total number of bytes in global symbols
ulong cPublics = 0; // total number of publics
ulong cbPublics = 0; // total number of bytes in publics
ulong cGlobalDel = 0; // total number of global symbols
ushort cSeg;
ushort segnum[MAXCDF];
ushort usInitCount;
extern uchar **ExtraSymbolLink;
extern uchar *ExtraSymbols;
extern ushort UDTAdd;
extern ulong ulCVTypeSignature; // The signature from the modules type segment
ulong InitialTypeInfoSize = 0;
CV_typ_t MaxIndex; // Maximum index for module
ushort IndexBlocks = 0;
struct BlockListEntry *BlockList = NULL;
struct BlockListEntry *cur;
VBuf SymBuf;
VBuf TypeBuf;
// A null LF_ARGLIST entry created at init time.
TENTRY *ZeroArg;
// remembers if we need to clear the first TENTRY block
bool_t fPendingInit;
extern bool_t FDebug;
/** InitializeTables
*
* Initialize the various tables and allocate space on the heap
* for them
*
* Entry none
*
* Exit tables initialized
*
* Returns none
*
*/
void InitializeTables (void)
{
plfArgList plf;
HTType = (HSTYPE **) CAlloc (HASH_TYPE * sizeof (HSTYPE *));
HTTypeCnt = (ushort *) CAlloc (HASH_TYPE * sizeof (ushort));
HTString = (HSSTRING **) CAlloc (HASH_STRING * sizeof (HSSTRING *));
HTStringCnt = (ushort *) CAlloc (HASH_STRING * sizeof (ushort));
HTSym = (GLOBALSYM **) CAlloc (HASH_SYM * sizeof (GLOBALSYM *));
HTPub = (GLOBALSYM **) CAlloc (HASH_SYM * sizeof (GLOBALSYM *));
HTComDat = (HSCOMDAT **) CAlloc (HASH_COMDAT * sizeof (HSCOMDAT *));
DLists = (PDCLASS) CAlloc (DCLASS_INC * sizeof (DCLASS));
HTLocalFwd = (HSFWD **)CAlloc (HASH_FWD * sizeof (HSFWD *));
HTGlobalFwd = (HSFWD **)CAlloc (HASH_FWD * sizeof (HSFWD *));
MaxDerivation = DCLASS_INC;
LastGlobalTableIndex = 0;
VBufInit (&SymBuf, SYMBLOCKSIZE);
VBufInit (&TypeBuf, TYPEBLOCKSIZE);
// create and initialize the null argument list
ZeroArg = CAlloc (sizeof (TENTRY));
ZeroArg->TypeString = Alloc (offsetof (lfArgList, arg[0]) + LNGTHSZ);
ZeroArg->flags.IsNewFormat = TRUE;
// Create the type string
((TYPPTR)(ZeroArg->TypeString))->len = offsetof (lfArgList, arg[0]) + LNGTHSZ;
plf = (plfArgList) (ZeroArg->TypeString + LNGTHSZ);
plf->leaf = LF_ARGLIST;
plf->count = 0;
}
/**
*
* CleanUpTables
*
* Free the various tables that have been allocated
*
*/
void CleanUpTables (void)
{
AddDerivationListsToTypeSegment ();
free (DLists);
free (HTType);
free (HTString);
// free (HTSym);
free (HTComDat);
}
#if defined (INCREMENTAL)
/** RestoreIndex - restore type index to global table
*
*/
void RestoreIndex (ushort cb)
{
int i;
HSSTRING *j;
TYPPTR pType;
ushort leaf;
uchar buf[100];
uint count;
static FoundDerived = FALSE;
uchar **pBuf;
if (read (exefile, &leaf, sizeof (leaf)) != sizeof (leaf)) {
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
}
cb -= sizeof (leaf);
if (leaf == LF_DERIVED) {
while (cb > 0) {
// throw away derivation leaf
count = min (cb, sizeof (buf));
read (exefile, buf, count);
cb -= count;
}
FoundDerived = TRUE;
return;
}
else if (FoundDerived == TRUE) {
DASSERT (FALSE);
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
}
if ((NewIndex - (CV_typ_t)CV_FIRST_NONPRIM) == LastGlobalTableIndex) {
LastGlobalTableIndex += GTYPE_INC;
pBuf = Alloc (GTYPE_INC * sizeof (uchar *));
pGType[(NewIndex - CV_FIRST_NONPRIM) / GTYPE_INC] = pBuf;
}
pBuf = pGType[(NewIndex - CV_FIRST_NONPRIM) / GTYPE_INC];
pBuf[(NewIndex - CV_FIRST_NONPRIM) % GTYPE_INC] =
VBufRead (&TypeBuf, cb, leaf);
pType = (TYPPTR)(pBuf[(NewIndex - CV_FIRST_NONPRIM) % GTYPE_INC]);
i = StringHash ((uchar *)pType);
j = (HSSTRING *)Alloc (sizeof (HSSTRING));
j->TypeString = pType;
j->CompactedIndex = NewIndex++;
if (NewIndex == 0) {
ErrorExit (ERR_65KTYPES, FormatMod (pCurMod), NULL);
}
j->Next = HTString[i];
HTString[i] = j;
HTStringCnt[i]++;
}
#endif
/** MatchIndex - find the compacted index of a non-recursive type
*
* MatchIndex (OldEntry)
*
* Entry OldEntry = pointer to type entry
*
* Exit OldEntry->TypeString added to global type table if not present
* OldEntry->CompactedIndex = global type index
*/
COUNTER (cnt_MatchIndex1)
COUNTER (cnt_MatchIndex2)
void MatchIndex (TENTRY *OldEntry)
{
ushort i;
HSSTRING *j;
plfClass plf;
TYPPTR pType;
uchar *pName;
HSFWD *pHash;
DASSERT (OldEntry->flags.IsNewFormat);
// search through nonrecursive hash list looking for matching entry
i = StringHash (OldEntry->TypeString);
for (j = HTString[i]; j != NULL; j = j->Next) {
if (j->TypeString != NULL) {
// a intermodule forward reference will end up having a
// null pointer to the type string when it is replaced
if (memcmp ((uchar *)j->TypeString, OldEntry->TypeString,
j->TypeString->len + LNGTHSZ) == 0) {
OldEntry->CompactedIndex = j->CompactedIndex;
OldEntry->flags.IsMatched = TRUE;
FreeAllocStrings (OldEntry);
if (OldEntry->flags.LargeList) {
free (OldEntry->IndexUnion.IndexString);
OldEntry->flags.LargeList = FALSE;
}
return;
}
}
}
// we did not find the type string in the non-recursive hash table. We
// now look to see if there is a forward reference that was added by some
// other module. If we find one, we will overwrite the forward reference
// type string with this one and then rehash the string.
COUNT (cnt_MatchIndex2);
pType = (TYPPTR)OldEntry->TypeString;
switch (pType->leaf) {
case LF_CLASS:
case LF_STRUCTURE:
pName = (uchar *)&((plfClass)&(pType->leaf))->data[0];
pName += C7SizeOfNumeric (pName);
break;
case LF_UNION:
pName = (uchar *)&((plfUnion)&(pType->leaf))->data[0];
pName += C7SizeOfNumeric (pName);
break;
case LF_ENUM:
pName = (uchar *)&((plfEnum)&(pType->leaf))->Name[0];
break;
default:
pName = NULL;
}
if (pName != NULL) {
switch (FindGlobalFwd (pType->leaf, pName, &pHash)) {
case FWD_none:
// this is OK since we may not have added this list yet
break;
case FWD_local:
// we should never have looked in the module list
DASSERT (FALSE);
break;
case FWD_global:
// we do not need to do any thing here but add the new type
break;
case FWD_globalfwd:
OldEntry->CompactedIndex = pHash->index;
memmove (pHash->pType, pType, pType->len + LNGTHSZ);
goto fwdreplaced;
}
}
// No matching type string found so we add the type to the global types
// table and add it to the string (non-recursive) hash table, Note that
// InsertIntoTypeSegment frees the local type string if it is in
// allocated memory.
InsertIntoTypeSegment (OldEntry);
AddTypeToTypeTable( OldEntry );
OldEntry->iDone = (ushort) -1;
fwdreplaced:
j = (HSSTRING *)Alloc (sizeof (HSSTRING));
j->TypeString = (TYPPTR)OldEntry->TypeString;
j->CompactedIndex = OldEntry->CompactedIndex;
j->Next = HTString[i];
HTString[i] = j;
HTStringCnt[i]++;
if ((j->TypeString->leaf == LF_CLASS) ||
(j->TypeString->leaf == LF_STRUCTURE)) {
plf = (plfClass)&(j ->TypeString->leaf);
if (plf->property.fwdref == FALSE) {
// if we have a forward reference, then the field list
// was null.
DoDerivationList (j->CompactedIndex, plf->field);
}
}
}
/**
*
* DoDerivationList
*
* Takes a field specification list and the derived class and adds
* it to all the inherited classes given by the list.
*
*/
void DoDerivationList (CV_typ_t DerivedClass, CV_typ_t FieldSpecList)
{
TYPPTR typptr;
uchar *plf;
#if 0
uchar **pBuf;
#endif
bool_t Loop = TRUE;
// Get the field list type string
typptr = (TYPPTR) RgGType[FieldSpecList - CV_FIRST_NONPRIM].pbType;
DASSERT (typptr->leaf == LF_FIELDLIST);
// Loop through the real and direct virtual base classes
plf = (uchar *)&(typptr->data[0]);
while (Loop == TRUE) {
if (*plf >= LF_PAD0) {
plf += *plf & 0x0f;
}
switch (((plfEasy)plf)->leaf) {
case LF_BCLASS:
AddToDerivationList (DerivedClass, ((plfBClass)plf)->index);
plf = (uchar *)&((plfBClass)plf)->offset[0];
plf += C7SizeOfNumeric (plf);
break;
case LF_VBCLASS:
AddToDerivationList (DerivedClass, ((plfVBClass)plf)->index);
plf = (uchar *)&((plfVBClass)plf)->vbpoff[0];
plf += C7SizeOfNumeric (plf);
plf += C7SizeOfNumeric (plf);
break;
case LF_INDEX:
DASSERT (FALSE);
default:
Loop = FALSE;
break;
}
}
}
/**
*
* InsertIntoTypeSegment
*
* Inserts a type string into the compacted segment and assigns
* it a new index
* Uses C7 format type strings
*
*/
void InsertIntoTypeSegment (TENTRY *OldEntry)
{
ushort length;
TYPPTR pType;
plfStructure plf;
UDTPTR pSym;
uint usSymLen;
uchar *Name;
uchar *NewSymbol;
uchar *pchDest;
unsigned int iPad; // Number of pad bytes needed.
uint usNewLength; // Symbol length - LNGTHSZ including pad bytes.
#if 0
uchar **pBuf;
#endif
DASSERT (OldEntry->flags.IsNewFormat);
BreakOnIndex (NewIndex);
pType = (TYPPTR)(OldEntry->TypeString);
plf = (plfStructure)&pType->leaf;
#if DBG
if (FDebug) {
DumpPartialType (NewIndex, pType, FALSE);
}
#endif
// add in symbol typedefs for structures; maintaining it as
// a linked list with ExtraSymbols as the head and ExtraSymbolLink
// to point to the next symbol. The link field preceeds the actual
// symbol in memory.
if ((plf->leaf == LF_STRUCTURE) && AddNewSymbols) {
Name = ((uchar *)plf) + offsetof (lfStructure, data[0]);
Name += C7SizeOfNumeric (Name); // go to the name
if (*Name != 0 &&
((*Name != sizeof ("(untagged)") - 1) ||
(strncmp ((char *)(Name + 1), "(untagged)", sizeof ("(untagged)") - 1) != 0))){
// name present, and isn't "(untagged)"
// calculate the size of the symbol;
usSymLen = sizeof (UDTSYM) + *Name;
iPad = PAD4 (usSymLen);
usNewLength = usSymLen + (ushort)iPad - LNGTHSZ;
// allocate space for a new UDT Symbol
NewSymbol = Alloc (usNewLength + LNGTHSZ + sizeof(char *));
if (ExtraSymbols == NULL) {
ExtraSymbols = NewSymbol;// head of list
}
else {
// Change "next" field of the last sybol to point to the new one
*ExtraSymbolLink = NewSymbol;
}
// Create the User Defined Type symbol
pSym = (UDTPTR)(NewSymbol + sizeof(char *));
DASSERT (usNewLength <= USHRT_MAX);
pSym->reclen = (ushort)usNewLength;
pSym->rectyp = S_UDT;
pSym->typind = NewIndex;
memcpy (pSym->name, Name, *Name + 1); // Copy the name
pchDest = ((uchar *)&(pSym->name[0])) + *Name + 1;
PADLOOP (iPad, pchDest);
// Store address of this symbol for next time
ExtraSymbolLink = (uchar **)NewSymbol;
// Set the "next" field of this symbol to NULL
*ExtraSymbolLink = NULL;
}
}
length = C7LENGTH (pType) + LNGTHSZ;
RgGType[NewIndex - CV_FIRST_NONPRIM].pbType = VBufCpy(&TypeBuf,
(uchar*) pType,
length);
FreeAllocStrings (OldEntry);
OldEntry->TypeString = RgGType[NewIndex - CV_FIRST_NONPRIM].pbType;
OldEntry->CompactedIndex = NewIndex++;
// we need to keep track of the following type records that were added
// to the global types table. The forward reference entries will
// later be backpatched to the correct type. We keep track of the
// non-forward references so we know to ignore forward references
// in later modules.
pType = (TYPPTR)(OldEntry->TypeString);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
case LF_UNION:
case LF_ENUM:
HashFwd (pType, (CV_typ_t) (NewIndex - 1), HTGlobalFwd);
break;
default:
break;
}
if (NewIndex == 0) {
#if defined (DUMPER)
DumpPartial ();
#endif
ErrorExit (ERR_65KTYPES, FormatMod (pCurMod), NULL);
}
}
/**
*
* PsuedoInsertIntoTypeSegment
*
* Inserts a type string into the compacted segment and assigns
* it a new index
* Uses C7 format type strings
*
*/
void PsuedoInsertIntoTypeSegment (TENTRY *OldEntry, CV_typ_t OldIndex)
{
static uchar rgType[] = {0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0};
ushort length;
TYPPTR pType;
plfStructure plf;
UDTPTR pSym;
uint usSymLen;
uchar *Name;
uchar *NewSymbol;
uchar *pchDest;
unsigned int iPad; // Number of pad bytes needed.
uint usNewLength; // Symbol length - LNGTHSZ including pad bytes.
DASSERT (OldEntry->flags.IsNewFormat);
BreakOnIndex (NewIndex);
pType = (TYPPTR)(OldEntry->TypeString);
plf = (plfStructure)&pType->leaf;
#if DBG
if (FDebug) {
DumpPartialType (NewIndex, pType, FALSE);
}
#endif
/*
* add in symbol typedefs for structures; maintaining it as
* a linked list with ExtraSymbols as the head and ExtraSymbolLink
* to point to the next symbol. The link field preceeds the actual
* symbol in memory.
*/
if ((plf->leaf == LF_STRUCTURE) && AddNewSymbols) {
Name = ((uchar *)plf) + offsetof (lfStructure, data[0]);
Name += C7SizeOfNumeric (Name); // go to the name
if (*Name != 0 &&
((*Name != sizeof ("(untagged)") - 1) ||
(strncmp ((char *)(Name + 1), "(untagged)", sizeof ("(untagged)") - 1) != 0))){
// name present, and isn't "(untagged)"
// calculate the size of the symbol;
usSymLen = sizeof (UDTSYM) + *Name;
iPad = PAD4 (usSymLen);
usNewLength = usSymLen + (ushort)iPad - LNGTHSZ;
// allocate space for a new UDT Symbol
NewSymbol = Alloc (usNewLength + LNGTHSZ + sizeof(char *));
if (ExtraSymbols == NULL) {
ExtraSymbols = NewSymbol;// head of list
}
else {
// Change "next" field of the last sybol to point to the new one
*ExtraSymbolLink = NewSymbol;
}
// Create the User Defined Type symbol
pSym = (UDTPTR)(NewSymbol + sizeof(char *));
DASSERT (usNewLength <= USHRT_MAX);
pSym->reclen = (ushort)usNewLength;
pSym->rectyp = S_UDT;
pSym->typind = NewIndex;
memcpy (pSym->name, Name, *Name + 1); // Copy the name
pchDest = ((uchar *)&(pSym->name[0])) + *Name + 1;
PADLOOP (iPad, pchDest);
// Store address of this symbol for next time
ExtraSymbolLink = (uchar **)NewSymbol;
// Set the "next" field of this symbol to NULL
*ExtraSymbolLink = NULL;
}
}
length = C7LENGTH (pType) + LNGTHSZ;
*(ulong *) &rgType[4] = OldIndex;
RgGType[NewIndex - CV_FIRST_NONPRIM].pbType = VBufCpy(&TypeBuf,
(uchar*) rgType,
sizeof(rgType));
OldEntry->CompactedIndex = NewIndex++;
OldEntry->flags.fPsuedoPatch = TRUE;
// we need to keep track of the following type records that were added
// to the global types table. The forward reference entries will
// later be backpatched to the correct type. We keep track of the
// non-forward references so we know to ignore forward references
// in later modules.
pType = (TYPPTR)(OldEntry->TypeString);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
case LF_UNION:
case LF_ENUM:
HashFwd (pType, (CV_typ_t) (NewIndex - 1), HTGlobalFwd);
break;
default:
break;
}
if (NewIndex == 0) {
#if defined (DUMPER)
DumpPartial ();
#endif
ErrorExit (ERR_65KTYPES, FormatMod (pCurMod), NULL);
}
} /* PsuedoInsertIntoSegment() */
void PsuedoBackPatch(TENTRY * pOldEntry)
{
TYPPTR pType = (TYPPTR)(pOldEntry->TypeString);
CV_typ_t index = pOldEntry->CompactedIndex;
ushort length;
HSTYPE * j;
length = C7LENGTH(pType) + LNGTHSZ;
DASSERT( ((TYPPTR) RgGType[index - CV_FIRST_NONPRIM].pbType)->leaf == 0xffff);
RgGType[index - CV_FIRST_NONPRIM].pbType = VBufCpy(&TypeBuf,
(uchar *) pType,
length);
/*
* Patch
*/
for (j = HTType[TypeHash(pOldEntry)]; j != NULL; j = j->Next) {
if (j->Type == pOldEntry->TypeString) {
j->Type = RgGType[index - CV_FIRST_NONPRIM].pbType;
break;
}
}
/*
*/
FreeAllocStrings(pOldEntry);
pOldEntry->TypeString = RgGType[index - CV_FIRST_NONPRIM].pbType;
pOldEntry->flags.fPsuedoPatch = FALSE;
return;
} /* PsuedoBackPatch() */
/**
*
* AddTypeToStringTable
*
* Adds a type string to the global hash table
* Uses C7 format type strings
*
*/
void AddTypeToStringTable (uchar *TypeString, CV_typ_t GlobalIndex)
{
static uint cStringsAvail;
static HSSTRING *hstrAvail;
ushort i;
HSSTRING *j;
if (cStringsAvail == 0) {
hstrAvail = (HSSTRING *)Alloc(sizeof(HSSTRING) * 1024);
cStringsAvail = 1024;
}
cStringsAvail--;
j = hstrAvail++;
i = StringHash (TypeString);
j->TypeString = (TYPPTR) TypeString;
j->CompactedIndex = GlobalIndex;
j->Next = HTString[i];
HTString[i] = j;
HTStringCnt[i]++;
}
/**
*
* AddTypeToTypeTable
*
* Add a type string to the type table for recursive types
* Uses C7 format type strings
*
*/
void AddTypeToTypeTable (TENTRY *OldEntry)
{
static uint cTypesAvail;
static HSTYPE *hstAvail;
HSTYPE *new;
int index;
if (cTypesAvail == 0) {
hstAvail = (HSTYPE *)Alloc(sizeof(HSTYPE) * 1024);
cTypesAvail = 1024;
}
index = TypeHash (OldEntry);
cTypesAvail--;
new = hstAvail++;
new->Type = OldEntry->TypeString;
new->GlobalIndex = OldEntry->CompactedIndex;
// add it to the head of the bucket
new->Next = HTType[index];
HTType[index] = new;
HTTypeCnt[index]++;
}
ushort ComDat (uchar *Symbol)
{
bool_t flat32;
ulong Offset;
ushort Seg;
ushort Type;
uchar *Name;
ushort i;
ushort Sum;
HSCOMDAT *p;
if (flat32 = Symbol[1] & 0x80) {
Offset = *(ulong *)(Symbol + 14);
Seg = *(ushort *)(Symbol + 18);
Type = *(ushort *)(Symbol + 20);
Name = Symbol + 35;
}
else {
Offset = (ulong)*(ushort *)(Symbol + 14);
Seg = *(ushort *)(Symbol + 16);
Type = *(ushort *)(Symbol + 18);
Name = Symbol + 27;
}
i = ComDatHash (Name, &Sum);
for (p = HTComDat[i]; p; p = p->Next) {
if ((p->Sum == Sum) && (p->Seg == Seg) && (p->Offset == Offset) &&
(p->Type == Type) && (p->Name[0] == Name[0]) &&
(memcmp (p->Name + 1, Name + 1, Name[0]) == 0)) {
return (TRUE);
}
}
p = (HSCOMDAT *)Alloc(sizeof (HSCOMDAT) + Name[0]);
p->Seg = Seg;
p->Offset = Offset;
p->Type = Type;
p->Sum = Sum;
memcpy (p->Name, Name, Name[0] + 1);
p->Next = HTComDat[i];
HTComDat[i] = p;
return (FALSE);
}
/** C7ReadTypes - read C7 formatted types table
*
* C7ReadTypes (cbTypes, fPreComp)
*
* Entry cbTypes = count of bytes in types table excluding the
* byte count of the signature
* fPreComp = TRUE if precompiled types table allowed
*
*/
void C7ReadTypes (ulong cbTypeSeg, bool_t fPreComp)
{
ulong cbCur; // Number of bytes currently read from file
ushort cbRecLen; // The current record's length
ushort RecType; // The current record's length
uchar *pCurType; // Points to the current type string
uchar *pEnd; // Points to the of type segment
int remainder = 0;
ushort cSkip;
int cbRead;
InitModTypeTable ();
cbCur = 0;
iTypeSeg = 0;
while (cbCur < cbTypeSeg) {
pCurType = pTypeSeg[iTypeSeg];
cbRead = (uint)(min (cbTypeSeg - cbCur, _HEAP_MAXREQ)) - remainder;
if (read (exefile, pCurType + remainder, cbRead) != cbRead) {
ErrorExit (ERR_INVALIDTABLE, "Types", FormatMod (pCurMod));
}
pEnd = pCurType + cbRead + remainder;
while ((size_t)(pEnd - pCurType) >= offsetof (TYPTYPE, data[0])) {
// we have at least the length and record type in memory
cbRecLen = ((TYPPTR)pCurType)->len;
RecType = ((TYPPTR)pCurType)->leaf;
if ((size_t)(pEnd - pCurType) <
(cbRecLen + sizeof (((TYPPTR)pCurType)->len))) {
// the type record is split across this and the next buffer
break;
}
switch (RecType) {
case LF_PRECOMP:
DASSERT (fPreComp == FALSE);
MapPreComp ((plfPreComp)(pCurType + LNGTHSZ));
break;
case LF_ENDPRECOMP:
// we have found the type record that specifies
// the end of the precompiled types for this module.
// Set maxPreComp to MaxIndex (really current index)
// so the precompiled types packer knows how far
// to pack before the publics and symbols are packed.
DASSERT (fPreComp == TRUE);
maxPreComp = MaxIndex + CV_FIRST_NONPRIM;
AddTypeEntry (NULL, FALSE, TRUE, FALSE, T_NOTYPE, 0);
pCurMod->signature =
((plfEndPreComp)(pCurType + LNGTHSZ))->signature;
break;
case LF_TYPESERVER:
ErrorExit (ERR_NOTYPESVR, NULL, NULL );
break;
default:
if (RecType == LF_SKIP) {
cSkip = ((plfSkip)(pCurType + LNGTHSZ))->type -
MaxIndex - CV_FIRST_NONPRIM;
}
else {
cSkip = 0;
}
AddTypeEntry (pCurType, FALSE, TRUE, FALSE, T_NOTYPE, cSkip);
break;
}
pCurType += cbRecLen + LNGTHSZ;
cbCur += cbRecLen + LNGTHSZ;
}
// we have reached the point where we are either at the end of types
// or the next type record does not fit within the current buffer
if (cbCur < cbTypeSeg) {
// we have not reached the end of the types so we allocate and
// read another buffer
if (pTypeSeg[iTypeSeg + 1] == NULL) {
if ((pTypeSeg[iTypeSeg + 1] = malloc (_HEAP_MAXREQ)) == 0) {
ErrorExit (ERR_NOMEM, NULL, NULL);
}
cTypeSeg++;
}
remainder = pEnd - pCurType;
memmove (pTypeSeg[iTypeSeg + 1], pCurType, remainder);
iTypeSeg++;
}
}
InitialTypeInfoSize += cbTypeSeg; // update size info
}
/** C6ReadTypes - read C6 types table
*
* Purpose : Given a Type segment and its size, initialize the
* module type index table and set all global indices to
* zero
*/
void C6ReadTypes (uchar *TypeSegment, ulong Size)
{
uchar *End = TypeSegment + Size;
ushort cSkip;
InitModTypeTable ();
while (TypeSegment < End) {
if (TypeSegment[3] == OLF_SKIP) {
cSkip = (*(CV_typ_t *)(TypeSegment + 4)) - MaxIndex - 512;
}
else {
cSkip = 0;
}
AddTypeEntry (TypeSegment, FALSE, FALSE, FALSE, T_NOTYPE, cSkip);
if (TypeSegment[3] == OLF_STRUCTURE) {
// We have to add a symbol for each C6 UDT found. We
// are deliberately overestimating the size of the symbol
// because it takes too much time to do an accurate estimate
UDTAdd += MAXPAD + sizeof (UDTSYM) + *(ushort *)&TypeSegment[1];
}
TypeSegment += LENGTH (TypeSegment) + 3; // on to next string
}
InitialTypeInfoSize += (unsigned long) Size; // update size info
}
/** InitModTypeTable - initialize/reset module type table
*
* InitModTypeTable ()
*
* Entry BlockList = head of first level index structure
*
* Exit cur = pointer to first level index structure
* MaxIndex = 0
* if BlockList = NULL, then a first level index structure is
* allocated and initialized. If BlockList is not NULL, then
* the first level index structure is initialized.
*/
LOCAL void InitModTypeTable (void)
{
HSFWD *pHash;
uint i;
usInitCount++;
fPendingInit = FALSE;
if (BlockList == NULL) {
BlockList = Alloc (sizeof (struct BlockListEntry));
BlockList->Low = 0;
BlockList->Next = NULL;
BlockList->ModuleIndexTable = (TENTRY *)
CAlloc (INDEXBLOCKSIZE * sizeof (TENTRY));
}
else {
fPendingInit = TRUE;
}
IndexBlocks = 1;
cur = BlockList;
MaxIndex = 0;
// clear out the hash table for forward reference resolution
for (i = 0; i < HASH_FWD; i++) {
pHash = HTLocalFwd[i];
while (pHash != NULL) {
pHash->index = T_NOTYPE;
pHash->pType = NULL;
pHash->pName = NULL;
pHash = pHash->Next;
}
}
}
/** AddTypeEntry - add type descriptor to local table
*
* AddTypeEntry (pType, IsMalloced, IsNewFormat, IsPrecomp, type, cSkip)
*
* Entry pType = pointer to type string
* IsMalloced = TRUE if string is in malloced memory
* IsNewFormat = TRUE if type is CV4 format
* IsPreComp = TRUE if precompile type from another module
* cSkip = number of indices to skip before adding this type
*
* Exit type added to local type descriptors
*
* Return none
*
* Note: MapPreComp contains an inlined/simplified version of this
* function, if AddTypeEntry ever changes semantics then
* the inline code in MapPreComp should be examined [rm]
*
*/
LOCAL void AddTypeEntry (uchar *pType, bool_t IsMalloced, bool_t IsNewFormat,
bool_t IsPreComp, CV_typ_t type, ushort cSkip)
{
ushort i;
ushort NextIndex;
if (fPendingInit) {
memset(BlockList->ModuleIndexTable, 0,
INDEXBLOCKSIZE * sizeof(TENTRY));
fPendingInit = FALSE;
}
// Store type string in the appropriate Index Block
i = MaxIndex - cur->Low;
if (i == INDEXBLOCKSIZE) { // next block
IndexBlocks++;
if (cur->Next == NULL) {
cur->Next = Alloc (sizeof (struct BlockListEntry));
cur->Next->Next = NULL;
cur->Next->ModuleIndexTable = (TENTRY *)
CAlloc (INDEXBLOCKSIZE * sizeof (TENTRY));
}
else {
memset(cur->Next->ModuleIndexTable, 0,
INDEXBLOCKSIZE * sizeof(TENTRY));
}
cur = cur->Next;
cur->Low = MaxIndex;
i = 0;
}
cur->ModuleIndexTable[i].TypeString = pType;
cur->ModuleIndexTable[i].CompactedIndex = type;
cur->ModuleIndexTable[i].flags.IsMalloced = IsMalloced;
cur->ModuleIndexTable[i].flags.IsNewFormat = IsNewFormat;
cur->ModuleIndexTable[i].flags.IsPreComp = IsPreComp;
if ((IsNewFormat == TRUE) && (IsPreComp == FALSE) &&
(pType != NULL)) {
// we need to hash the names in the following type records
// so we can satisfy a forward reference if we find one
// while packing this module.
switch (((TYPPTR)pType)->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
if (((plfClass)&((TYPPTR)pType)->leaf)->property.fwdref ==
FALSE) {
HashFwd ((TYPPTR)pType, (CV_typ_t)(MaxIndex + CV_FIRST_NONPRIM),
(HSFWD **)HTLocalFwd);
}
break;
case LF_UNION:
if (((plfUnion)&((TYPPTR)pType)->leaf)->property.fwdref ==
FALSE) {
HashFwd ((TYPPTR)pType, (CV_typ_t) (MaxIndex + CV_FIRST_NONPRIM),
(HSFWD **)HTLocalFwd);
}
break;
case LF_ENUM:
if (((plfEnum)&((TYPPTR)pType)->leaf)->property.fwdref ==
FALSE) {
HashFwd ((TYPPTR)pType, (CV_typ_t)(MaxIndex + CV_FIRST_NONPRIM),
(HSFWD **)HTLocalFwd);
}
break;
default:
break;
}
}
if (cSkip != 0) {
NextIndex = MaxIndex + cSkip;
if (NextIndex - cur->Low < INDEXBLOCKSIZE) {
// new index fits on block. We need to zero out all of
// the unused indices and then mark them invalid
memset (cur->ModuleIndexTable + i + 1, 0,
(NextIndex - MaxIndex - 1) * sizeof (TENTRY));
MaxIndex = NextIndex;
while (i < (ushort) (MaxIndex - cur->Low)) {
cur->ModuleIndexTable[i].flags.WasSkipped = TRUE;
i++;
}
cur->High = MaxIndex - 1;
}
else {
// start new block
IndexBlocks++;
if (cur->Next == NULL) {
cur->Next = Alloc (sizeof (struct BlockListEntry));
cur->Next->Next = NULL;
cur->Next->ModuleIndexTable = (TENTRY *)
CAlloc (INDEXBLOCKSIZE * sizeof (TENTRY));
}
else {
memset(cur->Next->ModuleIndexTable, 0,
INDEXBLOCKSIZE * sizeof(TENTRY));
}
cur->High = MaxIndex - 1;
cur = cur->Next;
cur->Low = MaxIndex = NextIndex;
}
}
else {
cur->High = MaxIndex++;
}
}
/** MapPreComp - map in precompiled types from creator module
*
* MapPreComp (plf)
*
* Entry plf = pointer to LF_PRECOMP type record up to name field
*
* Exit types from creator file inserted into this modules type entries
*
* Returns none
*/
LOCAL void MapPreComp (plfPreComp plf)
{
PMOD pMod;
ushort j;
OMFPreCompMap *pMap;
static PMOD pModLast; // last module we installed
static CV_typ_t MaxIndexLast; // saved MaxIndex value
static struct BlockListEntry *curLast; // saved 'cur' value
static ushort IndexBlocksLast; // saved IndexBlocks
static ushort curHighLast; // saved cur->High
static ushort usPreCompCount;
pMod = FindModule ((char *)&plf->name[0]);
if ((pMap = (OMFPreCompMap *)VmLoad (pMod->PreCompAddr, _VM_CLEAN)) == _VM_NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if (pMod->signature != plf->signature) {
ErrorExit (ERR_PCTSIG, FormatMod (pCurMod), NULL);
}
if ((pMap->cTypes != plf->count) ||
((ushort) (MaxIndex + CV_FIRST_NONPRIM) != plf->start)) {
ErrorExit (ERR_PRECOMPERR, FormatMod (pCurMod), FormatMod (pMod));
}
if (usInitCount == (ushort)(usPreCompCount + 1) && pMod == pModLast) {
// we're doing the same module as last time...
// let's short circuit everything
usPreCompCount = usInitCount;
MaxIndex = MaxIndexLast;
cur = curLast;
IndexBlocks = IndexBlocksLast;
cur->High = curHighLast;
j = MaxIndex - cur->Low;
if (j != INDEXBLOCKSIZE) {
memset(cur->ModuleIndexTable+j, 0,
(INDEXBLOCKSIZE - j) * sizeof(TENTRY));
}
fPendingInit = FALSE;
return;
}
if (fPendingInit) {
memset(BlockList->ModuleIndexTable, 0,
INDEXBLOCKSIZE * sizeof(TENTRY));
fPendingInit = FALSE;
}
for (j = 0; j < plf->count; j++) {
ushort i;
TENTRY * pEntry;
// NOTE: this code is cloned from AddTypeEntry which is
// the general purpose adder of info to the local types table
// this code needs to always be a reflection of the code in
// AddTypeEntry
// Store type string in the appropriate Index Block
i = MaxIndex - cur->Low;
if (i == INDEXBLOCKSIZE) { // next block
IndexBlocks++;
// we better have already allocated the memory for this
// since these are indices that we've already visited
DASSERT(cur->Next != NULL);
memset(cur->Next->ModuleIndexTable, 0,
INDEXBLOCKSIZE * sizeof(TENTRY));
cur = cur->Next;
cur->Low = MaxIndex;
i = 0;
}
pEntry = &cur->ModuleIndexTable[i];
pEntry->CompactedIndex = pMap->map[j];
pEntry->flags.IsNewFormat = TRUE;
pEntry->flags.IsPreComp = TRUE;
cur->High = MaxIndex++;
}
curLast = cur;
MaxIndexLast = MaxIndex;
pModLast = pMod;
IndexBlocksLast = IndexBlocks;
curHighLast = cur->High;
usPreCompCount = usInitCount;
}
LOCAL PMOD FindModule (char *pName)
{
PMOD pMod = ModuleList;
char Name[257];
// search to end of module list
while (pMod != NULL) {
if ((pMod->pName != NULL) && (*pName == *pMod->pName)) {
if (strnicmp (pName + 1, pMod->pName + 1, *pName) == 0) {
return (pMod);
}
}
pMod = pMod->next;
}
strncpy (Name, pName + 1, *pName);
Name[*pName] = 0;
ErrorExit (ERR_REFPRECOMP, Name, NULL);
}
COUNTER (cnt_GetTypeEntry)
COUNTER (cnt_GetTypeEntry2)
TENTRY *GetTypeEntry (CV_typ_t index, CV_typ_t *forward)
{
struct BlockListEntry *cur;
TENTRY *tmp;
ushort n;
CV_typ_t dummy;
COUNT (cnt_GetTypeEntry);
*forward = T_NOTYPE;
for (cur = BlockList, n = IndexBlocks; cur != NULL && n > 0; cur = cur->Next, n--) {
if (index >= cur->Low && index <= cur->High) {
tmp = &(cur->ModuleIndexTable[index - cur->Low]);
if (tmp->flags.WasSkipped != TRUE) {
if (tmp->flags.IsForward == TRUE) {
*forward = tmp->ForwardIndex;
COUNT (cnt_GetTypeEntry2);
return (GetTypeEntry ((CV_typ_t)(tmp->ForwardIndex - CV_FIRST_NONPRIM), &dummy));
}
else {
return (tmp);
}
}
else {
errIndex = index + usCurFirstNonPrim;
ErrorExit (ERR_LFSKIP, FormatMod (pCurMod), FormatIndex (errIndex));
}
}
}
// If converting a C6 type and the index is the special ZEROARGTYPE
// index then return the LF_ARGLIST, count 0 type info.
if ((ulCVTypeSignature == CV_SIGNATURE_C6) &&
index == (ushort)(ZEROARGTYPE - usCurFirstNonPrim)){
return (ZeroArg);
}
errIndex = index + usCurFirstNonPrim;
ErrorExit (ERR_INDEX, FormatMod (pCurMod), FormatIndex (errIndex));
}
/** GetPatchIndex -
*
* Given a local index to a recursive structure, consults the
* hash table to see if another similar structure is present
* or not. If yes, return the global index, else insert the
* structure into the compacted segment and return its index
*
*/
COUNTER (cnt_GetPatchIndex)
CV_typ_t GetPatchIndex (TENTRY *OldEntry, CV_typ_t OldIndex)
{
HSTYPE *j;
COUNT (cnt_GetPatchIndex);
DASSERT (OldIndex >= usCurFirstNonPrim);
DASSERT (MaxIndex > OldIndex - usCurFirstNonPrim);
if ((OldEntry->flags.IsMatched) || (OldEntry->flags.IsInserted) ||
(OldEntry->flags.IsPreComp)) {
return (OldEntry->CompactedIndex);
}
j = HTType[TypeHash (OldEntry)];
while (j != NULL) {
if (IdenticalTree (OldEntry, OldIndex, (TYPPTR)j->Type,
j->GlobalIndex)) {
return (j->GlobalIndex);
}
else {
j = j->Next;
}
}
return (AddPatchType (OldIndex));
}
/** GetRecursiveIndex -
*
* Given a local index to a recursive structure, consults the
* hash table to see if another similar structure is present
* or not. If yes, return the global index, else insert the
* structure into the compacted segment and return its index
*
*/
COUNTER (cnt_GetRecursiveIndex)
CV_typ_t GetRecursiveIndex (TENTRY *OldEntry, CV_typ_t OldIndex)
{
HSTYPE *j;
TYPPTR pType;
HSFWD *pHash;
COUNT (cnt_GetRecursiveIndex);
DASSERT (OldIndex >= usCurFirstNonPrim);
DASSERT (MaxIndex > OldIndex - usCurFirstNonPrim);
pType = (TYPPTR)OldEntry->TypeString;
switch (FindFwdRef (OldEntry, &pHash, FALSE)) {
case FWD_none:
case FWD_local:
case FWD_global:
break;
case FWD_globalfwd:
AddPatchEntry (OldIndex, OldEntry, pType);
return (pHash->index);
}
j = HTType[TypeHash (OldEntry)];
while (j != NULL) {
if (IdenticalTree (OldEntry, OldIndex, (TYPPTR)j->Type,
j->GlobalIndex)) {
return (j->GlobalIndex);
}
else {
j = j->Next;
}
}
// return (AddRecursiveType (OldIndex));
return (AddPatchType( OldIndex ));
}
/** FindFwdRef - find definition of forward reference
*
*
* state = FindFwdRef (OldEntry, HSFWD **ppHash, fLocal)
*
* Entry OldEntry = pointer to index structure
* fLocal = TRUE of local table to be searched
*
* Exit **ppHash = pointer to hash entry
*
* Return FWD_none if definition not found
* FWD_local if definition found in local table
* FWD_global if definition found in global table
* FWD_globalfwd if forward reference found in global table
*/
FWD_t FindFwdRef (TENTRY *OldEntry, HSFWD **ppHash, bool_t fLocal)
{
uchar *pName;
TYPPTR pType = (TYPPTR)OldEntry->TypeString;
FWD_t retval = FWD_none;
switch (pType->leaf) {
case LF_CLASS:
case LF_STRUCTURE:
pName = (uchar *)&((plfClass)&(pType->leaf))->data[0];
pName += C7SizeOfNumeric (pName);
break;
case LF_UNION:
pName = (uchar *)&((plfUnion)&(pType->leaf))->data[0];
pName += C7SizeOfNumeric (pName);
break;
case LF_ENUM:
pName = (uchar *)&((plfEnum)&(pType->leaf))->Name[0];
break;
default:
return (retval);
}
if (fLocal == TRUE) {
if ((retval = FindLocalFwd (pType->leaf, pName, ppHash)) != FWD_local) {
retval = FindGlobalFwd (pType->leaf, pName, ppHash);
}
}
else {
retval = FindGlobalFwd (pType->leaf, pName, ppHash);
}
return (retval);
}
/** FindLocalFwd - find local definition of forward reference
*
* status = FindLocalFwd (leaf, pName, ppHash)
*
* Entry leaf = leaf type
* pName = pointer to name string
* pIndex = pointer to replacement index
*
* Exit **ppHash = pointer to hash entry
*
* Return FWD_none if definition not found
* FWD_local if definition found in local table
*/
COUNTER (cnt_FindLocalFwd)
LOCAL FWD_t FindLocalFwd (ushort leaf, char *pName, HSFWD **ppHash)
{
uchar *pc;
uint Sum;
uint i;
uint hash;
HSFWD *pHash;
COUNT (cnt_FindLocalFwd);
pc = pName;
Sum = *pc;
for (i = *pc++; i > 0; i--) {
Sum += *pc++;
}
hash = Sum % HASH_FWD;
pHash = HTLocalFwd[hash];
while ((pHash != NULL) && (pHash->pType != 0)) {
DASSERT (pHash->index >= CV_FIRST_NONPRIM);
if ((leaf == pHash->pType->leaf) &&
(strncmp (pHash->pName, pName, *pName + 1) == 0)) {
*ppHash = pHash;
return (FWD_local);
}
pHash = pHash->Next;
}
return (FWD_none);
}
/** FindGlobalFwd - find global definition of forward reference
*
* status = FindGlobalFwd (leaf, pName, pIndex)
*
* Entry leaf = leaf type
* pName = pointer to name string
* pIndex = pointer to replacement index
*
* Exit *pIndex = replacement index
*
* Return FWD_none if definition not found
* FWD_global if definition found in global table
* FWD_globalfwd if forward reference found in global table
*/
COUNTER (cnt_FindGlobalFwd)
LOCAL FWD_t FindGlobalFwd (ushort leaf, char *pName, HSFWD **ppHash)
{
uchar *pc;
uint Sum;
uint i;
uint hash;
HSFWD *pHash;
#if 0
uchar **pBuf;
#endif
FWD_t retval = FWD_none;
TYPPTR pType;
COUNT (cnt_FindGlobalFwd);
pc = pName;
Sum = *pc;
for (i = *pc++; i > 0; i--) {
Sum += *pc++;
}
hash = Sum % HASH_FWD;
pHash = HTGlobalFwd[hash];
while ((pHash != NULL) && (pHash->pType != 0)) {
DASSERT (pHash->index >= CV_FIRST_NONPRIM);
if ((leaf == pHash->pType->leaf) &&
(strncmp (pHash->pName, pName, *pName + 1) == 0)) {
// the names and record types are identical. we now need
// to check to see if this is a forward reference or a
// definition
pType = (TYPPTR) RgGType[pHash->index - CV_FIRST_NONPRIM].pbType;
DASSERT(pType->leaf != 0xffff);
*ppHash = pHash;
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
if (((plfClass)&((TYPPTR)pType)->leaf)->property.fwdref ==
FALSE) {
retval = FWD_global;
}
else {
retval = FWD_globalfwd;
}
break;
case LF_UNION:
if (((plfUnion)&((TYPPTR)pType)->leaf)->property.fwdref ==
FALSE) {
retval = FWD_global;
}
else {
retval = FWD_globalfwd;
}
break;
case LF_ENUM:
if (((plfEnum)&((TYPPTR)pType)->leaf)->property.fwdref ==
FALSE) {
retval = FWD_global;
}
else {
retval = FWD_globalfwd;
}
break;
}
return (retval);
}
pHash = pHash->Next;
}
return (FWD_none);
}
/** HashFwd - hash type strings for forward ref resolution
*
* HashFwd (pType, pTable)
*
* Entry pType = pointer to type string
* pTable = hash table to add string to
*
* Exit type string hashed into table
*
* Returns none
*/
COUNTER (cnt_HashFwd)
LOCAL void HashFwd (TYPPTR pType, CV_typ_t index, HSFWD **pTable)
{
uchar *pName;
uchar *pc;
uint Sum;
uint hash;
uint i;
HSFWD *pHash;
COUNT (cnt_HashFwd);
switch (pType->leaf) {
case LF_CLASS:
case LF_STRUCTURE:
pName = (uchar *)&((plfClass)&(pType->leaf))->data[0];
pName += C7SizeOfNumeric (pName);
break;
case LF_UNION:
pName = (uchar *)&((plfUnion)&(pType->leaf))->data[0];
pName += C7SizeOfNumeric (pName);
break;
case LF_ENUM:
pName = (uchar *)&((plfEnum)&(pType->leaf))->Name[0];
break;
}
pc = pName;
Sum = *pc;
for (i = *pc++; i > 0; i--) {
Sum += *pc++;
}
DASSERT (index >= CV_FIRST_NONPRIM);
hash = Sum % HASH_FWD;
pHash = pTable[hash];
while ((pHash != NULL) && (pHash->pType != 0)) {
DASSERT (pHash->index >= CV_FIRST_NONPRIM);
if ((pType->leaf == pHash->pType->leaf) &&
(strncmp (pHash->pName, pName, *pName + 1) == 0)) {
return;
}
pHash = pHash->Next;
}
if (pHash == NULL) {
// add new entry to table since we are at then end
if ((pHash = (HSFWD *)CAlloc (sizeof (HSFWD))) == NULL) {
ErrorExit (ERR_NOMEM, NULL, NULL);
}
pHash->Next = pTable[hash];
pTable[hash] = pHash;
}
pHash->pType = pType;
pHash->pName = pName;
pHash->index = index;
}
/** SumUCChar - generate sum of upper case character hash
*
* hash = SumUCChar (pSym, pSum, pLen, modulo)
*
* Entry pSym = pointer to symbol
* pSum = pointer to sum
* pLen = pointer of offset of length prefixed name
* modulo = hash table size
*
* Exit *sum = sum of characters (upper cased) in name
*
* Returns *sum / modulo
*/
uint SumUCChar (SYMPTR pSym, ulong *pSum, uint *pLen, uint modulo)
{
uchar *pName;
ushort i;
ushort n;
ushort Sum = 0;
switch (pSym->rectyp) {
case S_CONSTANT:
pName = (uchar *)(&((CONSTPTR)pSym)->value);
pName += C7SizeOfNumeric (pName);
break;
case S_GDATA16:
pName = (uchar *)(&((DATAPTR16)pSym)->name[0]);
break;
case S_GDATA32:
case S_GTHREAD32:
pName = (uchar *)(&((DATAPTR32)pSym)->name[0]);
break;
case S_UDT:
pName = (uchar *)(&((UDTPTR)pSym)->name[0]);
break;
case S_PUB16:
pName = (uchar *)&(((DATAPTR16)pSym)->name[0]);
break;
case S_PUB32:
pName = (uchar *)&(((DATAPTR32)pSym)->name[0]);
break;
default:
DASSERT (FALSE);
*pLen = 0;
*pSum = 0;
return (0);
}
*pLen = pName - (uchar *)pSym;
n = *pName++;
for (i = 0; i < n; i++) {
Sum += toupper (pName[i]);
}
*pSum = Sum;
return (Sum % modulo);
}
uint
DWordXorLrl(
SYMPTR pSym,
ulong * pSum,
uint * pLen,
uint modulo
)
/*++
Routine Description:
This function is used to compute the hash of a symbol. It has several
good and bad properties as a hash function. Some of the special things
that it does are:
- Case is to be ignored. i.e. 'a' and 'A' should hash identically
- For standard call functions, '@#' should be ignored in the hash.
Arguments:
pSym - Supplies the pointer to the symbol to be hashed
pSum - Returns the pre-modulo calcuation value
pLen - Returns the offset of the name in the symbol
modulo - Supplies the hash range.
Return Value:
The final hash value
--*/
{
uchar * pName;
int cb;
uchar * pch;
ulong UNALIGNED * pul;
ulong hash;
static rgMask[] = {0, 0xff, 0xffff, 0xffffff};
switch( pSym->rectyp ) {
case S_CONSTANT:
pName = (uchar *) &(((CONSTPTR) pSym)->value);
pName += C7SizeOfNumeric( pName );
cb = *pName;
break;
case S_GDATA16:
pName = (uchar *) &(((DATAPTR16) pSym)->name[0]);
cb = *pName;
break;
case S_GDATA32:
case S_GTHREAD32:
pName = (uchar *) &(((DATAPTR32) pSym)->name[0]);
cb = *pName;
break;
case S_UDT:
pName = (uchar *) &(((UDTPTR) pSym)->name[0]);
cb = *pName;
break;
case S_PUB16:
pName = (uchar *) &(((DATAPTR16) pSym)->name[0]);
cb = *pName;
goto MangleName;
break;
case S_PUB32:
pName = (uchar *) &(((DATAPTR32) pSym)->name[0]);
cb = *pName;
/*
* We want to do some name mangling at this point. Specifically
* we want to strip the @## from the end of stdcall names
*/
MangleName:
pch = pName + cb;
while (isdigit(*pch)) {
pch--;
DASSERT(pch >= pName);
}
if (*pch == '@') {
cb = pch - pName - 1;
}
break;
/*
* In other cases always end up with a hash value of 0
*/
default:
DASSERT( FALSE );
*pLen = 0;
*pSum = 0;
return 0;
}
*pLen = pName - (uchar *) pSym;
pName++;
/*
* Setup for the hash function
*/
hash = 0;
pul = (ulong *) pName;
for (; cb > 3; cb-=4, pul++) {
hash = _lrotl(hash, 4);
hash ^= (*pul & 0xdfdfdfdf);
}
if (cb > 0) {
hash = _lrotl(hash, 4);
hash ^= ((*pul & rgMask[cb]) & 0xdfdfdfdf);
}
*pSum = hash;
return hash % modulo;
} /* DWordXorLrl() */
ushort AddrHash (SYMPTR pSym, ushort *pSum, ushort *indName, ushort modulo)
{
ulong Offset;
switch (pSym->rectyp) {
case S_CONSTANT:
case S_UDT:
return (0);
case S_PUB16:
case S_GDATA16:
Offset = (ulong)(((DATAPTR16)pSym)->off);
break;
case S_PUB32:
case S_GDATA32:
case S_GTHREAD32:
Offset = (ulong)(((DATAPTR32)pSym)->off);
break;
default:
DASSERT (FALSE);
return (0);
}
*pSum = 0;
*indName = 0;
return (ushort) ((Offset >> 6) % modulo);
}
/** PrepareGlobalTypeTable
*
* Entry TypeBuf - Linked list of blocks containing Global types.
* The global type strings are unpadded.
*
* Exit GlobalTypeTable contains an array of offsets to the types.
* These offsets are calculated on the assumption that at write
* time the strings will be placed on 4 word bounderies.
*
*/
void PrepareGlobalTypeTable ()
{
VBlock *TypeBlock;
ushort usTotal; // Length of record including size of length field
ushort i = 0;
uchar *Types;
uchar *End;
#if 0
ulong *pBuf;
#endif
ulong Offset;
Offset = (long)(NewIndex - CV_FIRST_NONPRIM + 1) * sizeof (ulong) + sizeof (OMFTypeFlags);
for (TypeBlock = VBufFirstBlock (&TypeBuf);
TypeBlock;
TypeBlock = VBufNextBlock (TypeBlock)) {
for (Types = TypeBlock->Address,
End = TypeBlock->Address + TypeBlock->Size; Types < End;) {
RgGType[i].pbType = (uchar *) Offset;
i++;
// Get the length of this record
usTotal = ((SYMPTR)Types)->reclen + LNGTHSZ;
// Move to the next type
Types += usTotal;
// Calculate the address of the next type string after padding
Offset += usTotal + PAD4 (usTotal);
}
}
DASSERT (i == NewIndex - CV_FIRST_NONPRIM);
}
/** PackPublic - pack public symbol into list if possible
*
* flag = PackPublic (pSym, lpfnHash)
*
* Entry pSym = pointer to symbol
* lpfnHash = pointer to hash function
*
* Exit symbol added to global symbol table if possible
* original symbol type changed to S_CVRESERVE if packed
*
* Returns GPS_intable if symbol is in the global symbol table
* GPS_added if symbol can be added to the global table
* GPS_noadd if symbol of same name but different type in table
*
*/
GPS_t PackPublic (SYMPTR pSym, LPFNHASH lpfnHash)
{
uchar *pName;
uchar *pTemp;
ushort hashName;
ulong sumName;
uint indName;
GLOBALSYM *p;
GLOBALSYM *pNew;
ushort len;
ushort iPad;
uint cbReqd;
static uint cbLocal = 0;
static uchar *pbLocal = 0;
hashName = lpfnHash ((SYMPTR)pSym, &sumName, &indName, HASH_SYM);
pName = (uchar *)pSym + indName;
len = *pName;
for (p = HTPub[hashName]; p != NULL; p = p->Next) {
pTemp = p->Sym + p->indName;
if (sumName == p->sumName) {
if (memcmp (pName, pTemp, len + 1) == 0) {
// name is in global symbol table. Now make sure the
// symbol record is identical.
if (memcmp ((uchar *)pSym + LNGTHSZ, p->Sym + LNGTHSZ,
pSym->reclen - p->indName - LNGTHSZ) == 0) {
pSym->rectyp = S_CVRESERVE;
cGlobalDel++;
return (GPS_intable);
}
else {
// the name is in the table, but the record is different
Warn (WARN_DUPPUBLIC, pName, FormatMod (pCurMod));
//Warn (WARN_DUPPUBLIC, (char *)(&((PUBPTR16)pSym)->name[0]) + 1,
// FormatMod (pCurMod));
return (GPS_noadd);
}
}
}
}
iPad = PAD4 (pSym->reclen + LNGTHSZ);
cbReqd = (sizeof (GLOBALSYM) + pSym->reclen + LNGTHSZ + iPad);
if (cbLocal < cbReqd) {
DASSERT(cbReqd < CB_ATOMIC);
pbLocal = Alloc(CB_ATOMIC);
cbLocal = CB_ATOMIC;
}
pNew = (GLOBALSYM *) pbLocal;
cbLocal -= cbReqd;
pbLocal += cbReqd;
pNew->sumName = sumName;
pNew->indName = indName;
memcpy (pNew->Sym, pSym, pSym->reclen + LNGTHSZ);
pTemp = pNew->Sym + pSym->reclen + LNGTHSZ;
((SYMPTR)&(pNew->Sym[0]))->reclen += iPad;
cbPublics += pSym->reclen + LNGTHSZ + iPad;
cPublics++;
PADLOOP (iPad, pTemp);
pNew->Next = HTPub[hashName];
HTPub[hashName] = pNew;
pSym->rectyp = S_CVRESERVE;
return (GPS_added);
}
/** PackSymbol - pack symbol into global symbol list if possible
*
* flag = PackSymbol (pSym, lpfnHash)
*
* Entry pSym = pointer to symbol
* lpfnHash = pointer to hash function
*
* Exit symbol added to global symbol table if possible
* original symbol type changed to S_CVRESERVE if packed
*
* Returns GPS_intable if symbol is in the global symbol table
* GPS_added if symbol can be added to the global table
* GPS_noadd if symbol of same name but different type in table
*
*/
GPS_t PackSymbol (SYMPTR pSym, LPFNHASH lpfnHash)
{
uchar *pName;
uchar *pTemp;
ushort hashName;
ulong sumName;
uint indName;
GLOBALSYM *p;
GLOBALSYM *pNew;
ushort len;
ushort iPad;
uint cbReqd;
static uint cbLocal = 0;
static uchar *pbLocal = 0;
hashName = lpfnHash ((SYMPTR)pSym, &sumName, &indName, HASH_SYM);
pName = (uchar *)pSym + indName;
len = *pName;
for (p = HTSym[hashName]; p != NULL; p = p->Next) {
pTemp = p->Sym + p->indName;
if (sumName == p->sumName) {
if (memcmp (pName, pTemp, len + 1) == 0) {
// name is in global symbol table. Now make sure the
// symbol record is identical.
if (memcmp ((uchar *)pSym + LNGTHSZ, (uchar *)(&p->Sym[0]) + LNGTHSZ,
pSym->reclen) == 0) {
pSym->rectyp = S_CVRESERVE;
cGlobalDel++;
return (GPS_intable);
}
else {
// the name is in the table, but the record is different
return (GPS_noadd);
}
}
}
}
iPad = PAD4 (pSym->reclen + LNGTHSZ);
cbReqd = sizeof (GLOBALSYM) + pSym->reclen + LNGTHSZ + iPad;
if (cbLocal < cbReqd) {
DASSERT(cbReqd < CB_ATOMIC);
pbLocal = Alloc(CB_ATOMIC);
cbLocal = CB_ATOMIC;
}
pNew = (GLOBALSYM *) pbLocal;
cbLocal -= cbReqd;
pbLocal += cbReqd;
pNew->sumName = sumName;
pNew->indName = indName;
memcpy (pNew->Sym, pSym, pSym->reclen + LNGTHSZ);
pTemp = pNew->Sym + pSym->reclen + LNGTHSZ;
((SYMPTR)&(pNew->Sym[0]))->reclen += iPad;
cbGlobalSym += pSym->reclen + LNGTHSZ + iPad;
cGlobalSym++;
PADLOOP (iPad, pTemp);
pNew->Next = HTSym[hashName];
HTSym[hashName] = pNew;
pSym->rectyp = S_CVRESERVE;
return (GPS_added);
}
void WritePublics (OMFDirEntry *Dir, long lfoStart)
{
OMFSymHash hash;
GLOBALSYM *p;
VBuf NameHashBuf;
VBlock *NameHashBlock;
VBuf AddrHashBuf;
VBlock *AddrHashBlock;
ushort iHash;
int PadCount;
ulong Zero = 0;
memset ( &hash, 0, sizeof (hash) );
hash.cbSymbol = cbPublics;
BuildHash (
&HASHFUNCTION,
&hash.symhash,
&hash.cbHSym,
&NameHashBuf,
cPublics,
HTPub
);
BuildSort (
&hash.addrhash,
&hash.cbHAddr,
&AddrHashBuf,
cPublics,
HTPub
);
Dir->SubSection = sstGlobalPub;
Dir->iMod = 0xffff;
Dir->lfo = lfoStart;
Dir->cb = sizeof (OMFSymHash) + hash.cbSymbol + hash.cbHSym + hash.cbHAddr;
// write out global symbols
if (!BWrite ((char *)&hash, sizeof (hash))) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
for (iHash = 0; iHash < HASH_SYM; iHash++) {
for (p = HTPub[iHash]; p != NULL; p = p->Next) {
if (!BWrite (&p->Sym[0], ((SYMPTR)(&(p->Sym[0])))->reclen + LNGTHSZ)) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
}
}
// write out the hash table
if ( hash.symhash != 0 ) {
for (
NameHashBlock = VBufFirstBlock (&NameHashBuf);
NameHashBlock != NULL;
NameHashBlock = VBufNextBlock (NameHashBlock)
) {
if (!BWrite (NameHashBlock->Address,
NameHashBlock->Size)) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
}
}
if ( hash.addrhash != 0 ) {
for (
AddrHashBlock = VBufFirstBlock (&AddrHashBuf);
AddrHashBlock != NULL;
AddrHashBlock = VBufNextBlock (AddrHashBlock)
) {
if (!BWrite (AddrHashBlock->Address,
AddrHashBlock->Size)) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
}
}
PadCount = (int)(sizeof (ulong) - (Dir->cb % sizeof (ulong)));
if ((PadCount != 4) &&
(!BWrite (&Zero, PadCount))) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
#ifndef WINDOWS
if (logo == TRUE) {
printf ("Public symbol size = %8.1ld\n", hash.cbSymbol);
}
#endif
}
void WriteGlobalSym (OMFDirEntry *Dir, long lfoStart)
{
OMFSymHash hash;
GLOBALSYM *p;
VBuf NameHashBuf;
VBlock *NameHashBlock;
VBuf AddrHashBuf;
VBlock *AddrHashBlock;
ushort iHash;
int PadCount;
ulong Zero = 0;
memset ( &hash, 0, sizeof (hash) );
hash.cbSymbol = cbGlobalSym;
BuildHash (
&HASHFUNCTION,
&hash.symhash,
&hash.cbHSym,
&NameHashBuf,
cGlobalSym,
HTSym
);
// M00NOTE - global symbols are not address hashed
Dir->SubSection = sstGlobalSym;
Dir->iMod = 0xffff;
Dir->lfo = lfoStart;
Dir->cb = sizeof (OMFSymHash) + hash.cbSymbol + hash.cbHSym + hash.cbHAddr;
// write out global symbols
if (!BWrite ((char *)&hash, sizeof (hash))) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
for (iHash = 0; iHash < HASH_SYM; iHash++) {
if (iHash == 0x205) {
int i = 0;
}
for (p = HTSym[iHash]; p != NULL; p = p->Next) {
if (!BWrite (&p->Sym[0], ((SYMPTR)(&(p->Sym[0])))->reclen + LNGTHSZ)) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
}
}
// write out the hash table
if ( hash.symhash != 0 ) {
for (
NameHashBlock = VBufFirstBlock (&NameHashBuf);
NameHashBlock != NULL;
NameHashBlock = VBufNextBlock (NameHashBlock)
) {
if (!BWrite (NameHashBlock->Address,
NameHashBlock->Size)) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
}
}
if ( hash.addrhash != 0 ) {
for (
AddrHashBlock = VBufFirstBlock (&AddrHashBuf);
AddrHashBlock != NULL;
AddrHashBlock = VBufNextBlock (AddrHashBlock)
) {
if (!BWrite (AddrHashBlock->Address,
AddrHashBlock->Size)) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
}
}
PadCount = (int)(sizeof (ulong) - (Dir->cb % sizeof (ulong)));
if ((PadCount != 4) &&
(!BWrite (&Zero, PadCount))) {
ErrorExit (ERR_NOSPACE, NULL, NULL);
}
#ifndef WINDOWS
if (logo == TRUE) {
printf ("Initial symbol size = %8.ld\n", InitialSymInfoSize);
printf ("Final symbol size = %8.ld\n", FinalSymInfoSize);
printf ("Global symbol size = %8.1ld\n", hash.cbSymbol);
}
#endif
}
/** LinkScope - link lexicals scope
*
* LinkScope (pSym, cbSym)
*
* Entry pSym = pointer to symbol table
* cbSym = count of bytes in symbol table
*
* Exit lexical scopes in symbol table linked
*
* Returns TRUE if scopes linked
* FALSE if error linking scopes
*/
bool_t LinkScope (uchar *pStart, ulong cbSym)
{
SYMPTR pEnd;
SYMPTR pPrev;
SYMPTR pSym;
SYMPTR pInit;
SEARCHPTR pSearch;
ulong offParent = 0;
// fill in the parent and end fields
pSym = (SYMPTR)(pStart + sizeof (long));
pSearch = (SEARCHPTR)pSym;
pEnd = (SYMPTR)(pStart + cbSym);
while( pSym < pEnd ) {
switch( ((SYMPTR)pSym)->rectyp) {
case S_LPROC16:
case S_GPROC16:
case S_THUNK16:
case S_BLOCK16:
case S_WITH16:
case S_LPROC32:
case S_GPROC32:
case S_THUNK32:
case S_BLOCK32:
case S_WITH32:
case S_LPROCMIPS:
case S_GPROCMIPS:
// note that this works because all of these symbols
// have a common format for the first fields. The
// address variants follow the link fields.
// put in the parent
((BLOCKPTR)pSym)->pParent = offParent;
offParent = (uchar *)pSym - pStart;
break;
case S_END:
// fill in the end record to the parent
((BLOCKPTR)(pStart + offParent))->pEnd =
(ulong)((uchar *)pSym - pStart);
// reclaim his parent as the parent
offParent = ((BLOCKPTR)(pStart + offParent))->pParent;
break;
}
pSym = (SYMPTR)((uchar *)pSym + pSym->reclen + LNGTHSZ);
}
// Go to the end of the Search part of the symbols table
pInit = (SYMPTR)pSearch;
while (pInit < pEnd && pInit->rectyp == S_SSEARCH) {
pInit = (SYMPTR)((uchar *)pInit + pInit->reclen + LNGTHSZ);
}
// Fill in the next fields
while (((SYMPTR)pSearch < pEnd) && (pSearch->rectyp == S_SSEARCH)) {
pPrev = (SYMPTR) pSearch;
pSym = pInit;
offParent = 0;
while (pSym < pEnd) {
switch ( ((SYMPTR)pSym)->rectyp ) {
case S_LPROC16:
case S_GPROC16:
case S_THUNK16:
case S_LPROC32:
case S_GPROC32:
case S_THUNK32:
case S_GPROCMIPS:
case S_LPROCMIPS:
if (((PROCPTR)pSym)->pEnd == 0) {
// bad lexical scope data
return (FALSE);
}
if (((SYMPTR)pPrev)->rectyp == S_SSEARCH) {
((SEARCHPTR)pPrev)->startsym =
(ulong)((uchar *)pSym - pStart);
} else {
((PROCPTR)pPrev)->pNext = (ulong)((uchar *)pSym - pStart);
}
pPrev = pSym;
pSym = (SYMPTR)((uchar *)pSym + pSym->reclen + LNGTHSZ);
break;
default:
pSym = (SYMPTR)((uchar *)pSym + pSym->reclen + LNGTHSZ);
}
}
pSearch = (SEARCHPTR)((uchar *)pSearch + pSearch->reclen + LNGTHSZ);
}
return (TRUE);
}
bool_t SegmentPresent (ushort defaultseg)
{
ushort i;
for (i = 0; i < cSeg; i ++) {
if (segnum[i] == defaultseg) {
return (TRUE);
}
}
return (FALSE);
}
ushort AddSearchSym (uchar *pSym, ushort seg)
{
uchar *pPad;
int iPad;
int len;
len = ALIGN4 (sizeof (SEARCHSYM));
((SEARCHPTR)pSym)->reclen = len - LNGTHSZ;
iPad = PAD4 (sizeof (SEARCHSYM));
// Fill in all the fields with the data passed.
((SEARCHPTR)pSym)->rectyp = S_SSEARCH;
((SEARCHPTR)pSym)->seg = seg;
((SEARCHPTR)pSym)->startsym = 0;
pPad = pSym + len - LNGTHSZ;
PADLOOP (iPad, pPad);
return (len);
}
/**
*
* AddDerivationListsToTypeSegment
*
* Finally put the lists into the type segment
*
*/
LOCAL void AddDerivationListsToTypeSegment (void)
{
ushort i,j,l,m;
plfClass BaseClassString;
uchar *ScratchString;
uchar *NewString;
HSSTRING *k;
plfDerived plfDer;
PDCLASS DerivStructure;
#if 0
uchar **pBuf;
#endif
for (i = 0; i < NextInDerivation; i ++) {
DerivStructure = &DLists[i];
j = DerivStructure->Count;
ScratchString = GetScratchString (2 * j +
offsetof (lfDerived, drvdcls[0]) + LNGTHSZ);
NewString = ScratchString;
// Set Length of type record and make pointer to derived leaf and
// fill in the derived record
((TYPPTR)ScratchString)->len = 2 * j + offsetof (lfDerived, drvdcls[0]);
plfDer = (plfDerived)&(((TYPPTR)ScratchString)->leaf);
plfDer->leaf = LF_DERIVED;
plfDer->count = j;
m = 0;
for (; j > 0; j --) {
plfDer->drvdcls[m++] = DerivStructure->List[j - 1];
}
free (DerivStructure->List);
// Check for a matching LF_DERIVED record
l = StringHash (NewString);
for (k = HTString[l]; k != NULL; k = k->Next) {
if (memcmp ((uchar *)k->TypeString, NewString,
k->TypeString->len + LNGTHSZ) == 0) {
break;
}
}
// Add the new record to the global index table if there wasn't a match
// Then store the new record index in the base class.
BaseClassString = (plfClass)(RgGType[DerivStructure->BClass - CV_FIRST_NONPRIM].pbType + LNGTHSZ);
DASSERT( ((TYPPTR) BaseClassString)->leaf != 0xffff );
if (k == NULL) {
k = (HSSTRING *) Alloc (sizeof (HSSTRING));
k->CompactedIndex = NewIndex;
k->TypeString = (TYPPTR) VBufCpy (&TypeBuf, NewString, ((TYPPTR)NewString)->len + LNGTHSZ);
k->Next = HTString[l];
HTString[l] = k;
HTStringCnt[l]++;
RgGType[NewIndex - CV_FIRST_NONPRIM].pbType = (uchar *)(k->TypeString);
BaseClassString->derived = NewIndex++;
if (NewIndex == 0) {
ErrorExit (ERR_65KTYPES, FormatMod (pCurMod), NULL);
}
}
else {
BaseClassString->derived = k->CompactedIndex;
}
}
}
/**
*
* StringHash
*
* Hash a typestring as a string by adding in all the bytes except
* the linkage. If the record type is LF_STRUCTURE, LF_CLASS, LF_UNION or
* LF_ENUM, only the name is used for the hash.
*/
COUNTER (cnt_StringHash)
LOCAL ushort StringHash (uchar *TypeString)
{
ushort j;
uchar *puc;
uchar *pucEnd;
TYPPTR pType = (TYPPTR)TypeString;
COUNT (cnt_StringHash);
j = 0;
pucEnd = TypeString + pType->len + sizeof (pType->len);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
puc = (uchar *)&(((plfClass)&pType->leaf)->data[0]);
puc += C7SizeOfNumeric (puc);
break;
case LF_UNION:
puc = (uchar *)&(((plfUnion)&pType->leaf)->data[0]);
puc += C7SizeOfNumeric (puc);
break;
case LF_ENUM:
puc = (uchar *)&(((plfEnum)&pType->leaf)->Name[0]);
break;
default:
puc = TypeString;
break;
}
for (; puc < pucEnd; puc++) {
j += (ushort) *puc;
}
return (j % HASH_STRING);
}
/** IdenticalTypes - check two type strings for identity
*
* fSuccess = IdenticalTypes (Type1, Type2)
*
* Entry Type1 = first type string
* Type2 = second type string
*
* Exit none
*
* Returns TRUE if type strings are identical
* FALSE if type strings are different
*/
bool_t IdenticalTypes (TYPPTR Type1, TYPPTR Type2)
{
return ((Type1->len == Type2->len) &&
memcmp ((uchar *)Type1, (uchar *)Type2, Type1->len + LNGTHSZ) == 0);
}
/**
*
* AddToDerivationList
*
* Adds a derived class to the derivation list of a base class
*
*/
LOCAL void AddToDerivationList (CV_typ_t DerivedClass, CV_typ_t BaseClass)
{
plfClass BClassStr;
ushort i;
#if 0
uchar **pBuf;
#endif
BClassStr = (plfClass)(GetGTypeEntry(BaseClass) + LNGTHSZ);
DASSERT ((BClassStr->leaf == LF_CLASS) ||
(BClassStr->leaf == LF_STRUCTURE));
for (i = 0; i < NextInDerivation; i++) {
if (DLists[i].BClass == BaseClass) {
break;
}
}
if (i == NextInDerivation) {
// This is the first derivation for this class
if (NextInDerivation == MaxDerivation) {
// It won't fit in our current list, so lengthen the list.
MaxDerivation += DCLASS_INC;
DLists = (PDCLASS)NoErrorRealloc (DLists, MaxDerivation * sizeof (DCLASS));
}
DLists[i].Count = 0;
DLists[i].Max = DLIST_INC;
DLists[i].BClass = BaseClass;
DLists[i].List = (CV_typ_t *)Alloc (DLIST_INC * sizeof (CV_typ_t));
NextInDerivation++;
}
// Add the derived class
if (DLists[i].Count == DLists[i].Max) {
DLists[i].Max += DLIST_INC;
DLists[i].List = (CV_typ_t *)NoErrorRealloc (
DLists[i].List, DLists[i].Max * sizeof (CV_typ_t));
}
DLists[i].List[DLists[i].Count++] = DerivedClass;
}
/**
*
* TypeHash
*
* Map a type string to an integer without including the lower level
* type indices
* Uses C7 format type strings
*
*/
COUNTER (cnt_TypeHash)
LOCAL int TypeHash (TENTRY *OldEntry)
{
int i;
ushort j;
int length;
int index;
uchar *TypeString;
ushort hashval = 0;
uchar *puc;
TYPPTR pType = (TYPPTR)OldEntry->TypeString;
if (OldEntry->Hash)
return OldEntry->Hash;
OldEntry->Hash = HASH_TYPE - 1; // set tmp hash so we don't recurse
COUNT (cnt_TypeHash);
hashval = (pType->leaf);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
puc = (uchar *)&(((plfClass)&pType->leaf)->data[0]);
puc += C7SizeOfNumeric (puc);
break;
case LF_UNION:
puc = (uchar *)&(((plfUnion)&pType->leaf)->data[0]);
puc += C7SizeOfNumeric (puc);
break;
case LF_ENUM:
puc = (uchar *)&(((plfEnum)&pType->leaf)->Name[0]);
break;
case LF_MEMBER:
puc = (uchar *)&(((plfMember)&pType->leaf)->offset[0]);
puc += C7SizeOfNumeric (puc);
break;
case LF_STMEMBER:
puc = (uchar *)&(((plfSTMember)&pType->leaf)->Name[0]);
break;
default:
TypeString = OldEntry->TypeString;
length = C7LENGTH (TypeString) + LNGTHSZ;
j = 0;
i = 0;
while (i < length) {
if (j == OldEntry->Count) {
index = length;
}
else {
if (OldEntry->flags.LargeList) {
index = OldEntry->IndexUnion.IndexString[j];
}
else {
index = OldEntry->IndexUnion.Index[j];
}
j ++;
}
while (i < index) {
hashval = (hashval << 2) ^ TypeString[i++] ^ (hashval >> 14);
}
i += sizeof (CV_typ_t);
}
// check no more than 3 nested subtypes...
i = OldEntry->Count;
if (i > 3) {
i = 3;
}
while (--i >= 0) {
hashval ^= SubHash(OldEntry, i);
}
OldEntry->Hash = (hashval % HASH_TYPE);
return OldEntry->Hash;
}
length = *puc++;
while (--length > 0) {
hashval = (hashval << 2) ^ (*puc++) ^ (hashval >> 14);
}
OldEntry->Hash = (hashval % HASH_TYPE);
return OldEntry->Hash;
}
LOCAL ushort SubHash (TENTRY *OldEntry, int iitem)
{
TYPPTR pType = (TYPPTR)OldEntry->TypeString;
CV_typ_t forward;
CV_typ_t next;
TENTRY * TmpLocalEntry;
ushort index;
if (OldEntry->flags.LargeList) {
index = OldEntry->IndexUnion.IndexString[iitem];
}
else {
index = OldEntry->IndexUnion.Index[iitem];
}
next = *(CV_typ_t *)((uchar *)pType + index);
if (next < usCurFirstNonPrim)
return next;
next -= usCurFirstNonPrim;
TmpLocalEntry = GetTypeEntry (next, &forward);
if (TmpLocalEntry->flags.IsInserted)
return (TmpLocalEntry->Hash);
else
return (TypeHash(TmpLocalEntry));
}
/**
*
* ComDatHash
*
* Hash on proc name
*
*/
LOCAL int ComDatHash (uchar *Name, ushort *Sum)
{
ushort i;
ushort length = Name[0] + 1;
*Sum = 0;
for (i = 0; i < length; i++) {
*Sum += (ushort) Name[i];
}
return (*Sum % HASH_COMDAT);
}
LOCAL void CleanUpModuleIndexTable (void)
{
struct BlockListEntry *cur, *next;
for (cur = BlockList; cur != NULL; cur = next) {
next = cur->Next;
free (cur->ModuleIndexTable);
free (cur);
}
}
/**
*
* FreeStrings
*
* Frees any malloced strings in a recursive structure
*
*/
void FreeStrings (CV_typ_t OldIndex)
{
ushort i, index;
uchar *TypeString;
TENTRY *OldEntry;
CV_typ_t forward;
DASSERT (MaxIndex > OldIndex - usCurFirstNonPrim);
OldEntry = (TENTRY *)GetTypeEntry ((CV_typ_t)(OldIndex - usCurFirstNonPrim), (CV_typ_t *)&forward);
if ((OldEntry->flags.IsBeingFreed) || (OldEntry->flags.IsInserted)) {
return;
}
OldEntry->flags.IsBeingFreed = TRUE;
TypeString = OldEntry->TypeString;
for (i = 0; i < OldEntry->Count; i ++) {
if (OldEntry->flags.LargeList) {
index = OldEntry->IndexUnion.IndexString[i];
}
else {
index = OldEntry->IndexUnion.Index[i];
}
FreeStrings (*(CV_typ_t *)(TypeString + index));
}
FreeAllocStrings (OldEntry);
OldEntry->Count = 0;
if (OldEntry->flags.LargeList) {
free (OldEntry->IndexUnion.IndexString);
OldEntry->flags.LargeList = FALSE;
}
}
void FreeAllocStrings (TENTRY *OldEntry)
{
if (OldEntry->flags.IsMalloced) {
free (OldEntry->TypeString);
OldEntry->flags.IsMalloced = FALSE;
}
else if (OldEntry->flags.IsPool2) {
Pool2Free (OldEntry->TypeString);
OldEntry->flags.IsPool2 = FALSE;
}
else if (OldEntry->flags.IsPool) {
PoolFree (OldEntry->TypeString);
OldEntry->flags.IsPool = FALSE;
}
}
/** BuildHash
*
* Build a global symbol hash table using the hash function
* passed in lpfnHash
*
* The format of this table is as follows:
*
* Position Size Description
*
* 0 2 # of hash entries
* 2 2 filler to preserve nat. alignment
* 4 4*n Hash table, each entry is the offset from
* the start of this table to the
* chain associated with its index.
* 4+4*n 2*n Count of entries in each hash bucket
* chain associated with its index.
* 4 + 6*n 4*m Chain table, each entry is a length prefixed
* list of offsets to the symbols associated with
* this index.
*
* NOTE: All offsets are ulongs
*
*/
LOCAL void BuildHash (
LPFNHASH lpfnHash,
ushort *pusHashId,
ulong *pcbHash,
VBuf *HashBuf,
ulong cSym,
GLOBALSYM **HT
) {
ulong ulSymbolAddr = sizeof (OMFSymHash);
ushort HashSize;
PECT *rgpect;
POVFL rgpecet [ cpecetMax ] = { NULL };
ushort cpecet = 0;
ushort cect = 0;
ushort iect = 0;
ulong cbAlloc;
ushort index;
PECT *ppect;
PECT pect;
ushort ipecet;
ushort iHash;
ulong ulChain;
POVFL pOvfl;
POVFL *ppOvfl;
ushort culSymbol;
ushort ipect;
GLOBALSYM *p;
ulong sumName;
uint indName;
if (cSym == 0) {
return;
}
// compute size of hash table and allow for initial zero length.
// the hashsize is always rounded to an even number so that the
// count array is aligned. The intent is to minimize the average
// length of the bucket to about cBucketSize entries per chain. We
// are also assuming that the number of entries per bucket is less
// than 65k.
HashSize = (ushort) min (cSym / cBucketSize, 0xFFFF);
HashSize = max (HashSize, MINHASH);
HashSize = (HashSize + 1) & ~1;
// Set up the chain tables for each bucket. rgpect is an array that
// contains pointers to portions of the array of hash entry structures.
// The hash entry structures contain the count of symbols in this bucket,
// the offsets of the first cBucketSize symbols in the bucket and a pointer
// to the overflow chain.
cect = HashSize / cectMax + 1;
rgpect = Alloc (cect * sizeof (PECT));
for (iect = 0; iect < cect; iect++) {
cbAlloc = (iect == (ushort)(cect-1)) ?
(((long)HashSize * sizeof (ECT)) % (cectMax * sizeof (ECT))) :
cectMax * sizeof (ECT);
DASSERT (cbAlloc <= UINT_MAX);
*(rgpect + iect) = CAlloc ((size_t)cbAlloc);
}
// loop through all of the symbols generating hash information
// for each symbol
for (iHash = 0; iHash < HASH_SYM; iHash++) {
for (p = HT[iHash]; p != NULL; p = p->Next) {
// compute hash index, pointer to pointer to chain and
// pointer to chain
index = lpfnHash ((SYMPTR)(&p->Sym[0]), &sumName, &indName, HashSize);
ppect = rgpect + (index / cectMax);
pect = *ppect + (index % cectMax);
if (pect->culSymbol < culEct) {
// the bucket has not overflowed
pect->rgulSymbol[pect->culSymbol] = ulSymbolAddr;
}
else {
// the bucket has overflowed. Walk the chain of
// overflow buffers to the final bucket and store
// the symbol offset
ppOvfl = &pect->pOvflNext;
culSymbol = (pect->culSymbol - culEct) % OVFL_C;
while (*ppOvfl != NULL &&
(culSymbol == 0 || (*ppOvfl)->pOvflNext != NULL)) {
ppOvfl = &(*ppOvfl)->pOvflNext;
}
if (culSymbol == 0) {
ipecet = cpecet / cecetMax;
if (rgpecet [ ipecet ] == NULL) {
rgpecet [ ipecet ] = CAlloc (cbMaxAlloc);
}
*ppOvfl = rgpecet [ ipecet ] + cpecet;
cpecet += 1;
}
(*ppOvfl)->rgulSymbol [ culSymbol ] = ulSymbolAddr;
}
pect->culSymbol += 1;
ulSymbolAddr += ((SYMPTR)(&p->Sym[0]))->reclen + LNGTHSZ;
}
}
// Now put all of this information into the VBuf
VBufInit (HashBuf, NameHashBlockSize);
// Write out the table size preserving natural alignment
VBufCpy (HashBuf, (uchar *) &HashSize, sizeof (HashSize));
VBufSet (HashBuf, 0, sizeof (ushort));
// Write out the actual hash table
ulChain = sizeof (HashSize) + sizeof (ushort) +
sizeof (ulong) * HashSize + sizeof (ushort) * HashSize;
for (iHash = 0; iHash < HashSize; iHash++) {
ppect = rgpect + (iHash / cectMax);
pect = *ppect + (iHash % cectMax);
VBufCpy (HashBuf, (uchar *)&ulChain, sizeof (ulChain));
ulChain += pect->culSymbol * sizeof (ulong);
}
// Write out the bucket counts
for (iHash = 0; iHash < HashSize; iHash++) {
ppect = rgpect + (iHash / cectMax);
pect = *ppect + (iHash % cectMax);
VBufCpy (HashBuf, (uchar *)&pect->culSymbol, sizeof (culSymbol));
}
// Write out the chains
for (iHash = 0; iHash < HashSize; iHash++) {
ppect = rgpect + (iHash / cectMax);
pect = *ppect + (iHash % cectMax);
pOvfl = pect->pOvflNext;
culSymbol = pect->culSymbol;
VBufCpy (HashBuf, (uchar *)pect->rgulSymbol,
min (culEct, culSymbol) * sizeof (ulong));
culSymbol -= min (culEct, culSymbol);
while (culSymbol > 0) {
VBufCpy (HashBuf, (uchar *)pOvfl->rgulSymbol,
min (OVFL_C, culSymbol) * sizeof (ulong));
culSymbol -= min (OVFL_C, culSymbol);
pOvfl = pOvfl->pOvflNext;
}
}
*pusHashId = HASHID;
*pcbHash =
sizeof (HashSize) +
sizeof (ushort) +
sizeof (ulong) * HashSize +
sizeof (ushort) * HashSize +
sizeof (ulong) * cSym;
// Now free all of our internal structures
for (ipect = 0; ipect < cect; ipect++) {
free (*(rgpect + ipect));
}
free (rgpect);
for (ipecet = 0; ipecet < cpecetMax; ipecet++) {
free (rgpecet [ipecet]);
}
}
#define PUBSEG(p) ( \
((SYMPTR)p)->rectyp == S_PUB16 ? \
((PUBPTR16)p)->seg : \
((PUBPTR32)p)->seg \
)
#define PUBOFF(p) ( \
((SYMPTR)p)->rectyp == S_PUB16 ? \
(CV_uoff32_t) ((PUBPTR16)p)->off : \
((PUBPTR32)p)->off \
)
typedef struct _EST {
SYMPTR psym;
ulong ulsym;
} EST; // Entry in Sort Table
typedef EST *PEST;
typedef struct _SGN {
int csym;
int isym;
PEST rgest;
} SGN; // SeGment Node
typedef SGN *PSGN;
LOCAL int _CRTAPI1 PubAddrCmp (const void * pv1, const void * pv2)
{
PEST pest1 = (PEST) pv1;
PEST pest2 = (PEST) pv2;
return (int) ( PUBOFF ( pest1->psym ) - PUBOFF ( pest2->psym ) );
}
LOCAL void BuildSort (
ushort *pusHashId,
ulong *pcbHash,
VBuf *SortBuf,
ulong cSym,
GLOBALSYM **HT
) {
short cseg = 0;
int iseg;
int isym;
int iHash;
ulong ulsrt;
PSGN rgsgn = NULL;
ulong ulsym = sizeof (OMFSymHash);
GLOBALSYM *p = NULL;
int csymBogus = 0;
if ( cSym == 0 ) {
return;
}
// Find the number of segments used by the publics
for ( iHash = 0; iHash < HASH_SYM; iHash++ ) {
for ( p = HT[iHash]; p != NULL; p = p->Next ) {
if ( (int) PUBSEG ( p->Sym ) > cseg ) {
cseg = PUBSEG ( p->Sym );
}
}
}
// Allocate an array containing global information for each segment
rgsgn = CAlloc ( sizeof ( SGN ) * cseg );
for ( iHash = 0; iHash < HASH_SYM; iHash++ ) {
for ( p = HT[iHash]; p != NULL; p = p->Next ) {
if ( PUBSEG ( p->Sym ) == 0 ) {
csymBogus += 1;
}
else {
rgsgn [ PUBSEG ( p->Sym ) - 1 ].csym += 1;
}
}
}
// Allocate memory for the list of symbols associated w/ each segment
for ( iseg = 0; iseg < cseg; iseg++ ) {
if ( rgsgn [ iseg ].csym ) {
rgsgn [ iseg ].rgest = CAlloc ( rgsgn [ iseg ].csym * sizeof (EST) );
}
}
// Associate a pointer to each symbol with the appropriate segment
for ( iHash = 0; iHash < HASH_SYM; iHash++ ) {
for ( p = HT[iHash]; p != NULL; p = p->Next ) {
PEST pest = NULL;
iseg = PUBSEG ( p->Sym ) - 1;
if ( iseg != -1 ) {
pest = &rgsgn [ iseg ].rgest [ rgsgn [ iseg ].isym++ ];
pest->psym = (SYMPTR) p->Sym;
pest->ulsym = ulsym;
}
ulsym += ((SYMPTR)(&p->Sym[0]))->reclen + LNGTHSZ;
}
}
// Now sort the symbols within each segment
for ( iseg = 0; iseg < cseg; iseg++ ) {
PSGN psgn = &rgsgn [ iseg ];
qsort ((void *)psgn->rgest, psgn->csym, sizeof (EST), PubAddrCmp );
}
// Write the sorted table out to the vbuf
VBufInit (SortBuf, NameHashBlockSize);
// Write out the number of segments preserving natural alignment
VBufCpy (SortBuf, (uchar *) &cseg, sizeof (cseg) );
VBufSet (SortBuf, 0, sizeof (ushort));
// Write out the position of each segment's info
ulsrt =
sizeof (cseg) +
sizeof (ushort) +
sizeof (ulong) * cseg +
sizeof (ushort) * cseg;
// write out cseg items of 4 bytes -- alignment preserved
for ( iseg = 0; iseg < cseg; iseg++ ) {
VBufCpy (SortBuf, (uchar *) &ulsrt, sizeof ( ulong ) );
ulsrt += rgsgn [ iseg ].csym * sizeof ( ulong );
}
// Write out the count of symbols in each segment
//
// write out cseg items of size 2 bytes -- alignment needs to be fixed
// afterwards
for ( iseg = 0; iseg < cseg; iseg++ ) {
VBufCpy (SortBuf, (uchar *) &(rgsgn [ iseg ].csym), sizeof ( ushort ) );
}
if (cseg & 1) {
VBufSet (SortBuf, 0, sizeof(ushort));
}
// Write out the sorted list of publics associated w/ each segment
//
// all items of size ulong -- alignment preserved
for ( iseg = 0; iseg < cseg; iseg++ ) {
PSGN psgn = &rgsgn [ iseg ];
for ( isym = 0; isym < psgn->csym; isym++ ) {
VBufCpy (
SortBuf,
(uchar *) &(psgn->rgest [ isym ].ulsym),
sizeof ( ulong )
);
}
}
*pusHashId = 5;
*pcbHash =
sizeof (cseg) +
sizeof (ushort) +
sizeof (ulong) * cseg +
sizeof (ushort) * cseg +
sizeof (ushort) * (cseg & 1) +
sizeof (ulong) * ( cSym - csymBogus );
if (cseg & 1) {
pcbHash += sizeof(ushort);
}
// Free the temporary memory
for ( iseg = 0; iseg < cseg; iseg++ ) {
if ( rgsgn [ iseg ].rgest ) {
free ( rgsgn [ iseg ].rgest );
}
}
free ( rgsgn );
}
/** IsFwdRef - is this a forward reference
*
*
* fSuccess = IsFwdRef (pType)
*
* Entry pType = type string
*
* Exit none
*
* Return TRUE if forward reference
* FALSE if not forward reference
*/
COUNTER (cnt_IsFwdRef)
bool_t IsFwdRef (TYPPTR pType)
{
COUNT (cnt_IsFwdRef);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
return (((plfClass)&((TYPPTR)pType)->leaf)->property.fwdref);
case LF_UNION:
return (((plfUnion)&((TYPPTR)pType)->leaf)->property.fwdref);
case LF_ENUM:
return (((plfEnum)&((TYPPTR)pType)->leaf)->property.fwdref);
default:
return (FALSE);
}
}
void UniqueType(void)
{
static int k = CV_FIRST_NONPRIM;
int i;
TYPPTR pTyp1;
TYPPTR pTyp2;
for (; k<NewIndex; k++) {
pTyp1 = (TYPPTR) (RgGType[k - CV_FIRST_NONPRIM].pbType);
DASSERT( pTyp1->leaf != 0xffff );
for (i=CV_FIRST_NONPRIM; i<k; i++) {
pTyp2 = (TYPPTR) (RgGType[i - CV_FIRST_NONPRIM].pbType);
DASSERT( pTyp2->leaf != 0xffff);
if (IdenticalTypes(pTyp1, pTyp2)) {
printf("ISOTYPES %x %x\n", i, k);
}
}
}
}