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.
 
 
 
 
 
 

1322 lines
26 KiB

//
// bsc1.cpp
//
// implementation of Bsc interface for single source of browser information
//
#include "pdbimpl.h"
#include "bsc1.h"
#include "helper.h"
#define _CRTBLD // Use copy from C runtime DLL
#include <..\undname\undname.h>
// create a BSC object using an existing PDB
PDBAPI(BOOL) Bsc::open(PDB* ppdb, OUT Bsc** ppbsc)
{
precondition(ppbsc);
precondition(ppdb);
Bsc1* pbsc1 = new Bsc1;
*ppbsc = pbsc1;
if (!pbsc1) return FALSE;
return pbsc1->init(ppdb);
}
PDBAPI(BOOL) Bsc::open(SZ szName, OUT Bsc** ppbsc)
{
precondition(ppbsc);
precondition(szName);
Bsc1* pbsc1 = new Bsc1;
*ppbsc = pbsc1;
if (!pbsc1) return FALSE;
pbsc1->fIOwnThePdb = TRUE;
EC ec;
char szError[cbErrMax];
PDB *pdb;
if (!PDB::Open(szName, "r", (SIG)0, &ec, szError, &pdb) ||
!pbsc1->init(pdb)) {
delete pbsc1;
*ppbsc = NULL;
return FALSE;
}
return TRUE;
}
Bsc1::Bsc1()
{
pdb = NULL;
pnm = NULL;
fIOwnThePdb = FALSE;
pstmModules = NULL;
pstmEntities = NULL;
cEntities = 0;
cModules = 0;
fCase = TRUE;
rgstm = NULL;
rghead = NULL;
rgimodSorted = NULL;
}
BOOL Bsc1::init(PDB *pdb_)
{
pdb = pdb_;
if (!NameMap::open(pdb_, FALSE, &pnm))
return FALSE;
if (!pdb->OpenStream(SZ_BSC_ENTITIES, &pstmEntities))
return FALSE;
cEntities = pstmEntities->QueryCb()/sizeof(ENTITY);
if (!cEntities)
return FALSE;
if (!pdb->OpenStream(SZ_BSC_MODULES, &pstmModules))
return FALSE;
cModules = pstmModules->QueryCb()/sizeof(NI);
if (!cModules)
return FALSE;
if (!rgEn.addSection(pstmEntities, 0, cEntities))
return FALSE;
rgModNi = new NI[cModules];
if (!rgModNi)
return FALSE;
if (!pstmModules->Read2(0, rgModNi,cModules*sizeof(NI)))
return FALSE;
if (!readModuleHeaders())
return FALSE;
return TRUE;
}
SZ Bsc1::szFrNi(NI ni)
{
return ::szFrNi (pnm, ni);
}
// helper functions for sorting things...
Bsc1 *pbscSorting;
int CmpImod(const void *p1, const void *p2)
{
IMOD i1 = *(IMOD*)p1;
IMOD i2 = *(IMOD*)p2;
BYTE h1 = pbscSorting->rgModIsHdr[i1];
BYTE h2 = pbscSorting->rgModIsHdr[i2];
if (h1 && !h2) return -1;
if (h2 && !h1) return 1;
NI ni1 = pbscSorting->rgModNi[i1];
NI ni2 = pbscSorting->rgModNi[i2];
if (ni1 < ni2)
return -1;
if (ni1 == ni2)
return 0;
return 1;
}
int CmpIinst(const void *p1, const void *p2)
{
IINST i1 = *(IINST*)p1;
IINST i2 = *(IINST*)p2;
if (i1 < i2)
return -1;
if (i1 == i2)
return 0;
return 1;
}
BOOL Bsc1::readModuleHeaders()
{
char buf[512];
rgstm = (Stream**)malloc(cModules * sizeof(Stream*));
rghead = new BSC_HEAD[cModules];
rgidx = new MODIDX[cModules];
rgimodSorted = new IMOD[cModules];
rgModIsHdr = new BYTE[cModules];
if (!rgstm || !rghead || !rgidx || !rgimodSorted || !rgModIsHdr)
return FALSE;
for (IMOD imod = 0; imod < cModules; imod++) {
SZ szMod = szFrNi(rgModNi[imod]);
strcpy(buf, SZ_BSC_SRC_PREFIX);
strcat(buf, szMod);
if (!pdb->OpenStream(buf, &rgstm[imod]))
return FALSE;
Stream *pstm = rgstm[imod];
BSC_HEAD &bh = rghead[imod];
MODIDX *pmi = &rgidx[imod];
if (!pstm->QueryCb()) {
// empty stream -- special case avoid read
memset(&bh, 0, sizeof(bh));
}
else {
CB cb = sizeof(BSC_HEAD);
if (!pstm->Read(0, &bh, &cb) || cb != sizeof(BSC_HEAD))
return FALSE; // REVIEW : cleanup
if (bh.vers_major != BSC_VERS_MAJOR || bh.vers_minor != BSC_VERS_MINOR)
return FALSE; // REVIEW : cleanup
}
if (imod == 0) {
pmi->idefMin = 0;
pmi->irefMin = 0;
pmi->iuseMin = 0;
pmi->ibaseMin = 0;
pmi->ipropMin = 0;
}
else {
MODIDX *pp = &rgidx[imod-1];
BSC_HEAD *bp = &rghead[imod-1];
pmi->idefMin = pp->idefMin + bp->cdef;
pmi->irefMin = pp->irefMin + bp->cref;
pmi->iuseMin = pp->iuseMin + bp->cuse;
pmi->ibaseMin = pp->ibaseMin + bp->cbase;
pmi->ipropMin = pp->ipropMin + bp->cprop;
}
OFF off = sizeof(BSC_HEAD);
if (!rgProp.addSection(pstm, off, bh.cprop))
return FALSE;
off += bh.cprop*sizeof(BSC_PROP);
if (!rgDef.addSection(pstm, off, bh.cdef))
return FALSE;
off += bh.cdef*sizeof(BSC_DEF);
if (!rgRef.addSection(pstm, off, bh.cref))
return FALSE;
off += bh.cref*sizeof(BSC_REF);
if (!rgUse.addSection(pstm, off, bh.cuse))
return FALSE;
off += bh.cuse*sizeof(BSC_USE);
if (!rgUby.addSection(pstm, off, bh.cuse))
return FALSE;
off += bh.cuse*sizeof(BSC_UBY);
if (!rgBase.addSection(pstm, off, bh.cbase))
return FALSE;
off += bh.cbase*sizeof(BSC_BASE);
if (!rgDerv.addSection(pstm, off, bh.cbase))
return FALSE;
}
for (imod = 0; imod < cModules; imod++) {
rgimodSorted[imod] = imod;
char *p = _tcsrchr(szFrNi(rgModNi[imod]), '.');
BOOL fHdr = TRUE;
// this is just a hueristic to help us indentify those files
// which are more likely to be headers, this in turn helps
// us to display references in a better order than we otherwise
// would. In particular we want the prototype of a function to
// to be the first reference as often as possible and this helps
// us to do that...
if (p && _tcslen(p) <= 4) {
switch (p[1]) {
case 'c': case 'C': case 'B': case 'b': case 'f': case 'F':
fHdr = FALSE;
}
}
rgModIsHdr[imod] = fHdr;
}
pbscSorting = this;
qsort(rgimodSorted, cModules, sizeof(IMOD), CmpImod);
delete [] rgModIsHdr;
rgModIsHdr = NULL;
return TRUE;
}
// close and dispose of pdb if necessary...
BOOL Bsc1::close()
{
if (fIOwnThePdb) {
fIOwnThePdb = FALSE;
pdb->Close();
pdb = NULL;
}
if (pstmModules) {
pstmModules->Release();
pstmModules = NULL;
}
if (pstmEntities) {
pstmEntities->Release();
pstmEntities = NULL;
}
if (rgstm) {
for (IMOD i = 0; i < cModules; i++) {
if (rgstm[i])
rgstm[i]->Release();
rgstm[i] = NULL;
}
free(rgstm);
}
if (rgModNi) {
delete [] rgModNi;
rgModNi = NULL;
}
if (rgidx) {
delete [] rgidx;
rgidx = NULL;
}
if (rgimodSorted) {
delete [] rgimodSorted;
rgimodSorted = NULL;
}
if (rghead) {
delete [] rghead;
rghead = NULL;
}
return TRUE;
}
// primitives for getting the information that underlies a handle
BOOL Bsc1::iinstInfo(IINST iinst, OUT SZ *psz, OUT TYP *ptyp, OUT ATR *patr)
{
ENTITY en = rgEn[iinst];
*psz = szFrNi(en.ni);
*ptyp = en.typ;
*patr = en.atr;
return TRUE;
}
SZ Bsc1::szFrIinst(IINST iinst)
{
return szFrNi(rgEn[iinst].ni);
}
BOOL Bsc1::idefInfo(IDEF idef, OUT SZ *pszModule, OUT LINE *piline)
{
BSC_DEF br = rgDef[idef];
IMOD imod = (IMOD)rgDef.isectOfIel(idef);
*pszModule = szFrNi(rgModNi[imod]);
*piline = br.line;
return TRUE;
}
BOOL Bsc1::irefInfo(IREF iref, OUT SZ *pszModule, OUT LINE *piline)
{
BSC_REF br = rgRef[iref];
IMOD imod = (IMOD)rgRef.isectOfIel(iref);
*pszModule = szFrNi(rgModNi[imod]);
*piline = br.line;
return TRUE;
}
BOOL Bsc1::imodInfo(IMOD imod, OUT SZ *pszModule)
{
*pszModule = szFrNi(rgModNi[imod]);
return TRUE;
}
char *ptyptab[] = {
"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
};
#define C_ATR 12
char *patrtab[] = {
"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
};
SZ Bsc1::szFrTyp(TYP typ)
{
return ptyptab[typ];
}
SZ Bsc1::szFrAtr(ATR atr)
{
static char buf[512];
buf[0] = 0;
for (int i=0; i < C_ATR; i++) {
if (atr & (1<<i)) {
if (buf[0])
strcat(buf, ":");
strcat(buf, patrtab[i]);
}
}
return buf;
}
// primitives for managing object instances (iinst)
BOOL Bsc1::getIinstByvalue(SZ szReqd, TYP typ, ATR atr, OUT IINST *piinst)
{
IINST iinst = iinstSupSz(szReqd);
if (iinst == iinstNil)
return iinstNil;
while (iinst < cEntities) {
ENTITY enT = rgEn[iinst];
if (cmpStr(szReqd, szFrNi(enT.ni)))
break;
if (typ == enT.typ && atr == enT.atr) {
*piinst = iinst;
return TRUE;
}
iinst++;
}
*piinst = iinstNil;
return FALSE;
}
Array<IINST> *parIinst;
Bsc1 *pbscCur;
static BOOL GatherOverloads(IINST iinst)
// gather up the possible overloads but first check to make sure
// the name is still in use...
{
if (pbscCur->fHasDefsOrRefs(iinst))
return parIinst->append(iinst);
return TRUE;
}
BOOL Bsc1::getOverloadArray(SZ sz, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
precondition(ppiinst);
precondition(pciinst);
IINST *rgiinst;
ULONG cIinst;
if (sz && sz[0] && sz[0] != '*') {
Array<IINST> arIinst;
parIinst = &arIinst;
pbscCur = this;
GenerateOverloads(sz, mbf, GatherOverloads,this);
cIinst = arIinst.size();
rgiinst = (IINST*)malloc(cIinst*sizeof(IINST));
if (!rgiinst) return FALSE;
for (UINT i=0; i < cIinst; i++)
rgiinst[i] = arIinst[i];
}
else {
rgiinst = (IINST*)malloc(cEntities*sizeof(IINST));
if (!rgiinst) return FALSE;
cIinst = 0;
for (UINT i = 0; i < cEntities; i++) {
if (fInstFilter(i, mbf) && fHasDefsOrRefs(i))
rgiinst[cIinst++] = i;
}
}
*ppiinst = rgiinst;
*pciinst = cIinst;
return TRUE;
}
IPROP Bsc1::ipropFrEn(ENTITY en, IMOD imod)
{
IPROP Lo = rgidx[imod].ipropMin;
IPROP Hi = Lo + rghead[imod].cprop;
IPROP ipropMac = Hi;
SZ szReqd = szFrNi(en.ni);
while (Lo < Hi) {
ULONG Mid = Lo + (Hi - Lo) / 2; // this way there can be no overflow
SZ szCur = szFrNi(rgProp[Mid].en.ni);
int Cmp = cmpStr(szCur, szReqd);
if (Cmp >= 0)
Hi = Mid;
else
Lo = Mid + 1;
}
if (Hi == ipropMac)
return ipropNil;
IPROP iprop = Hi;
while (iprop < ipropMac) {
ENTITY enT = rgProp[iprop].en;
// if we found something that doesn't match case-insenstively, we give up
if (_stricmp(szReqd, szFrNi(enT.ni)))
break;
// wait for the case sensitive match, we need an exact match because
// we're starting from an entity... the name has already been resolved
// to a specific object as far as the user is concerned
if (strcmp(szReqd, szFrNi(enT.ni))) {
iprop++;
continue;
}
if (en.typ == enT.typ && en.atr == enT.atr)
return iprop;
iprop++;
}
return ipropNil;
}
struct EnumProps
{
IMOD imod;
IMOD imodT;
BYTE mask;
int ib;
IPROP iprop;
ENTITY en;
Bsc1* pbsc;
ULONG iMac;
ULONG iCur;
ULONG MODIDX::*mBase;
BRIND BSC_PROP::*mIdx;
IPROP ipropBase;
ULONG cprobes;
EnumProps(Bsc1 *pbsc_, IINST iinst, ULONG MODIDX::*mBase_, BRIND BSC_PROP::*mIdx_)
{
pbsc = pbsc_;
mIdx = mIdx_;
mBase = mBase_;
en = pbsc->rgEn[iinst];
imodT = (IMOD)-1;
iMac = 0; iCur = 0; cprobes = 0;
}
BOOL next()
{
if (++iCur < iMac) {
return TRUE;
}
for ( ; ++imodT < pbsc->cModules ; ) {
imod = pbsc->rgimodSorted[imodT];
NI niMax = pbsc->rghead[imod].niMax;
if (en.ni > niMax) continue;
MaskFrNi(en.ni, niMax, CB_BITS_NI, &ib, &mask);
if (!(pbsc->rghead[imod].bitsNi[ib]&mask)) continue;
if ((iprop = pbsc->ipropFrEn(en, imod)) == ipropNil) continue;
ipropBase = pbsc->rgidx[imod].ipropMin;
pbsc->getIdxRange(imod, iprop, mBase, mIdx, iCur, iMac);
if (iCur >= iMac) continue;
return TRUE;
}
return FALSE;
}
};
BOOL Bsc1::getUsedByArray(IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
Array<IINST> rgIinst;
EnumProps enm(this, iinst, &MODIDX::iuseMin, &BSC_PROP::iuby);
while (enm.next()) {
IPROP iprop = rgUby[enm.iCur].iprop + enm.ipropBase;
IINST ii = iinstFrEn(rgProp[iprop].en);
if (!fInstFilter(ii, mbf))
continue;
if (!ppiinst) { *pciinst = 1; return TRUE; }
rgIinst.append(ii);
}
return DupArray(ppiinst, pciinst, rgIinst);
}
BOOL Bsc1::getUsesArray(IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
Array<IINST> rgIinst;
EnumProps enm(this, iinst, &MODIDX::iuseMin, &BSC_PROP::iuse);
while (enm.next()) {
IPROP iprop = rgUse[enm.iCur].iprop + enm.ipropBase;
IINST ii = iinstFrEn(rgProp[iprop].en);
if (!fInstFilter(ii, mbf))
continue;
if (!ppiinst) { *pciinst = 1; return TRUE; }
rgIinst.append(ii);
}
return DupArray(ppiinst, pciinst, rgIinst);
}
BOOL Bsc1::getBaseArray(IINST iinst, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
Array<IINST> rgIinst;
EnumProps enm(this, iinst, &MODIDX::ibaseMin, &BSC_PROP::ibase);
while (enm.next()) {
IPROP iprop = rgBase[enm.iCur].iprop + enm.ipropBase;
IINST ii = iinstFrEn(rgProp[iprop].en);
if (!ppiinst) { *pciinst = 1; return TRUE; }
rgIinst.append(ii);
}
return DupArray(ppiinst, pciinst, rgIinst);
}
BOOL Bsc1::getDervArray(IINST iinst, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
Array<IINST> rgIinst;
EnumProps enm(this, iinst, &MODIDX::ibaseMin, &BSC_PROP::iderv);
while (enm.next()) {
IPROP iprop = rgDerv[enm.iCur].iprop + enm.ipropBase;
IINST ii = iinstFrEn(rgProp[iprop].en);
if (!ppiinst) { *pciinst = 1; return TRUE; }
rgIinst.append(ii);
}
return DupArray(ppiinst, pciinst, rgIinst);
}
BOOL Bsc1::getMembersArray(IINST iinst, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
Array<IINST> rgIinst;
EnumProps enm(this, iinst, &MODIDX::iuseMin, &BSC_PROP::iuse);
while (enm.next()) {
IPROP iprop = rgUse[enm.iCur].iprop + enm.ipropBase;
IINST ii = iinstFrEn(rgProp[iprop].en);
TYP typ = rgEn[ii].typ;
if (typ != INST_TYP_MEMFUNC && typ != INST_TYP_MEMVAR)
continue;
if (!fInstFilter(ii, mbf))
continue;
if (!ppiinst) { *pciinst = 1; return TRUE; }
rgIinst.append(ii);
}
if (!DupArray(ppiinst, pciinst, rgIinst)) return FALSE;
qsort(*ppiinst, *pciinst, sizeof(IINST), CmpIinst);
return TRUE;
}
// get the array of definitions associated with this instance...
BOOL Bsc1::getDefArray(IINST iinst, OUT IDEF **ppidef, OUT ULONG *pcidef)
{
Array<IDEF> rgIdef;
EnumProps enm(this, iinst, &MODIDX::idefMin, &BSC_PROP::idef);
while (enm.next()) {
if (!ppidef) { *pcidef = 1; return TRUE; }
rgIdef.append(enm.iCur);
}
return DupArray(ppidef, pcidef, rgIdef);
}
BOOL Bsc1::getRefArray(IINST iinst, OUT IREF **ppiref, OUT ULONG *pciref)
{
Array<IREF> rgIref;
EnumProps enm(this, iinst, &MODIDX::irefMin, &BSC_PROP::iref);
while (enm.next()) {
if (!ppiref) { *pciref = 1; return TRUE; }
rgIref.append(enm.iCur);
}
return DupArray(ppiref, pciref, rgIref);
}
// primitives for managing source module contents
BOOL Bsc1::getModuleContents(IMOD imod, MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
IPROP iprop = rgidx[imod].ipropMin;
IPROP ipropMac = iprop + rghead[imod].cprop;
Array<IINST> rgIinst;
IDEF idefLast = 0;
BSC_PROP bp;
for (;iprop < ipropMac; iprop++, idefLast = bp.idef) {
bp = rgProp[iprop];
if (bp.idef == idefLast) // check for def'n in this module
continue;
IINST ii = iinstFrEn(bp.en);
if (!fInstFilter(ii, mbf))
continue;
if (!ppiinst) { *pciinst = 1; return TRUE; }
rgIinst.append(ii);
}
return DupArray(ppiinst, pciinst, rgIinst);
}
BOOL Bsc1::getModuleByName(SZ szReqd, OUT IMOD *pimod)
{
IMOD Lo = 0;
IMOD Hi = (IMOD)cModules;
while (Lo < Hi) {
IMOD Mid = Lo + (Hi - Lo) / 2; // this way there can be no overflow
SZ szCur = szFrNi(rgModNi[Mid]);
int Cmp = _tcsicmp(szCur, szReqd);
if (Cmp == 0) {
*pimod = Mid;
return TRUE;
}
if (Cmp > 0)
Hi = Mid;
else
Lo = Mid + 1;
}
*pimod = imodNil;
return FALSE;
}
BOOL Bsc1::getAllModulesArray(OUT IMOD **ppimod, OUT ULONG *pcimod)
{
*pcimod = cModules;
if (!cModules) {
*ppimod = NULL;
return TRUE;
}
*ppimod = (IMOD*)malloc(cModules*sizeof(IMOD));
if (!*ppimod)
return FALSE;
for (IMOD imod = 0; imod < cModules; imod++)
(*ppimod)[imod] = imod;
return TRUE;
}
// call this when a computed array is no longer required
void Bsc1::disposeArray(void *pAnyArray)
{
free(pAnyArray);
}
int Bsc1::cmpStr(SZ sz1, SZ sz2)
//
// think of sz1 and sz2 being in a list of things that are sorted
// case insensitively and then case sensitively within that. This is
// the case for browser symbols
//
// return -1, 0, or 1 if sz1 before, at, or after sz2 in the list
//
{
if (sz1[0] == '?') sz1++;
if (sz2[0] == '?') sz2++;
// do case insensitive compare, these strings are known to contain no DB chars
int ret = _stricmp(sz1, sz2);
// if this is good enough then use it, or if we are only doing
// a case insensitive search then this is good enough
if (ret || !fCase) return ret;
// if we must, do the case sensitive compare
return strcmp(sz1, sz2);
}
int Bsc1::cmpStrPrefix(SZ szPrefix, SZ szMain)
// checks to see if szMain begins with szPrefix
// returns lexical prefix only comparison like cmpStr()
//
{
int lenp = strlen(szPrefix);
int lenf = strlen(szMain);
char buffer[256];
assert(lenf < sizeof(buffer));
strcpy(buffer, szMain);
if (szPrefix[0] != '?' && szMain[0] == '?')
lenp++;
if (lenf > lenp)
buffer[lenp] = '\0';
return cmpStr(szPrefix, buffer);
}
IINST Bsc1::iinstSupSz(SZ szReqd)
// find the smallest ISYM whose value is greater or equal to the given SZ
//
{
IINST Lo = 0;
IINST Hi = cEntities;
while (Lo < Hi) {
IINST Mid = Lo + (Hi - Lo) / 2; // this way there can be no overflow
SZ szCur = szFrIinst(Mid);
int Cmp = cmpStr(szCur, szReqd);
if (Cmp >= 0)
Hi = Mid;
else
Lo = Mid + 1;
}
if (Hi == cEntities)
Hi = iinstNil;
return Hi;
}
BOOL Bsc1::findPrefixRange(SZ szprefix, IINST *piinstFirst, IINST *piinstLast)
// return, if successful, the range of bob's which are prefixed by the
// zero terminated string in szprefix, the boolean indicates success
{
BOOL fCaseSaved = fCase;
fCase = FALSE;
// init. the range to search
IINST low = 0;
IINST high = cEntities;
if (*szprefix == '\0') {
*piinstFirst = low;
*piinstLast = high - 1;
fCase = fCaseSaved;
return TRUE;
}
IINST middle;
while (low < high) {
// get the name of the middle symbol in the range
middle = low + (high - low) / 2;
int cmp = cmpStrPrefix(szprefix, szFrIinst(middle));
if (cmp == 0)
break;
if (cmp < 0)
high = middle;
else
low = middle + 1;
}
// did we find it?
if (low >= high) {
fCase = fCaseSaved;
return FALSE;
}
// get the range of the instances for this prefix
IINST curr = middle;
assert(!cmpStrPrefix(szprefix, szFrIinst(curr)));
while (curr > 0 && !cmpStrPrefix(szprefix, szFrIinst(curr-1)))
curr--;
*piinstFirst = curr;
curr = middle;
while (curr < cEntities-1 && !cmpStrPrefix(szprefix, szFrIinst(curr+1)))
curr++;
*piinstLast = curr;
fCase = fCaseSaved;
return TRUE;
}
BOOL
Bsc1::fInstFilter(IINST iinst, MBF mbf)
// return true if the given inst has the required properties
//
{
if (mbf == mbfAll)
return TRUE;
TYP typ = rgEn[iinst].typ;
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:
return !!(mbf & mbfClass);
case INST_TYP_STRUCNAM:
if ((mbf & (mbfTypes|mbfClass)) == (mbfTypes|mbfClass))
return TRUE;
// test for structs that are being used like classes...
ULONG c = 0;
if ((getBaseArray(iinst, NULL, &c) && c) ||
(getDervArray(iinst, NULL, &c) && c))
return !!(mbf & mbfClass);
return !!(mbf & mbfTypes);
}
return FALSE;
}
SZ Bsc1::formatDname(SZ szDecor)
{
#define BUFLEN 250
static char decorBuf[BUFLEN];
if (szDecor[0] != '?')
return szDecor;
__unDName(decorBuf, szDecor, BUFLEN-32, malloc, free,
UNDNAME_NO_FUNCTION_RETURNS|
UNDNAME_NO_ALLOCATION_MODEL|
UNDNAME_NO_ALLOCATION_LANGUAGE|
UNDNAME_NO_MS_KEYWORDS|
UNDNAME_NO_MS_THISTYPE|
UNDNAME_NO_CV_THISTYPE|
UNDNAME_NO_ACCESS_SPECIFIERS|
UNDNAME_NO_THROW_SIGNATURES|
UNDNAME_NO_MEMBER_TYPE|
UNDNAME_NO_RETURN_UDT_MODEL);
szDecor = decorBuf;
if (szDecor[0] == ' ')
szDecor++;
if (szDecor[0] == '?' && szDecor[1] == '?' && szDecor[2] == ' ')
szDecor += 3;
return szDecor;
}
IINST Bsc1::iinstFrEn(ENTITY en)
{
IINST iinst;
getIinstByvalue(szFrNi(en.ni), en.typ, en.atr, &iinst);
return iinst;
}
IINST Bsc1::iinstFrIref(IREF iref)
{
IMOD imod = (IMOD)rgRef.isectOfIel(iref);
return iinstContainingIdx(iref - rgidx[imod].irefMin, &BSC_PROP::iref, imod);
}
IINST Bsc1::iinstFrIdef(IDEF idef)
{
IMOD imod = (IMOD)rgDef.isectOfIel(idef);
return iinstContainingIdx(idef - rgidx[imod].idefMin, &BSC_PROP::idef, imod);
}
IINST Bsc1::iinstContextIref(IREF iref)
{
IMOD imod = (IMOD)rgRef.isectOfIel(iref);
IPROP ipropBase = rgidx[imod].ipropMin;
IPROP iprop = ipropContainingIdx(iref - rgidx[imod].irefMin, &BSC_PROP::iref, imod);
IPROP ipropBest = ipropNil;
LINE lineBest = 0;
LINE lineReqd = rgRef[iref].line;
IUBY iuby, iubyMac;
getIdxRange(imod, iprop, &MODIDX::iuseMin, &BSC_PROP::iuby, iuby, iubyMac);
for (;iuby < iubyMac; iuby++) {
IPROP ipUser = rgUby[iuby].iprop + ipropBase;
IDEF idef, idefMac;
getIdxRange(imod, ipUser, &MODIDX::idefMin, &BSC_PROP::idef, idef, idefMac);
for ( ;idef < idefMac; idef++) {
LINE line = rgDef[idef].line;
if (line > lineBest && line <= lineReqd) {
ipropBest = ipUser;
lineBest = line;
}
}
}
if (ipropBest == ipropNil)
return iinstNil;
return iinstFrEn(rgProp[ipropBest].en);
}
IPROP Bsc1::ipropContainingIdx(ULONG idxReqd, BRIND BSC_PROP::*mIdx, IMOD imod)
{
IPROP Lo = rgidx[imod].ipropMin;
IPROP Hi = Lo + rghead[imod].cprop;
IPROP ipropMac = Hi;
while (Lo < Hi) {
ULONG Mid = Lo + (Hi - Lo) / 2; // this way there can be no overflow
ULONG idx = rgProp[Mid].*mIdx;
if (idxReqd < idx)
Hi = Mid;
else
Lo = Mid + 1;
}
if (Hi == ipropMac)
return ipropNil;
return Hi;
}
IINST Bsc1::iinstContainingIdx(ULONG idxReqd, BRIND BSC_PROP::*mIdx, IMOD imod)
{
IPROP iprop = ipropContainingIdx(idxReqd, mIdx, imod);
if (iprop == ipropNil)
return iinstNil;
return iinstFrEn(rgProp[iprop].en);
}
void Bsc1::getIdxRange(IMOD imod, IPROP iprop, ULONG MODIDX::*mBase, BRIND BSC_PROP::*mIdx, ULONG &iMin, ULONG &iMac)
{
ULONG iBase = rgidx[imod].*mBase;
if (iprop == rgidx[imod].ipropMin)
iMin = iBase;
else
iMin = iBase + rgProp[iprop-1].*mIdx;
iMac = iBase + rgProp[iprop].*mIdx;
}
BOOL Bsc1::getStatistics(struct BSC_STAT *pstat)
{
pstat->cMod = cModules;
pstat->cInst = cEntities;
pstat->cDef = rgDef.iMac();
pstat->cRef = rgRef.iMac();
pstat->cUseLink = rgUse.iMac();
pstat->cBaseLink = rgBase.iMac();
return TRUE;
}
BOOL Bsc1::getModuleStatistics(IMOD imod, struct BSC_STAT *pstat)
{
BSC_HEAD *ph = &rghead[imod];
pstat->cMod = 1;
pstat->cInst = ph->cprop;
pstat->cDef = ph->cdef;
pstat->cRef = ph->cref;
pstat->cUseLink = ph->cuse;
pstat->cBaseLink = ph->cbase;
return TRUE;
}
BOOL Bsc1::fCaseSensitive()
{
return fCase;
}
BOOL Bsc1::setCaseSensitivity(BOOL fCaseIn)
{
fCase = fCaseIn;
return TRUE;
}
BOOL Bsc1::getAllGlobalsArray(MBF mbf, OUT IINST **ppiinst, OUT ULONG *pciinst)
{
precondition(ppiinst);
precondition(pciinst);
IINST *rgiinst;
ULONG cIinst;
rgiinst = (IINST*)malloc(cEntities*sizeof(IINST));
if (!rgiinst) return FALSE;
cIinst = 0;
for (UINT i = 0; i < cEntities; i++) {
// make sure it is the right sort of object
if (!fInstFilter(i, mbf))
continue;
// then strip out objects with scope
SZ sz; TYP typ; ATR atr;
iinstInfo(i, &sz, &typ, &atr);
switch (typ) {
case INST_TYP_MEMVAR:
case INST_TYP_MEMFUNC:
case INST_TYP_PARAMETER:
case INST_TYP_ENUMMEM:
continue;
}
// these objects are not at global scope
if (atr & (INST_ATR_LOCAL|INST_ATR_STATIC|INST_ATR_MODULE))
continue;
rgiinst[cIinst++] = i;
}
*ppiinst = rgiinst;
*pciinst = cIinst;
return TRUE;
}
BOOL Bsc1::getAllGlobalsArray(MBF mbf, OUT IinstInfo **ppiinstinfo, OUT ULONG *pciinst)
{
// NYI
precondition (FALSE);
return FALSE;
}
SZ Bsc1::getParams (IINST iinst)
{
static char buf[2];
return buf;
}
USHORT Bsc1::getNumParam (IINST iinst)
{
return 0;
}
SZ Bsc1::getParam (IINST iinst, USHORT index)
{
static char buf[2];
return buf;
}
SZ Bsc1::getType (IINST iinst)
// get return type/variable type
{
static char buf[2];
return buf;
}
BOOL Bsc1::regNotify (pfnNotifyChange pNotify)
{
return FALSE;
}
BOOL Bsc1::regNotify ()
{
return FALSE;
}
BOOL Bsc1::getQ (NiQ ** ppQ, ULONG * pcQ)
{
return FALSE;
}
BOOL Bsc1::checkParams (IINST iinst, SZ * pszParam, ULONG cParam)
{
return FALSE;
}
BOOL Bsc1::fHasMembers (IINST iinst, MBF mbf)
{
return FALSE;
}
BOOL Bsc1::fHasDefsOrRefs(IINST iinst)
{
IMOD imod;
BYTE mask;
int ib;
IPROP iprop;
ENTITY en;
ULONG iMac;
ULONG iCur;
en = rgEn[iinst];
for (imod = 0; imod < cModules ; imod++) {
NI niMax = rghead[imod].niMax;
if (en.ni > niMax) continue;
MaskFrNi(en.ni, niMax, CB_BITS_NI, &ib, &mask);
if (!(rghead[imod].bitsNi[ib]&mask)) continue;
if ((iprop = ipropFrEn(en, imod)) == ipropNil) continue;
// check for a definition
getIdxRange(imod, iprop, &MODIDX::idefMin, &BSC_PROP::idef, iCur, iMac);
if (iCur != iMac) return TRUE;
// check for a reference
getIdxRange(imod, iprop, &MODIDX::irefMin, &BSC_PROP::iref, iCur, iMac);
if (iCur != iMac) return TRUE;
}
return FALSE;
}
BOOL Bsc1::niFrIinst (IINST iinst, NI *ni)
{
return FALSE;
}
BOOL Bsc1::lock ()
{
return FALSE;
}
BOOL Bsc1::unlock ()
{
return FALSE;
}