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.
 
 
 
 
 
 

2329 lines
62 KiB

// ncbsc.cpp
// NCB's implementation of Bsc interface:
/////////////////////////////////////////////////////////////////////
#include "pdbimpl.h"
#include "ncbrowse.h"
#include "ncutil.h"
/////////////////////////////////////////////
// NOTE:
// IINST = 32 bit:
// 16 bit Module Index (iModHdr)
// 16 bit Instance/property Index (iProp)
/////////////////////////////////////////////
/////////////////////////////////////////////
// close()
// REVIEW: needs implementation
// must check count first, before really
// closing the file.
/////////////////////////////////////////////
BOOL Ncb::close()
{
USHORT i;
USHORT iBuf;
BOOL bClose = FALSE;
BOOL bOwnPdb = FALSE;
BOOL bRet = TRUE;
for (i = 0; i < ms_prgNcbInfo->size(); i++)
{
if ((*ms_prgNcbInfo)[i].m_pPdb == m_pdb)
{
(*ms_prgNcbInfo)[i].m_count--;
if ((*ms_prgNcbInfo)[i].m_count == 0)
{
bOwnPdb = (*ms_prgNcbInfo)[i].m_bIOwnPdb;
ms_prgNcbInfo->deleteAt(i);
bClose = TRUE;
}
break;
}
}
if (bClose)
{
while (m_rgRWBuf.size() > 0)
{
LoadFrWriteToRead (m_rgRWBuf.size()-1, &iBuf);
if (!SaveReadModToStream (m_pdb, iBuf))
bRet = FALSE;
}
if (!SaveTargetsToStream(m_pdb))
bRet = FALSE;
if (!SaveModHdrsToStream(m_pdb))
bRet = FALSE;
if (!m_pnm->close())
bRet =FALSE;
int i;
for (i = 0; i < NCB_MOD_BUF_SIZE; i++)
{
delete [] m_rgContBuf[i].m_rgProp;
delete [] m_rgContBuf[i].m_rgUse;
delete [] m_rgContBuf[i].m_rgParam;
m_rgContBuf[i].m_rgProp = NULL;
m_rgContBuf[i].m_rgUse = NULL;
m_rgContBuf[i].m_rgParam = NULL;
CloseHandle (m_hMutexNCB);
CloseHandle (m_hMutex);
m_hMutexNCB = NULL;
m_hMutex = NULL;
}
if (bOwnPdb)
{
if (bRet && !m_pdb->Commit())
bRet = FALSE;
m_pdb->Close();
m_pdb = NULL;
}
delete this;
}
return bRet;
};
///////////////////////////////////////////////
// iinstInfo ()
// get information regarding IINST
///////////////////////////////////////////////
BOOL Ncb::iinstInfo(IINST iinst, OUT SZ *psz, OUT TYP *ptyp, OUT ATR *patr)
{
NCB_ENTITY en;
if (EnFrIinst (iinst, &en))
{
*ptyp = en.m_typ;
*patr = en.m_atr;
*psz = szFrNi (en.m_ni);
return TRUE;
}
return FALSE;
};
/////////////////////////////////////////////
// iinstInfo()
// get information regarding IINST
////////////////////////////////////////////
BOOL Ncb::iinstInfo (HTARGET hTarget, IINST iinst, OUT SZ *psz, OUT TYP *ptyp, OUT ATR * patr)
{
USHORT iModHdr = IModFrIinst (iinst);
if (!isModInTarget (hTarget, iModHdr))
return FALSE;
return iinstInfo (iinst, psz, ptyp, patr);
};
//////////////////////////////////////////////////////////////////
// szFrNi()
//////////////////////////////////////////////////////////////////
SZ Ncb::szFrNi(NI ni)
{
return ::szFrNi (m_pnm, ni);
};
///////////////////////////////////////////////////////////////////
//irefInfo()
// NOT USED
///////////////////////////////////////////////////////////////////
BOOL Ncb::irefInfo(IREF iref, OUT SZ *pszModule, OUT LINE *piline)
{
USHORT iModHdr;
USHORT iProp;
USHORT iBuf;
iModHdr = IModFrIinst (iref);
iProp = IPropFrIinst (iref);
_ASSERT (iModHdr < m_rgModHdr.size());
*pszModule = szFrNi (m_rgModHdr[iModHdr].m_ni);
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_WRITE)
{
if (!FindWriteIndex (iModHdr, &iBuf))
return FALSE;
if (m_rgRWBuf[iBuf].m_rgProp.size() <= iProp)
return FALSE;
*piline = m_rgRWBuf[iBuf].m_rgProp[iProp].m_lnStart;
}
else
{
if (!LoadModForRead (m_pdb, iModHdr, &iBuf))
return FALSE;
_ASSERT (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_READ);
_ASSERT (iBuf< NCB_MOD_BUF_SIZE);
*piline = m_rgContBuf[iBuf].m_rgProp[iProp].m_lnStart;
}
return TRUE;
};
///////////////////////////////////////////////////////////////////
// idefInfo()
// the same as iinst info
// get info based on the IDEF (which is the same thing as IINST)
// first, we have to obtain the PROP, and from there, must check
// whether it is really a def or not, otherwise must search for
// proper definition.
///////////////////////////////////////////////////////////////////
BOOL Ncb::idefInfo(IDEF idef, OUT SZ *pszModule, OUT LINE *piline)
{
return idefInfo ((HTARGET)-1, idef, pszModule, piline);
};
////////////////////////////////////////////////////////////////////
BOOL Ncb::idefInfo(HTARGET hTarget, IDEF idef, OUT SZ *pszModule, OUT LINE *piline)
{
IINST iinst;
USHORT iModHdr;
USHORT iProp;
USHORT iBuf;
if (!GetIDef (hTarget, (IINST)idef, (IDEF *)&iinst, &iBuf))
return FALSE;
iModHdr = IModFrIinst (iinst);
iProp = IPropFrIinst (iinst);
_ASSERT (iModHdr < m_rgModHdr.size());
*pszModule = szFrNi (m_rgModHdr[iModHdr].m_ni);
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_WRITE)
{
*piline = m_rgRWBuf[iBuf].m_rgProp[iProp].m_lnStart;
}
else
{
_ASSERT (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_READ);
_ASSERT (iBuf< NCB_MOD_BUF_SIZE);
*piline = m_rgContBuf[iBuf].m_rgProp[iProp].m_lnStart;
}
return TRUE;
};
///////////////////////////////////////////////////////////
// BOOL GetIDef (IINST iinst, OUT IDEF *pIDef, OUT USHORT * piBuf)
// get the idef given the iinst:
///////////////////////////////////////////////////////////
BOOL Ncb::GetIDef (HTARGET hTarget, IINST iinst, OUT IDEF * piDef, OUT USHORT * piBuf)
{
USHORT iModHdr = IModFrIinst ((IINST)iinst);
USHORT iProp = IPropFrIinst ((IINST)iinst);
USHORT index;
USHORT cParam;
NI * rgParam;
NCB_ENTITY * pEn;
_ASSERT (iModHdr < m_rgModHdr.size());
if (iProp >= m_rgModHdr[iModHdr].m_cProp)
return FALSE;
if (hTarget != (HTARGET)-1)
{
if (!isModInTarget (hTarget, iModHdr))
return FALSE;
};
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
if (iProp == 0)
{
rgParam = m_rgContBuf[index].m_rgParam;
cParam = m_rgContBuf[index].m_rgProp[0].m_iParam;
}
else
{
rgParam = &(m_rgContBuf[index].m_rgParam[m_rgContBuf[index].m_rgProp[iProp-1].m_iParam]);
cParam = m_rgContBuf[index].m_rgProp[iProp].m_iParam -
m_rgContBuf[index].m_rgProp[iProp-1].m_iParam;
}
pEn =&(m_rgContBuf[index].m_rgProp[iProp].m_en);
// lock the read buffer
m_iReadLock = index;
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return FALSE;
_ASSERT (m_rgRWBuf[index].m_iModHdr == iModHdr);
if (m_rgRWBuf[index].m_rgProp.size() <= iProp)
return FALSE;
cParam = m_rgRWBuf[index].m_rgProp[iProp].m_rgParam.size();
if (cParam > 0)
rgParam = &(m_rgRWBuf[index].m_rgProp[iProp].m_rgParam[0]);
else
rgParam = NULL;
pEn = &m_rgRWBuf[index].m_rgProp[iProp].m_en;
}
// no need to search if it is already a definition:
if (pEn->m_atr & INST_NCB_ATR_DEFN)
{
*piDef = (IDEF) iinst;
*piBuf = index;
// release the read lock buffer, so the buffer can be overwritten now
m_iReadLock = NCB_MOD_BUF_SIZE;
return TRUE;
}
// search for the real definition, given the rgParam and cParam
if (!GetIDef (hTarget, pEn, rgParam, cParam, piDef, piBuf))
{
// release the read lock buffer, so the buffer can be overwritten now
m_iReadLock = NCB_MOD_BUF_SIZE;
return FALSE;
}
// release the read lock buffer, so the buffer can be overwritten now
m_iReadLock = NCB_MOD_BUF_SIZE;
return TRUE;
};
//////////////////////////////////////////////////////////////////////////////////////////////////
// GetIDef()
//////////////////////////////////////////////////////////////////////////////////////////////////
BOOL Ncb::GetIDef (HTARGET hTarget, NCB_ENTITY * pEn, NI * rgParam, USHORT cParam, OUT IDEF * piDef, OUT USHORT * piBuf)
{
BOOL bFound = FALSE;
EnumNi enm(hTarget, pEn->m_ni, this);
while (enm.GetNext())
{
// if it is not in the write buffer then must be in the read buffer
if (enm.m_BufType != NCB_STATMOD_LOAD_WRITE)
{
if (m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_typ == pEn->m_typ &&
(m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_atr & INST_NCB_ATR_DEFN))
{
if (enm.m_iProp == 0)
bFound = CheckParam (rgParam, cParam, m_rgContBuf[enm.m_index].m_rgParam,
m_rgContBuf[enm.m_index].m_rgProp[0].m_iParam);
else
{
bFound = CheckParam (rgParam, cParam,
&m_rgContBuf[enm.m_index].m_rgParam[m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp-1].m_iParam],
m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_iParam -
m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp - 1].m_iParam);
}
if (bFound)
{
// IINST creation:
// REVIEW: should do similar to DupArray()
if (piDef == NULL)
piDef = (IDEF *) malloc (sizeof (IINST));
*piDef = (enm.m_iModHdr << 16) | enm.m_iProp;
*piBuf = enm.m_index;
UpdateBuffer(enm.m_index);
return TRUE;
}
}
}
else // check the write buffer:
{
if (m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_typ == pEn->m_typ &&
m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_atr & INST_NCB_ATR_DEFN)
{
bFound = CheckParam (rgParam, cParam, &m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_rgParam[0],
m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_rgParam.size());
if (bFound)
{
*piDef = (enm.m_iModHdr << 16) | enm.m_iProp;
*piBuf = enm.m_index;
return TRUE;
}
}
}
}
return FALSE;
};
// will return TRUE is acceptance ration is > 0.5 for all parameters.
#define ACCEPTANCE_RATIO 0.5
//////////////////////////////////////////////////////////////////
// BOOL CheckParam()
//for functions and variables:
// variables:
// will check if it is the same type or not:
// function:
// checks if it is the same return value, and params.
//////////////////////////////////////////////////////////////////
BOOL Ncb::CheckParam(NI * rg1, USHORT c1, NI * rg2, USHORT c2)
{
double flRatio = 1.0;
double flCur;
USHORT i;
unsigned cbMatch, cbMin;
// number of params are not the same so, just return FALSE:
if (c1 != c2)
return FALSE;
i = 1; // ignoring the return type
while (flRatio > ACCEPTANCE_RATIO && i < c1)
{
if (!NiFuzzyMatch (m_pnm, rg1[i], rg2[i], cbMatch, cbMin))
{
flCur = (double)cbMatch / (double)cbMin;
if (flRatio > flCur)
flRatio = flCur;
}
i++;
}
if (flRatio > ACCEPTANCE_RATIO)
return TRUE;
return FALSE;
};
//////////////////////////////////////////////////////////////////
// BOOL checkParam()
//for functions and variables:
// variables:
// will check if it is the same type or not:
// function:
// checks if it is the same return value, and params.
//////////////////////////////////////////////////////////////////
BOOL Ncb::checkParams(IINST iinst, SZ * pszParam, ULONG cParam)
{
double flRatio = 1.0;
double flCur;
USHORT i;
unsigned cbMatch, cbMin;
NI * rgParam = NULL;
ULONG count = 0;
SZ szParam;
getParams (iinst, &rgParam, &count);
// number of params are not the same so, just return FALSE:
if (cParam != count)
goto fail;
i = 1; // ignoring the return type
while (flRatio > ACCEPTANCE_RATIO && i < count)
{
szParam = szFrNi (rgParam[i]);
if (!SzFuzzyMatch (pszParam[i], szParam, cbMatch, cbMin))
{
flCur = (double)cbMatch / (double)cbMin;
if (flRatio > flCur)
flRatio = flCur;
}
i++;
}
disposeArray (rgParam);
if (flRatio > ACCEPTANCE_RATIO)
return TRUE;
else
return FALSE;
fail:
disposeArray (rgParam);
return FALSE;
};
///////////////////////////////////////////////////////////////////
// imodInfo()
// returns the name of the module
///////////////////////////////////////////////////////////////////
BOOL Ncb::imodInfo(IMOD imod, OUT SZ *pszModule)
{
_ASSERT (imod < m_rgModHdr.size());
*pszModule = szFrNi (m_rgModHdr[imod].m_ni);
return TRUE;
};
char *ptypNCBtab[] = {
"undef", // SBR_TYP_UNKNOWN
"function", // SBR_TYP_FUNCTION
"label", // SBR_TYP_LABEL
"parameter", // SBR_TYP_PARAMETER
"variable", // SBR_TYP_VARIABLE
"constant", // SBR_TYP_CONSTANT
"macro", // SBR_TYP_MACRO
"typedef", // SBR_TYP_TYPEDEF
"struct_name", // SBR_TYP_STRUCNAM
"enum_name", // SBR_TYP_ENUMNAM
"enum_mem", // SBR_TYP_ENUMMEM
"union_name", // SBR_TYP_UNIONNAM
"segment", // SBR_TYP_SEGMENT
"group", // SBR_TYP_GROUP
"program", // SBR_TYP_PROGRAM
"class", // SBR_TYP_CLASSNAM
"mem_func", // SBR_TYP_MEMFUNC
"mem_var", // SBR_TYP_MEMVAR
};
//////////////////////////////////////////////////////////////////
// szFrTyp()
// Get the name of the type
//////////////////////////////////////////////////////////////////
SZ Ncb::szFrTyp(TYP typ)
{
return ptypNCBtab[typ];
};
#define C_NCB_ATR 12
char *patrNCBtab[] = {
"local", // SBR_ATR_LOCAL
"static", // SBR_ATR_STATIC
"shared", // SBR_ATR_SHARED
"near", // SBR_ATR_NEAR
"common", // SBR_ATR_COMMON
"decl_only", // SBR_ATR_DECL_ONLY
"public", // SBR_ATR_PUBLIC
"named", // SBR_ATR_NAMED
"module", // SBR_ATR_MODULE
"virtual", // SBR_ATR_VIRTUAL
"private", // SBR_ATR_PRIVATE
"protected", // SBR_ATR_PROTECT
};
////////////////////////////////////////////////////
// szFrAtr (ATR)
// get the name of the attributes, separated by a ':'
////////////////////////////////////////////////////
SZ Ncb::szFrAtr(ATR atr)
{
static char buf[512];
buf[0] = 0;
for (int i=0; i < C_NCB_ATR; i++)
{
if (atr & (1<<i))
{
if (buf[0])
strcat(buf, ":");
strcat(buf, patrNCBtab[i]);
}
}
return buf;
};
////////////////////////////////////////////////////////
// getIinstByvalue()
// get the IINST given the name, types and attributes
// SLOW (?) operation since must load each module one by one
////////////////////////////////////////////////////////
BOOL Ncb::getIinstByvalue(SZ sz, TYP typ, ATR atr, OUT IINST *piinst)
{
return getIinstByvalue ((HTARGET)-1, sz, typ, atr, piinst);
};
/////////////////////////////////////////////////////////
BOOL Ncb::getIinstByvalue(HTARGET hTarget, SZ sz, TYP typ, ATR atr, OUT IINST *piinst)
{
// load every module and find the same NI:
// may not need to load the module content if
// the corresponding ni is not in the cache.
EnumNi enm (hTarget, sz, this);
while (enm.GetNext())
{
if (enm.m_BufType != NCB_STATMOD_LOAD_WRITE)
{ // make sure that it has the same ATR_DEFN or ATR_DECL
// and make sure that the reset of the attribute bits are
// the subset of the one in the database:
if (((m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_atr & atr) == atr) &&
m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_typ == typ)
{
// IINST creation:
*piinst = (enm.m_iModHdr << 16) | enm.m_iProp;
UpdateBuffer(enm.m_index);
return TRUE;
}
}
else
{
if (((m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_atr & atr) == atr) &&
m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_typ == typ)
{
*piinst = (enm.m_iModHdr << 16) | enm.m_iProp;
return TRUE;
}
}
}
return FALSE;
};
////////////////////////////////////////////////////////////
// UpdateBuffer(USHORT index);
// update priority buffer ordering by marking index as the
// most up-to-date:
////////////////////////////////////////////////////////////
void Ncb::UpdateBuffer (USHORT index)
{
BYTE iOld;
USHORT i;
iOld = m_rgContBuf[index].m_prio;
for (i = 0; i < NCB_MOD_BUF_SIZE; i++)
{
if (m_rgContBuf[i].m_prio < iOld)
m_rgContBuf[i].m_prio++;
}
m_rgContBuf[index].m_prio = 0;
};
////////////////////////////////////////////////////////
// GetiPropFrMod (NI ni, USHORT iModHdr, OUT USHORT ** prgProp)
// given the index for modhdr, and Ni, return an array of iProps
/////////////////////////////////////////////////////////
BOOL Ncb::GetIPropFrMod(NI ni, USHORT iModHdr, OUT USHORT *pindex, OUT USHORT ** prgProp, OUT ULONG * pcProp)
{
USHORT index;
// temporary array to hold iProps that have the same NI
// in the module
Array<USHORT> rgProp;
*prgProp = NULL;
*pcProp = 0;
if (*pindex >= NCB_MOD_BUF_SIZE)
{
// since the bit is set, now we have to load
// the module content since it may be in there:
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
}
else
index = *pindex;
// now module content is loaded, so start binary search
// we have to call twice, once for classes
// and another for other info
GetIPropFrMod (ni, m_rgModHdr[iModHdr].m_cClassProp,
m_rgContBuf[index].m_rgProp, 0, &rgProp);
GetIPropFrMod (ni,
m_rgModHdr[iModHdr].m_cProp - m_rgModHdr[iModHdr].m_cClassProp,
&m_rgContBuf[index].m_rgProp[m_rgModHdr[iModHdr].m_cClassProp],
m_rgModHdr[iModHdr].m_cClassProp, &rgProp);
*pindex = index;
return DupArray (prgProp, pcProp, rgProp);
};
////////////////////////////////////////////////////////
// void GetIPropFrMod (NI ni, USHORT cProp, NCB_PROP * rgProp, OUT Array<USHORT> * prgProp)
// get array of iprop given an array of NCB_PROP
////////////////////////////////////////////////////////
void Ncb::GetIPropFrMod (NI ni, USHORT cProp, NCB_PROP * rgProp, USHORT disp, OUT Array<USHORT> * prgProp)
{
// rgProp has a sorted NIs
_ASSERT (rgProp);
_ASSERT (prgProp);
// no prop in this module, so just return.
if (cProp == 0)
return;
// binary search:
// rgProp has a sorted strings so it must search all Ni's
USHORT i;
USHORT iProp;
for (i = 0 ; i < cProp; i++)
{
if (rgProp[i].m_en.m_ni == ni)
{
iProp = i + disp;
prgProp->append (iProp);
}
}
};
////////////////////////////////////////////////////////
// GetiPropFrMod (SZ sz, USHORT iModHdr, OUT USHORT ** prgProp)
// given the index for modhdr, and Ni, return an array of iProps
/////////////////////////////////////////////////////////
BOOL Ncb::GetIPropFrMod(SZ sz, USHORT iModHdr, OUT USHORT *pindex, OUT USHORT ** prgProp, OUT ULONG * pcProp)
{
USHORT index;
// temporary array to hold iProps that have the same NI
// in the module
Array<USHORT> rgProp;
*prgProp = NULL;
*pcProp = 0;
if (*pindex >= NCB_MOD_BUF_SIZE)
{
// since the bit is set, now we have to load
// the module content since it may be in there:
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
}
else
index = *pindex;
// now module content is loaded, so start binary search
// we have to call twice, once for classes
// and another for other info
GetIPropFrMod (sz, m_rgModHdr[iModHdr].m_cClassProp,
m_rgContBuf[index].m_rgProp, 0, &rgProp);
GetIPropFrMod (sz,
m_rgModHdr[iModHdr].m_cProp - m_rgModHdr[iModHdr].m_cClassProp,
&m_rgContBuf[index].m_rgProp[m_rgModHdr[iModHdr].m_cClassProp],
m_rgModHdr[iModHdr].m_cClassProp, &rgProp);
*pindex = index;
return DupArray (prgProp, pcProp, rgProp);
};
////////////////////////////////////////////////////////
// void GetIPropFrMod (SZ sz, USHORT cProp, NCB_PROP * rgProp, OUT Array<USHORT> * prgProp)
// get array of iprop given an array of NCB_PROP
////////////////////////////////////////////////////////
void Ncb::GetIPropFrMod (SZ sz, USHORT cProp, NCB_PROP * rgProp, USHORT disp, OUT Array<USHORT> * prgProp)
{
// no prop in this module, so just return.
if (cProp == 0)
return;
// rgProp has a sorted NIs
_ASSERT (rgProp);
_ASSERT (prgProp);
// rgProp has a sorted strings so it must search all Ni's
USHORT i;
USHORT iProp;
if (!FindFirstNi (sz, cProp, rgProp, &i))
return;
while (i < cProp)
{
if (_tcscmp (szFrNi(rgProp[i].m_en.m_ni), sz) == 0)
{
iProp = i + disp;
prgProp->append (iProp);
i++;
}
else
break;
};
};
///////////////////////////////////////////////////////////
// BOOL FindFirstSz (SZ sz, USHORT cClassProp, NCB_PROP * rgProp, OUT USHORT * piFirst)
// do a binary search on array rgProp to find the first matched NI
// rgProp has a sorted NIs, and possible multiple NIs
////////////////////////////////////////////////////////////
BOOL Ncb::FindFirstNi (SZ sz, USHORT cProp, NCB_PROP * rgProp, OUT USHORT * piFirst)
{
_ASSERT (rgProp);
_ASSERT (cProp);
USHORT iMin = 0;
USHORT iMax = cProp - 1;
USHORT iMid;
// full binary search (ie: never breaks since we want to find
// the first ni)
while (iMin < iMax)
{
iMid = iMin + (iMax - iMin)/2;
if (_tcscmp (szFrNi(rgProp[iMid].m_en.m_ni),sz) >= 0)
iMax = iMid;
else
iMin = iMid + 1;
};
if (_tcscmp (szFrNi (rgProp[iMin].m_en.m_ni),sz) == 0)
{
*piFirst = iMin;
return TRUE;
}
return FALSE;
};
///////////////////////////////////////////////////////
// getOverloadArray()
////////////////////////////////////////////////////////
BOOL Ncb::getOverloadArray(SZ sz, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
return getOverloadArray ((HTARGET)-1, sz, mbf, ppiinst, pciinst);
};
///////////////////////////////////////////////////////
// getOverloadArray()
////////////////////////////////////////////////////////
BOOL Ncb::getOverloadArray(HTARGET hTarget, SZ sz, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
Array<IINST> rgIinst;
IINST iinstArr;
*ppiinst = NULL;
*pciinst = 0;
EnumNi enm(hTarget, sz, this);
// iterate each module that has this NI:
while (enm.GetNext())
{
if (enm.m_BufType == NCB_STATMOD_LOAD_WRITE)
{
if (!(m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
if (TypFilter(m_rgRWBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_typ, mbf))
{
iinstArr = (enm.m_iModHdr << 16) | enm.m_iProp;
rgIinst.append (iinstArr);
}
}
else
{
if (!(m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
if (TypFilter(m_rgContBuf[enm.m_index].m_rgProp[enm.m_iProp].m_en.m_typ, mbf))
{
iinstArr = (enm.m_iModHdr << 16) | enm.m_iProp;
rgIinst.append (iinstArr);
}
}
}
if (rgIinst.size() == 0)
return FALSE;
return DupArray (ppiinst, pciinst, rgIinst);
};
/////////////////////////////////////////////////////////
// getUsesArray()
/////////////////////////////////////////////////////////
BOOL Ncb::getUsesArray(IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
*ppiinst = NULL;
*pciinst = 0;
return FALSE;
};
//////////////////////////////////////////////////////////
// getUsedByArray()
//////////////////////////////////////////////////////////
BOOL Ncb::getUsedByArray(IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
*ppiinst = NULL;
*pciinst = 0;
return FALSE;
};
/////////////////////////////////////////////////////////
// getBaseArray()
// given the IINST (which I suppose must be a class name), it will return
// its base class names.
/////////////////////////////////////////////////////////
BOOL Ncb::getBaseArray(IINST iinst, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
*ppiinst = NULL;
*pciinst = 0;
return getBaseArray ((HTARGET)-1, iinst, ppiinst, pciinst);
};
/////////////////////////////////////////////////////////
BOOL Ncb::getBaseArray(HTARGET hTarget, IINST iinst, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
IINST iinstDef;
USHORT iBuf;
USHORT iModHdr;
USHORT iProp;
USHORT cUse;
*ppiinst = NULL;
*pciinst = 0;
if (!GetIDef (hTarget, iinst, (IDEF *)&iinstDef, &iBuf))
return FALSE;
iModHdr = IModFrIinst (iinstDef);
iProp = IPropFrIinst (iinstDef);
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_WRITE)
{
if (m_rgRWBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgRWBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_MSGMAP)
return FALSE;
cUse = m_rgRWBuf[iBuf].m_rgProp[iProp].m_rgUse.size();
if (cUse == 0)
return FALSE;
return (getBaseArray (ppiinst, pciinst, iModHdr, &m_rgRWBuf[iBuf].m_rgProp[iProp].m_rgUse[0],
cUse));
}
else
{
_ASSERT (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_READ);
_ASSERT (iBuf< NCB_MOD_BUF_SIZE);
if (m_rgContBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgContBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_MSGMAP)
return FALSE;
if (iProp == 0)
{
cUse = m_rgContBuf[iBuf].m_rgProp[0].m_iUse;
if (cUse == 0)
return FALSE;
return getBaseArray (ppiinst, pciinst, iModHdr, m_rgContBuf[iBuf].m_rgUse, cUse);
}
cUse = m_rgContBuf[iBuf].m_rgProp[iProp].m_iUse - m_rgContBuf[iBuf].m_rgProp[iProp -1].m_iUse;
if (cUse == 0)
return FALSE;
return getBaseArray (ppiinst, pciinst, iModHdr, &m_rgContBuf[iBuf].m_rgUse[m_rgContBuf[iBuf].m_rgProp[iProp-1].m_iUse], cUse);
}
return FALSE;
};
////////////////////////////////////////////////////
// getBaseArray (OUT IINST ** ppiinst, OUT ULONG * pciinst, USHORT iModHdr, NCB_USE * rgUse, USHORT count)
//////////////////////////////////////////////////////////
BOOL Ncb::getBaseArray (OUT IINST ** ppiinst, OUT ULONG * pciinst, USHORT iModHdr, NCB_USE * rgUse, USHORT count)
{
Array<IINST> rgiinst;
USHORT i;
IINST iinst;
*ppiinst = NULL;
*pciinst = 0;
for (i = 0; i < count; i++)
{
if (rgUse[i].m_kind == NCB_KIND_BASECLASS)
{
iinst = (iModHdr << 16) | rgUse[i].m_iProp;
rgiinst.append (iinst);
}
}
if (rgiinst.size() == 0)
return FALSE;
return (DupArray (ppiinst, pciinst, rgiinst));
};
//////////////////////////////////////////////////////////
// getDervArray()
//////////////////////////////////////////////////////////
BOOL Ncb::getDervArray(IINST iinst, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
*ppiinst = NULL;
*pciinst = 0;
return getDervArray ((HTARGET)-1, iinst, ppiinst, pciinst);
};
////////////////////////////////////////////////////////////////////////////
BOOL Ncb::getDervArray(HTARGET hTarget, IINST iinst, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
NCB_ENTITY en;
USHORT iCurModHdr = (USHORT)-1;
Array<IINST> rgIinst;
IINST iinstDerv;
USHORT i,j;
USHORT iUse;
*ppiinst = NULL;
*pciinst = 0;
if (!EnFrIinst (iinst, &en))
return FALSE;
_ASSERT (en.m_typ == INST_TYP_CLASSNAM);
EnumNi enm(hTarget, en.m_ni, this);
// iterate each module that has this NI:
while (enm.GetNext())
{
if (enm.m_BufType == NCB_STATMOD_LOAD_WRITE)
{
for (i = 0; i < m_rgRWBuf[enm.m_index].m_rgProp.size(); i++)
{
if (m_rgRWBuf[enm.m_index].m_rgProp[i].m_en.m_typ != INST_TYP_CLASSNAM)
continue;
if (!(m_rgRWBuf[enm.m_index].m_rgProp[i].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
if (m_rgRWBuf[enm.m_index].m_rgProp[i].m_rgUse.size() == 0)
continue;
for (j = 0; j < m_rgRWBuf[enm.m_index].m_rgProp[i].m_rgUse.size(); j++)
{
if (m_rgRWBuf[enm.m_index].m_rgProp
[m_rgRWBuf[enm.m_index].m_rgProp[i].m_rgUse[j].m_iProp].m_en.m_ni ==
en.m_ni)
{
iinstDerv = (enm.m_iModHdr << 16) | i;
rgIinst.append (iinstDerv);
break;
}
}
}
}
else
{
for (i = 0; i < m_rgModHdr[enm.m_iModHdr].m_cClassProp; i++)
{
if (m_rgContBuf[enm.m_index].m_rgProp[i].m_en.m_atr & INST_NCB_ATR_DEFN)
continue;
if (i == 0)
iUse = 0;
else
iUse = m_rgContBuf[enm.m_index].m_rgProp[i-1].m_iUse;
for (j = iUse; j < m_rgContBuf[enm.m_index].m_rgProp[i].m_iUse; j++)
{
if (m_rgContBuf[enm.m_index].m_rgProp
[m_rgContBuf[enm.m_index].m_rgUse[j].m_iProp].m_en.m_ni ==
en.m_ni)
{
iinstDerv = (enm.m_iModHdr << 16) | i;
rgIinst.append (iinstDerv);
break;
}
}
}
}
enm.SkipNi(); // skip Nis for this module
}
if (rgIinst.size() == 0)
return FALSE;
return DupArray (ppiinst, pciinst, rgIinst);
};
//////////////////////////////////////////////////////////
// BOOL EnFrIinst (iinst, en)
//////////////////////////////////////////////////////////
BOOL Ncb::EnFrIinst (IINST iinst, NCB_ENTITY * pEn)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
USHORT index;
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{ // check item from read-only buffer, loading it if necessary
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
_ASSERT (index < NCB_MOD_BUF_SIZE);
if (iProp >= m_rgModHdr[iModHdr].m_cProp)
return FALSE;
*pEn = m_rgContBuf[index].m_rgProp[iProp].m_en;
}
else
{ // check item from write buffer
if (!FindWriteIndex (iModHdr, &index))
return FALSE;
_ASSERT (index < m_rgRWBuf.size());
if (iProp >= m_rgRWBuf[index].m_rgProp.size())
return FALSE;
*pEn = m_rgRWBuf[index].m_rgProp[iProp].m_en;
}
return TRUE;
};
//////////////////////////////////////////////////////////
// BOOL EnFrIinst (iinst, en)
//////////////////////////////////////////////////////////
BOOL Ncb::EnFrIinst (IINST iinst, NCB_ENTITY * pEn, HTARGET hTarget)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
if (!isModInTarget (hTarget, iModHdr))
return FALSE;
return EnFrIinst (iinst, pEn);
};
//////////////////////////////////////////////////////////
// getMembersArray()
///////////////////////////////////////////////////////////
BOOL Ncb::getMembersArray(IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
*ppiinst = NULL;
*pciinst = 0;
return getMembersArray ((HTARGET)-1, iinst, mbf, ppiinst, pciinst);
};
/////////////////////////////////////////////////////////////
BOOL Ncb::getMembersArray(HTARGET hTarget, IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
IINST iinstDef;
USHORT iBuf;
USHORT iModHdr;
USHORT iProp;
USHORT i;
Array<IINST> rgiinst;
USHORT iCurProp;
IINST iinstCur;
TYP typ;
ATR atr;
USHORT iMin = 0;
*ppiinst = NULL;
*pciinst = 0;
if (!GetIDef (hTarget, iinst, (IDEF *)&iinstDef, &iBuf))
return FALSE;
iModHdr = IModFrIinst (iinstDef);
iProp = IPropFrIinst (iinstDef);
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_WRITE)
{
if (m_rgRWBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgRWBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_MSGMAP)
return FALSE;
for (i = 0; i < m_rgRWBuf[iBuf].m_rgProp[iProp].m_rgUse.size() ; i++)
{
if (m_rgRWBuf[iBuf].m_rgProp[iProp].m_rgUse[i].m_kind != NCB_KIND_CONTAINMENT)
continue;
iCurProp = m_rgRWBuf[iBuf].m_rgProp[iProp].m_rgUse[i].m_iProp;
typ = m_rgRWBuf[iBuf].m_rgProp[iCurProp].m_en.m_typ;
atr = m_rgRWBuf[iBuf].m_rgProp[iCurProp].m_en.m_atr;
if (TypFilter(typ, mbf))
{
if ((typ == INST_TYP_CLASSNAM) && (atr & INST_NCB_ATR_DECL))
continue;
iinstCur = (iModHdr << 16) | iCurProp;
rgiinst.append (iinstCur);
}
}
}
else
{
_ASSERT (m_rgStat[iModHdr] == NCB_STATMOD_LOAD_READ);
_ASSERT (iBuf< NCB_MOD_BUF_SIZE);
if (m_rgContBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgContBuf[iBuf].m_rgProp[iProp].m_en.m_typ != INST_TYP_MSGMAP)
return FALSE;
if (iProp != 0)
iMin = m_rgContBuf[iBuf].m_rgProp[iProp-1].m_iUse;
for (i = iMin; i < m_rgContBuf[iBuf].m_rgProp[iProp].m_iUse; i++)
{
if (m_rgContBuf[iBuf].m_rgUse[i].m_kind != NCB_KIND_CONTAINMENT)
continue;
iCurProp = m_rgContBuf[iBuf].m_rgUse[i].m_iProp;
typ = m_rgContBuf[iBuf].m_rgProp[iCurProp].m_en.m_typ;
atr = m_rgContBuf[iBuf].m_rgProp[iCurProp].m_en.m_atr;
if (TypFilter(typ, mbf))
{
if ((typ == INST_TYP_CLASSNAM) && (atr & INST_NCB_ATR_DECL))
continue;
iinstCur = (iModHdr << 16) | iCurProp;
rgiinst.append (iinstCur);
}
}
}
if (rgiinst.size() == 0)
return TRUE;
return DupArray (ppiinst, pciinst, rgiinst);
};
//////////////////////////////////////////////
// TypFilter()
//////////////////////////////////////////////
BOOL Ncb::TypFilter (USHORT typ, MBF mbf)
{
if (mbf == mbfAll)
return TRUE;
switch (typ) {
case INST_TYP_FUNCTION:
case INST_TYP_LABEL:
case INST_TYP_PROGRAM:
case INST_TYP_MEMFUNC:
return !!(mbf & mbfFuncs);
case INST_TYP_PARAMETER:
case INST_TYP_VARIABLE:
case INST_TYP_SEGMENT:
case INST_TYP_GROUP:
case INST_TYP_MEMVAR:
return !!(mbf & mbfVars);
case INST_TYP_CONSTANT:
case INST_TYP_MACRO:
case INST_TYP_ENUMMEM:
return !!(mbf & mbfMacros);
case INST_TYP_TYPEDEF:
case INST_TYP_ENUMNAM:
case INST_TYP_UNIONNAM:
return !!(mbf & mbfTypes);
case INST_TYP_CLASSNAM:
case INST_TYP_STRUCNAM:
return !!(mbf & mbfClass);
case INST_TYP_INCL:
return !!(mbf & mbfIncl);
case INST_TYP_MSGMAP:
case INST_TYP_MSGITEM:
return !!(mbf & mbfMsgMap);
}
return FALSE;
}
// primitives for getting definition and reference information
///////////////////////////////////////////////////////////
// getDefArray()
///////////////////////////////////////////////////////////
BOOL Ncb::getDefArray(IINST iinst, OUT IDEF **ppidef, OUT ULONG *pciidef)
{
*ppidef = NULL;
*pciidef = 0;
return getDefArray ((HTARGET)-1, iinst, ppidef, pciidef);
};
////////////////////////////////////////////////////////////
BOOL Ncb::getDefArray(HTARGET hTarget, IINST iinst, OUT IDEF **ppidef, OUT ULONG *pciidef)
{
USHORT iBuf;
*ppidef = NULL;
*pciidef = 0;
IDEF idef;
_ASSERT (ppidef);
if (!GetIDef (hTarget, iinst, &idef, &iBuf))
return FALSE;
*pciidef = 1;
*ppidef = (IDEF *) malloc (sizeof (IDEF));
**ppidef = idef;
return TRUE;
};
///////////////////////////////////////////////////////////
// getRefArray()
///////////////////////////////////////////////////////////
BOOL Ncb::getRefArray(IINST iinst, OUT IREF **ppiref, OUT ULONG *pciiref)
{
*ppiref = (IREF *) malloc (sizeof (IREF));
**ppiref = iinst;
*pciiref = 1;
return TRUE;
};
// primitives for managing source module contents
/////////////////////////////////////////////////////////
// getModuleContents()
/////////////////////////////////////////////////////////
BOOL Ncb::getModuleContents(IMOD imod, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
USHORT index;
Array<IINST> rgiinst;
IINST iinst;
USHORT i;
*ppiinst = NULL;
*pciinst = 0;
if (m_rgStat[imod] == NCB_STATMOD_LOAD_WRITE)
{
if (!FindWriteIndex (imod, &index))
return FALSE;
for (i = 0; i < m_rgRWBuf[index].m_rgProp.size() ; i++)
{
if (mbf != mbfAll)
{
if (!(m_rgRWBuf[index].m_rgProp[i].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
}
if (TypFilter (m_rgRWBuf[index].m_rgProp[i].m_en.m_typ, mbf))
{
iinst = (imod << 16) | i;
rgiinst.append (iinst);
}
}
}
else
{
if (!LoadModForRead (m_pdb, imod, &index))
return FALSE;
for (i = 0; i < m_rgModHdr[imod].m_cProp; i++)
{
if (!(m_rgContBuf[index].m_rgProp[i].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
if (TypFilter (m_rgContBuf[index].m_rgProp[i].m_en.m_typ, mbf))
{
iinst = (imod << 16) | i;
rgiinst.append (iinst);
}
}
}
if (rgiinst.size() == 0)
return FALSE;
return DupArray (ppiinst, pciinst, rgiinst);
};
//////////////////////////////////////////////////////////
// getModuleByName()
//////////////////////////////////////////////////////////
BOOL Ncb::getModuleByName(SZ sz, OUT IMOD *pimod)
{
USHORT i;
for (i = 0; i < m_rgModHdr.size(); i++)
{
if (_tcsicmp (szFrNi (m_rgModHdr[i].m_ni), sz) == 0)
{
*pimod = i;
return TRUE;
}
}
return FALSE;
};
//////////////////////////////////////////////////////////
// getAllModulesArray()
// REVIEW:
// Needs to utilize the target information!!
// Right now it just returns all the modules in the
// database.
//////////////////////////////////////////////////////////
BOOL Ncb::getAllModulesArray(OUT IMOD **ppimod, OUT ULONG *pcimod)
{
USHORT i;
Array<IMOD> rgimod;
*ppimod = NULL;
*pcimod = 0;
for (i = 0; i < m_rgModHdr.size(); i++)
rgimod.append (i);
return DupArray(ppimod, pcimod, rgimod);
};
//////////////////////////////////////////////////////////
BOOL Ncb::getAllModulesArray (HTARGET hTarget, OUT IMOD **ppimod, OUT ULONG * pcimod)
{
USHORT i;
USHORT iTarget;
Array<IMOD> rgimod;
if (!FindITarget (hTarget, &iTarget))
return FALSE;
for (i = 0; i < m_rgTargetInfo[iTarget].m_rgModInfo.size(); i++)
{
rgimod.append (m_rgTargetInfo[iTarget].m_rgModInfo[i].m_iModHdr);
}
return DupArray (ppimod, pcimod, rgimod);
};
///////////////////////////////////////////////////////////
// disposeArray()
// call this when a computed array is no longer required
////////////////////////////////////////////////////////////
void Ncb::disposeArray(void *pAnyArray)
{
if (pAnyArray)
free(pAnyArray);
};
////////////////////////////////////////////////////////
// formatDname()
// call this to get a pretty form of a decorated name
// REVIEW:decided not to decorate name for a moment.
// (Is it really needed for NCB?)
////////////////////////////////////////////////////////
SZ Ncb::formatDname(SZ szDecor)
{
return szDecor;
};
////////////////////////////////////////////////////////
// fInstFilter()
// call this to do category testing on instances
////////////////////////////////////////////////////////
BOOL Ncb::fInstFilter(IINST iinst, MBF mbf)
{
NCB_ENTITY en;
if (!EnFrIinst (iinst, &en))
return FALSE;
return TypFilter (en.m_typ, mbf);
};
/////////////////////////////////////////////////////////
// primitives for converting index types
// iinstFrIref (IREF)
/////////////////////////////////////////////////////////
IINST Ncb::iinstFrIref(IREF iref)
{
// return the same id.
return iref;
};
//////////////////////////////////////////////////////////
// iinstFrIdef()
//////////////////////////////////////////////////////////
IINST Ncb::iinstFrIdef(IDEF idef)
{
return idef;
};
///////////////////////////////////////////////////////////
// iinstContextIref()
///////////////////////////////////////////////////////////
IINST Ncb::iinstContextIref(IREF iref)
{
return iref;
};
// general size information
///////////////////////////////////////////////////////////
// getStatistics ()
///////////////////////////////////////////////////////////
BOOL Ncb::getStatistics(BSC_STAT *)
{
//NYI
_ASSERT (FALSE);
return FALSE;
};
//////////////////////////////////////////////////////////
// getModuleStatistics ()
//////////////////////////////////////////////////////////
BOOL Ncb::getModuleStatistics(IMOD, BSC_STAT *)
{
// NYI
_ASSERT (FALSE);
return FALSE;
};
//////////////////////////////////////////////////////////
// IModFrIinst ()
// get the imod from IINST
//////////////////////////////////////////////////////////
USHORT Ncb::IModFrIinst (IINST iinst)
{
return (USHORT)((iinst & 0xffff0000) >> 16);
};
/////////////////////////////////////////////////////////
// IPropFrIinst()
// get the iProp from IINST
//////////////////////////////////////////////////////////
USHORT Ncb::IPropFrIinst (IINST iinst)
{
return (USHORT) (iinst & 0x0000ffff);
};
//////////////////////////////////////////////////////////
// getParams()
//////////////////////////////////////////////////////////
SZ Ncb::getParams (IINST iinst)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
static char buf[512];
USHORT i;
SZ_CONST szParam;
NI * rgParam = NULL;
ULONG cParam = 0;
buf[0] = NULL;
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (getParams (iinst, &rgParam, &cParam))
{
// skip return type:
for (i = 1; i < cParam; i++)
{
m_pnm->getName (rgParam[i], &szParam);
if (i == 1)
strcat (buf, szParam);
else
{
strcat (buf, ", ");
strcat (buf, szParam);
}
}
}
disposeArray(rgParam);
return buf;
};
//////////////////////////////////////////////////////////
// getParams()
//////////////////////////////////////////////////////////
BOOL Ncb::getParams (IINST iinst, OUT NI **prgParam, OUT ULONG * pcParam)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
USHORT index;
USHORT i, iMin;
Array<NI> arrParam;
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
_ASSERT (index < NCB_MOD_BUF_SIZE);
if (iProp == 0)
iMin = 0;
else
iMin = m_rgContBuf[index].m_rgProp[iProp-1].m_iParam;
for (i = iMin ; i < m_rgContBuf[index].m_rgProp[iProp].m_iParam;i++)
arrParam.append (m_rgContBuf[index].m_rgParam[i]);
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return FALSE;
if (m_rgRWBuf[index].m_rgProp.size() <= iProp)
return FALSE;
_ASSERT (m_rgRWBuf[index].m_iModHdr == iModHdr);
for (i = 0; i < m_rgRWBuf[index].m_rgProp[iProp].m_rgParam.size(); i++)
arrParam.append (m_rgRWBuf[index].m_rgProp[iProp].m_rgParam[i]);
}
return DupArray (prgParam, pcParam, arrParam);
};
USHORT Ncb::getNumParam (IINST iinst)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
USHORT index;
USHORT iMin;
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return 0;
_ASSERT (index < NCB_MOD_BUF_SIZE);
if (iProp == 0)
iMin = 0;
else
iMin = m_rgContBuf[index].m_rgProp[iProp-1].m_iParam;
// skip the return type
return (m_rgContBuf[index].m_rgProp[iProp].m_iParam - iMin - 1);
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return 0;
_ASSERT (m_rgRWBuf[index].m_iModHdr == iModHdr);
// skip the return type
if (m_rgRWBuf[index].m_rgProp.size() <= iProp)
return 0;
return m_rgRWBuf[index].m_rgProp[iProp].m_rgParam.size()-1;
}
return 0;
};
//////////////////////////////////////////////////////////////////////
// getParam()
//////////////////////////////////////////////////////////////////////
SZ Ncb::getParam (IINST iinst, USHORT ind)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
USHORT index;
static char buf[512];
USHORT iMin;
SZ_CONST szParam;
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
buf[0] = NULL;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return buf;
_ASSERT (index < NCB_MOD_BUF_SIZE);
if (iProp == 0)
iMin = 0;
else
iMin = m_rgContBuf[index].m_rgProp[iProp-1].m_iParam;
if (iMin + ind + 1 >= m_rgContBuf[index].m_rgProp[iProp].m_iParam)
return buf;
else
{
m_pnm->getName (m_rgContBuf[index].m_rgParam[iMin + ind + 1], &szParam);
strcat (buf, szParam);
}
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return buf;
_ASSERT (m_rgRWBuf[index].m_iModHdr == iModHdr);
// skip the return type
if (m_rgRWBuf[index].m_rgProp.size() <= iProp)
return buf;
if ((ind + 1) >= (USHORT)m_rgRWBuf[index].m_rgProp[iProp].m_rgParam.size())
return buf;
m_pnm->getName (m_rgRWBuf[index].m_rgProp[iProp].m_rgParam[ind+1], &szParam);
strcat (buf, szParam);
}
return buf;
};
/////////////////////////////////////////////////
// getType()
//////////////////////////////////////////////////
SZ Ncb::getType (IINST iinst)
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
USHORT index;
static char buf[512];
USHORT iMin;
SZ_CONST szParam;
_ASSERT (iModHdr < m_rgModHdr.size());
buf[0] = NULL;
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return buf;
_ASSERT (index < NCB_MOD_BUF_SIZE);
if (iProp == 0)
iMin = 0;
else
iMin = m_rgContBuf[index].m_rgProp[iProp-1].m_iParam;
// skip the return type
if (iMin < m_rgContBuf[index].m_rgProp[iProp].m_iParam)
{
m_pnm->getName (m_rgContBuf[index].m_rgParam[iMin], &szParam);
strcat (buf, szParam);
}
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return buf;
_ASSERT (m_rgRWBuf[index].m_iModHdr == iModHdr);
// skip the return type
if (m_rgRWBuf[index].m_rgProp.size() <= iProp)
return FALSE;
if (m_rgRWBuf[index].m_rgProp[iProp].m_rgParam.size() > 0)
{
m_pnm->getName (m_rgRWBuf[index].m_rgProp[iProp].m_rgParam[0], &szParam);
strcat (buf, szParam);
}
}
return buf;
};
///////////////////////////////////////////////////
// Ncb::getAllGlobalsArray()
// get global information
// check for "::" in the symbols:
// REVIEW:(should there be an easy way? so I don't have to
// getName() all Ni's ??
///////////////////////////////////////////////////
BOOL Ncb::getAllGlobalsArray (MBF mbf, OUT IINST ** ppiinst, OUT ULONG * pciinst)
{
return getAllGlobalsArray ((HTARGET)-1, mbf, ppiinst, pciinst);
};
///////////////////////////////////////////////////
BOOL Ncb::getAllGlobalsArray (HTARGET hTarget, MBF mbf, OUT IINST ** ppiinst, OUT ULONG * pciinst)
{
Array<IINST> rgiinst;
*ppiinst = NULL;
*pciinst = 0;
if (mbf & mbfClass)
GetGlobalClass (hTarget, &rgiinst);
GetGlobalOther (hTarget, mbf, &rgiinst);
return DupArray (ppiinst, pciinst, rgiinst);
}
////////////////////////////////////////////////////////
// Ncb::GetGlobalClass();
////////////////////////////////////////////////////////
BOOL Ncb::GetGlobalClass (HTARGET hTarget, Array<IINST> * prgiinst)
{
USHORT i;
for (i = 0; i < m_rgModHdr.size(); i++)
{
if (hTarget != (HTARGET)-1 && !isModInTarget (hTarget, i))
continue;
if (!GetGlobalClass (i, prgiinst))
return FALSE;
}
return TRUE;
};
///////////////////////////////////////////////////////
BOOL Ncb::GetGlobalClass (IMOD imod, Array<IINST> * prgiinst)
{
USHORT j;
USHORT index;
IINST iinst;
SZ_CONST szName;
if (m_rgStat[imod] == NCB_STATMOD_LOAD_WRITE)
{
if (!FindWriteIndex (imod, &index))
return FALSE;
// must search it linearly:
for (j = 0; j < m_rgRWBuf[index].m_rgProp.size(); j++)
{
if (!(m_rgRWBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
if (m_rgRWBuf[index].m_rgProp[j].m_en.m_typ == INST_TYP_CLASSNAM)
{
m_pnm->getName (m_rgRWBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinst = (imod << 16) | j;
prgiinst->append(iinst);
}
}
}
}
else // must load as read
{
if (!LoadModForRead (m_pdb, imod, &index))
return FALSE;
// can search just the first block:
for (j = 0; j < m_rgModHdr[imod].m_cClassProp; j++)
{
if (!(m_rgContBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
m_pnm->getName (m_rgContBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinst = (imod << 16) | j;
prgiinst->append (iinst);
}
}
}
return TRUE;
};
//////////////////////////////////////////////////////////////////////
// IsGlobalName (SZ_CONST sz)
//////////////////////////////////////////////////////////////////////
BOOL Ncb::IsGlobalName(SZ_CONST sz)
{
char * pch;
pch = strstr (sz, "::");
if (pch == NULL || pch == sz)
return TRUE;
return FALSE;
};
//////////////////////////////////////////////////////////////////////
// GetGlobalOther()
//////////////////////////////////////////////////////////////////////
BOOL Ncb::GetGlobalOther(HTARGET hTarget, MBF mbf, Array<IINST> * prgiinst)
{
USHORT i;
for (i = 0; i < m_rgModHdr.size(); i++)
{
if (hTarget != (HTARGET)-1 && !isModInTarget (hTarget, i))
continue;
if (!GetGlobalOther (i, mbf, prgiinst))
return FALSE;
}
return TRUE;
};
//////////////////////////////////////////////////////
BOOL Ncb::GetGlobalOther(IMOD imod, MBF mbf, Array<IINST> * prgiinst)
{
USHORT j;
USHORT index;
IINST iinst;
SZ_CONST szName;
if (m_rgStat[imod] == NCB_STATMOD_LOAD_WRITE)
{
if (!FindWriteIndex (imod, &index))
return FALSE;
// must search it linearly:
for (j = 0; j < m_rgRWBuf[index].m_rgProp.size(); j++)
{
if ((!(m_rgRWBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN)) ||
(m_rgRWBuf[index].m_rgProp[j].m_en.m_atr & INST_ATR_STATIC))
continue;
if (TypFilter(m_rgRWBuf[index].m_rgProp[j].m_en.m_typ, mbf) &&
m_rgRWBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgRWBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMVAR &&
m_rgRWBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMFUNC)
{
m_pnm->getName (m_rgRWBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinst = (imod << 16) | j;
prgiinst->append(iinst);
}
}
}
}
else // must load as read
{
if (!LoadModForRead (m_pdb, imod, &index))
return FALSE;
// can search just the first block:
for (j = m_rgModHdr[imod].m_cClassProp; j < m_rgModHdr[imod].m_cProp; j++)
{
if ((!(m_rgContBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN)) ||
(m_rgContBuf[index].m_rgProp[j].m_en.m_atr & INST_ATR_STATIC))
continue;
if (TypFilter (m_rgContBuf[index].m_rgProp[j].m_en.m_typ, mbf) &&
m_rgContBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgContBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMVAR &&
m_rgContBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMFUNC)
{
m_pnm->getName (m_rgContBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinst = (imod << 16) | j;
prgiinst->append (iinst);
}
}
}
}
return TRUE;
};
/////////////////////////////////////////////////////////////////////////////
// REVIEW: Ignatius
// combine these set of calls together with the one above.
/////////////////////////////////////////////////////////////////////////////
BOOL Ncb::getAllGlobalsArray (MBF mbf, OUT IinstInfo ** ppiinstinfo, OUT ULONG * pciinst)
{
return getAllGlobalsArray ((HTARGET)-1, mbf, ppiinstinfo, pciinst);
};
///////////////////////////////////////////////////
BOOL Ncb::getAllGlobalsArray (HTARGET hTarget, MBF mbf, OUT IinstInfo ** ppiinstinfo, OUT ULONG * pciinst)
{
Array<IinstInfo> rgiinst;
*ppiinstinfo = NULL;
*pciinst = 0;
if (mbf & mbfClass)
GetGlobalClass (hTarget, &rgiinst);
GetGlobalOther (hTarget, mbf, &rgiinst);
return DupArray (ppiinstinfo, pciinst, rgiinst);
}
////////////////////////////////////////////////////////
// Ncb::GetGlobalClass();
////////////////////////////////////////////////////////
BOOL Ncb::GetGlobalClass (HTARGET hTarget, Array<IinstInfo> * prgiinst)
{
USHORT i;
for (i = 0; i < m_rgModHdr.size(); i++)
{
if (hTarget != (HTARGET)-1 && !isModInTarget (hTarget, i))
continue;
if (!GetGlobalClass (i, prgiinst))
return FALSE;
}
return TRUE;
};
///////////////////////////////////////////////////////
BOOL Ncb::GetGlobalClass (IMOD imod, Array<IinstInfo> * prgiinst)
{
USHORT j;
USHORT index;
IinstInfo iinstinfo;
SZ_CONST szName;
if (m_rgStat[imod] == NCB_STATMOD_LOAD_WRITE)
{
if (!FindWriteIndex (imod, &index))
return FALSE;
// must search it linearly:
for (j = 0; j < m_rgRWBuf[index].m_rgProp.size(); j++)
{
if (!(m_rgRWBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
if (m_rgRWBuf[index].m_rgProp[j].m_en.m_typ == INST_TYP_CLASSNAM)
{
m_pnm->getName (m_rgRWBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinstinfo.m_iinst = (imod << 16) | j;
iinstinfo.m_ni = m_rgRWBuf[index].m_rgProp[j].m_en.m_ni;
iinstinfo.m_szName = szName;
prgiinst->append(iinstinfo);
}
}
}
}
else // must load as read
{
if (!LoadModForRead (m_pdb, imod, &index))
return FALSE;
// can search just the first block:
for (j = 0; j < m_rgModHdr[imod].m_cClassProp; j++)
{
if (!(m_rgContBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN))
continue;
m_pnm->getName (m_rgContBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinstinfo.m_iinst = (imod << 16) | j;
iinstinfo.m_ni = m_rgContBuf[index].m_rgProp[j].m_en.m_ni;
iinstinfo.m_szName = szName;
prgiinst->append(iinstinfo);
}
}
}
return TRUE;
};
//////////////////////////////////////////////////////////////////////
// GetGlobalOther()
//////////////////////////////////////////////////////////////////////
BOOL Ncb::GetGlobalOther(HTARGET hTarget, MBF mbf, Array<IinstInfo> * prgiinst)
{
USHORT i;
for (i = 0; i < m_rgModHdr.size(); i++)
{
if (hTarget != (HTARGET)-1 && !isModInTarget (hTarget, i))
continue;
if (!GetGlobalOther (i, mbf, prgiinst))
return FALSE;
}
return TRUE;
};
//////////////////////////////////////////////////////
BOOL Ncb::GetGlobalOther(IMOD imod, MBF mbf, Array<IinstInfo> * prgiinst)
{
USHORT j;
USHORT index;
IinstInfo iinstinfo;
SZ_CONST szName;
if (m_rgStat[imod] == NCB_STATMOD_LOAD_WRITE)
{
if (!FindWriteIndex (imod, &index))
return FALSE;
// must search it linearly:
for (j = 0; j < m_rgRWBuf[index].m_rgProp.size(); j++)
{
if ((!(m_rgRWBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN)) ||
(m_rgRWBuf[index].m_rgProp[j].m_en.m_atr & INST_ATR_STATIC))
continue;
if (TypFilter(m_rgRWBuf[index].m_rgProp[j].m_en.m_typ, mbf) &&
m_rgRWBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgRWBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMVAR &&
m_rgRWBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMFUNC)
{
m_pnm->getName (m_rgRWBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinstinfo.m_iinst = (imod << 16) | j;
iinstinfo.m_ni = m_rgRWBuf[index].m_rgProp[j].m_en.m_ni;
iinstinfo.m_szName = szName;
prgiinst->append(iinstinfo);
}
}
}
}
else // must load as read
{
if (!LoadModForRead (m_pdb, imod, &index))
return FALSE;
// can search just the first block:
for (j = m_rgModHdr[imod].m_cClassProp; j < m_rgModHdr[imod].m_cProp; j++)
{
if ((!(m_rgContBuf[index].m_rgProp[j].m_en.m_atr & INST_NCB_ATR_DEFN)) ||
(m_rgContBuf[index].m_rgProp[j].m_en.m_atr & INST_ATR_STATIC))
continue;
if (TypFilter (m_rgContBuf[index].m_rgProp[j].m_en.m_typ, mbf) &&
m_rgContBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgContBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMVAR &&
m_rgContBuf[index].m_rgProp[j].m_en.m_typ != INST_TYP_MEMFUNC)
{
m_pnm->getName (m_rgContBuf[index].m_rgProp[j].m_en.m_ni, &szName);
if (IsGlobalName (szName))
{
iinstinfo.m_iinst = (imod << 16) | j;
iinstinfo.m_ni = m_rgContBuf[index].m_rgProp[j].m_en.m_ni;
iinstinfo.m_szName = szName;
prgiinst->append(iinstinfo);
}
}
}
}
return TRUE;
};
//////////////////////////////////////////////////////
// fCaseSeinsitive()
///////////////////////////////////////////////////////
BOOL Ncb::fCaseSensitive()
{
return FALSE;
};
//////////////////////////////////////////////////////
// setCaseSeinsitivity()
//////////////////////////////////////////////////////
BOOL Ncb::setCaseSensitivity(BOOL)
{
return FALSE;
};
////////////////////////////////////////////////////////
// register notification function:
///////////////////////////////////////////////////////
BOOL Ncb::regNotify (pfnNotifyChange pNotify)
{
return regNotify ((HTARGET)-1, pNotify);
};
////////////////////////////////////////////////////////
BOOL Ncb::regNotify (HTARGET hTarget, pfnNotifyChange pNotify)
{
USHORT index;
BOOL bRet = TRUE;
NiQ niq;
DWORD dw = ::WaitForSingleObject (m_hMutex, INFINITE);
index = m_rgNotify.size();
if (!m_rgNotify.setSize(index+1))
bRet = FALSE;
else
{
m_rgNotify[index].m_pfnNotify = pNotify;
m_rgNotify[index].m_hTarget = hTarget;
if (m_bGraphBuilt)
{
niq.m_op = refreshAllOp;
niq.m_iinstOld = 0;
niq.m_iInfoNew.m_iinst = 0;
m_rgNotify[index].m_rgQ.append (niq);
}
}
::ReleaseMutex (m_hMutex);
return bRet;
};
// stub: should not call this directly
// must call regNotify from NcWrap
BOOL Ncb::regNotify ()
{
return FALSE;
}
// stub: should not call this directly
// must call getQ from NcWrap
BOOL Ncb::getQ (OUT NiQ ** ppQ, OUT ULONG * pcQ)
{
return FALSE;
}
BOOL Ncb::regNotify (HTARGET hTarget, ULONG * pindex)
{
USHORT index,i;
BOOL bRet = TRUE;
NiQ niq;
BOOL bFound = FALSE;
DWORD dw = ::WaitForSingleObject (m_hMutex, INFINITE);
index = m_rgNotifyQ.size();
for (i = 0; i < index; i++)
{
if (m_rgNotifyQ[i].m_bDel)
{
*pindex = (ULONG)i;
bFound = TRUE;
break;
}
}
if (!bFound)
{
if (!m_rgNotifyQ.setSize (index + 1))
bRet = FALSE;
else
*pindex = (ULONG) index;
}
if (bRet)
{
m_rgNotifyQ[*pindex].m_hTarget = hTarget;
m_rgNotifyQ[*pindex].m_bDel = FALSE;
if (m_bGraphBuilt)
{
niq.m_op = refreshAllOp;
niq.m_iinstOld = 0;
niq.m_iInfoNew.m_iinst = 0;
m_rgNotifyQ[*pindex].m_rgQ.append (niq);
}
}
::ReleaseMutex (m_hMutex);
return bRet;
}
BOOL Ncb::getQ (ULONG index, HTARGET hTarget, NiQ ** ppQ, ULONG * pcQ)
{
USHORT cArr = m_rgNotifyQ.size();
BOOL bRet = FALSE;
if ((ULONG)cArr < index)
return FALSE;
if (hTarget != m_rgNotifyQ[index].m_hTarget)
return FALSE;
bRet = DupArray (ppQ, pcQ, m_rgNotifyQ[index].m_rgQ);
if (bRet)
m_rgNotifyQ[index].m_rgQ.setSize(0);
return bRet;
}
/////////////////////////////////////////////////////
// unregister notification function
// REVIEW : needs to compare hTarget as well!
/////////////////////////////////////////////////////
BOOL Ncb::unregNotify (pfnNotifyChange pNotify)
{
USHORT index,i;
BOOL bRet = FALSE;
DWORD dw = ::WaitForSingleObject (m_hMutex, INFINITE);
index = m_rgNotify.size();
for (i = 0; i < index ;i++)
{
if (m_rgNotify[i].m_pfnNotify == pNotify)
{
m_rgNotify.deleteAt (i);
bRet = TRUE;
break;
}
}
::ReleaseMutex (m_hMutex);
return bRet;
};
///////////////////////////////////////////////////////////
BOOL Ncb::unregNotify (ULONG index, HTARGET hTarget)
{
USHORT cArr;
BOOL bRet = FALSE;
DWORD dw = ::WaitForSingleObject (m_hMutex, INFINITE);
cArr = m_rgNotifyQ.size();
if (cArr < index)
{
if (hTarget == m_rgNotifyQ[index].m_hTarget)
{
m_rgNotifyQ[index].m_bDel = TRUE;
m_rgNotifyQ[index].m_hTarget = NULL;
m_rgNotifyQ[index].m_rgQ.setSize(0);
bRet = TRUE;
}
}
::ReleaseMutex (m_hMutex);
return bRet;
};
//////////////////////////////////////////////////
// SuspendNotify()
///////////////////////////////////////////////////
BOOL Ncb::suspendNotify ()
{
m_bNotifyNow = FALSE;
return TRUE;
};
//////////////////////////////////////////////////
// RestoreNotify()
//////////////////////////////////////////////////
BOOL Ncb::resumeNotify()
{
m_bNotifyNow = TRUE;
// REVIEW:
// Notify();
return TRUE;
};
//////////////////////////////////////////////////
// IsInQ(Array<IINST> &rgiinst, IINST iinst, USHORT * pindex)
//////////////////////////////////////////////////
BOOL Ncb::IsInQ (Array<NiQ> &rgiinst, IINST iinst, USHORT * pindex)
{
USHORT i;
for (i = 0; i < rgiinst.size(); i++)
{
if (rgiinst[i].m_iInfoNew.m_iinst == iinst)
{
*pindex = i;
return TRUE;
}
}
return FALSE;
};
/////////////////////////////////////////////////////////
// Check if iinst has a member or not
/////////////////////////////////////////////////////////
BOOL Ncb::fHasMembers (IINST iinst, MBF mbf)
{
_ASSERT (FALSE);
return FALSE;
}
/////////////////////////////////////////////////////////
BOOL Ncb::fHasMembers (HTARGET hTarget, IINST iinst, MBF mbf)
{
if (iinst == IINST_GLOBALS)
return fHasGlobals(hTarget, mbf);
else
{
USHORT iModHdr = IModFrIinst (iinst);
USHORT iProp = IPropFrIinst (iinst);
USHORT index;
USHORT i, iStart;
TYP typ;
ATR atr;
_ASSERT (iModHdr < m_rgModHdr.size());
if (m_rgModHdr[iModHdr].m_cProp <= iProp)
return FALSE;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
if (m_rgContBuf[index].m_rgProp[iProp].m_en.m_typ != INST_TYP_CLASSNAM)
return FALSE;
iStart = (iProp == 0) ? 0 : (m_rgContBuf[index].m_rgProp[iProp-1].m_iUse);
for (i = iStart; i < m_rgContBuf[index].m_rgProp[iProp].m_iUse; i++)
{
if (m_rgContBuf[index].m_rgUse[i].m_kind == NCB_KIND_CONTAINMENT)
{
typ = m_rgContBuf[index].m_rgProp[m_rgContBuf[index].m_rgUse[i].m_iProp].m_en.m_typ;
atr = m_rgContBuf[index].m_rgProp[m_rgContBuf[index].m_rgUse[i].m_iProp].m_en.m_atr;
if (TypFilter(typ, mbf))
{
if ((typ == INST_TYP_CLASSNAM) && (atr & INST_NCB_ATR_DECL))
continue;
return TRUE;
}
}
}
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return FALSE;
_ASSERT (m_rgRWBuf[index].m_iModHdr == iModHdr);
if (m_rgRWBuf[index].m_rgProp.size() <= iProp)
return FALSE;
if (m_rgRWBuf[index].m_rgProp[iProp].m_en.m_typ != INST_TYP_CLASSNAM)
return FALSE;
for (i = 0; i < m_rgRWBuf[index].m_rgProp[iProp].m_rgUse.size(); i++)
{
if (m_rgRWBuf[index].m_rgProp[iProp].m_rgUse[i].m_kind == NCB_KIND_CONTAINMENT)
{
typ = m_rgRWBuf[index].m_rgProp[m_rgRWBuf[index].m_rgProp[iProp].m_rgUse[i].m_iProp].m_en.m_typ;
atr = m_rgRWBuf[index].m_rgProp[m_rgRWBuf[index].m_rgProp[iProp].m_rgUse[i].m_iProp].m_en.m_atr;
if (TypFilter(typ, mbf))
{
if ((typ == INST_TYP_CLASSNAM) && (atr & INST_NCB_ATR_DECL))
continue;
return TRUE;
}
}
}
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// BOOL Ncb::fHasGlobals(HTARGET, MBF)
//////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL Ncb::fHasGlobals (HTARGET hTarget, MBF mbf)
{
USHORT iModHdr;
USHORT index;
USHORT i;
for (iModHdr = 0; iModHdr < m_rgStat.size(); iModHdr++)
{
if (!isModInTarget (hTarget, iModHdr))
continue;
if (m_rgStat[iModHdr] != NCB_STATMOD_LOAD_WRITE)
{
if (!LoadModForRead (m_pdb, iModHdr, &index))
return FALSE;
if ((mbf & mbfClass) && (m_rgModHdr[iModHdr].m_cClassProp > 0))
return TRUE;
for (i = m_rgModHdr[iModHdr].m_cClassProp; i < m_rgModHdr[iModHdr].m_cProp; i++)
{
if ((!(m_rgContBuf[index].m_rgProp[i].m_en.m_atr & INST_NCB_ATR_DEFN)) ||
(m_rgContBuf[index].m_rgProp[i].m_en.m_atr & INST_ATR_STATIC))
continue;
if (TypFilter(m_rgContBuf[index].m_rgProp[i].m_en.m_typ, mbf) &&
m_rgContBuf[index].m_rgProp[i].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgContBuf[index].m_rgProp[i].m_en.m_typ != INST_TYP_MEMVAR &&
m_rgContBuf[index].m_rgProp[i].m_en.m_typ != INST_TYP_MEMFUNC)
return TRUE;
}
}
else
{
if (!FindWriteIndex (iModHdr, &index))
return FALSE;
// must search it linearly:
for (i = 0; i < m_rgRWBuf[index].m_rgProp.size(); i++)
{
if ((!(m_rgRWBuf[index].m_rgProp[i].m_en.m_atr & INST_NCB_ATR_DEFN)) ||
(m_rgRWBuf[index].m_rgProp[i].m_en.m_atr & INST_ATR_STATIC))
continue;
if (TypFilter(m_rgRWBuf[index].m_rgProp[i].m_en.m_typ, mbf) &&
m_rgRWBuf[index].m_rgProp[i].m_en.m_typ != INST_TYP_CLASSNAM &&
m_rgRWBuf[index].m_rgProp[i].m_en.m_typ != INST_TYP_MEMVAR &&
m_rgRWBuf[index].m_rgProp[i].m_en.m_typ != INST_TYP_MEMFUNC)
return TRUE;
}
}
}
return FALSE;
};
//////////////////////////////////////////////////////////////////////
// niFrIinst
//////////////////////////////////////////////////////////////////////
BOOL Ncb::niFrIinst (IINST iinst, NI *pni)
{
NCB_ENTITY en;
if (EnFrIinst (iinst, &en))
{
*pni = en.m_ni;
return TRUE;
}
return FALSE;
}