576 lines
9.3 KiB
C
576 lines
9.3 KiB
C
|
//
|
||
|
// query.c
|
||
|
//
|
||
|
// perform database queries
|
||
|
//
|
||
|
#include <stddef.h>
|
||
|
#include <string.h>
|
||
|
#if defined(OS2)
|
||
|
#define INCL_NOCOMMON
|
||
|
#define INCL_DOSPROCESS
|
||
|
#define INCL_DOSSEMAPHORES
|
||
|
#define INCL_DOSFILEMGR
|
||
|
#define INCL_DOSERRORS
|
||
|
#define INCL_DOSMISC
|
||
|
#include <os2.h>
|
||
|
#else
|
||
|
#include <windows.h>
|
||
|
#endif
|
||
|
|
||
|
#include <dos.h>
|
||
|
|
||
|
#include "hungary.h"
|
||
|
#include "bsc.h"
|
||
|
#include "bscsup.h"
|
||
|
|
||
|
// these keep track of the current query, they are globally visible so
|
||
|
// that users can see how the query is progressing
|
||
|
//
|
||
|
// you may not write on these
|
||
|
|
||
|
IDX far idxQyStart;
|
||
|
IDX far idxQyCur;
|
||
|
IDX far idxQyMac;
|
||
|
|
||
|
// this is auxilliary information about the current bob which some
|
||
|
// queries may choose to make available
|
||
|
//
|
||
|
|
||
|
static BOOL fWorking;
|
||
|
static LSZ lszModLast = NULL; // for removing duplicate modules
|
||
|
|
||
|
// prototypes for the query worker functions
|
||
|
//
|
||
|
|
||
|
static BOB BobQyFiles(VOID);
|
||
|
static BOB BobQySymbols (VOID);
|
||
|
static BOB BobQyContains (VOID);
|
||
|
static BOB BobQyCalls (VOID);
|
||
|
static BOB BobQyCalledBy (VOID);
|
||
|
static BOB BobQyUses (VOID);
|
||
|
static BOB BobQyUsedBy (VOID);
|
||
|
static BOB BobQyUsedIn (VOID);
|
||
|
static BOB BobQyDefinedIn(VOID);
|
||
|
static BOB BobQyRefs(VOID);
|
||
|
static BOB BobQyDefs(VOID);
|
||
|
|
||
|
// current bob worker function
|
||
|
static BOB (*bobFn)(VOID) = NULL;
|
||
|
|
||
|
BOOL BSC_API
|
||
|
InitBSCQuery (QY qy, BOB bob)
|
||
|
// do the request query on the given bob
|
||
|
//
|
||
|
{
|
||
|
fWorking = FALSE;
|
||
|
|
||
|
if (lszModLast == NULL)
|
||
|
lszModLast = LpvAllocCb(1024); // REVIEW -- how much to alloc? [rm]
|
||
|
|
||
|
// no memory -- no query
|
||
|
if (lszModLast == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
strcpy(lszModLast, "");
|
||
|
|
||
|
switch (qy) {
|
||
|
|
||
|
case qyFiles:
|
||
|
bobFn = BobQyFiles;
|
||
|
idxQyStart = (IDX)0;
|
||
|
idxQyMac = (IDX)ImodMac();
|
||
|
break;
|
||
|
|
||
|
case qySymbols:
|
||
|
bobFn = BobQySymbols;
|
||
|
idxQyStart = (IDX)0;
|
||
|
idxQyMac = (IDX)IinstMac();
|
||
|
break;
|
||
|
|
||
|
case qyContains:
|
||
|
{
|
||
|
IMS ims, imsMac;
|
||
|
|
||
|
bobFn = BobQyContains;
|
||
|
|
||
|
if (ClsOfBob(bob) != clsMod) return FALSE;
|
||
|
MsRangeOfMod(ImodFrBob(bob), &ims, &imsMac);
|
||
|
|
||
|
idxQyStart = (IDX)ims;
|
||
|
idxQyMac = (IDX)imsMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyCalls:
|
||
|
{
|
||
|
IUSE iuse, iuseMac;
|
||
|
|
||
|
bobFn = BobQyCalls;
|
||
|
if (ClsOfBob(bob) != clsInst) return FALSE;
|
||
|
UseRangeOfInst(IinstFrBob(bob), &iuse, &iuseMac);
|
||
|
|
||
|
idxQyStart = (IDX)iuse;
|
||
|
idxQyMac = (IDX)iuseMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyUses:
|
||
|
{
|
||
|
IUSE iuse, iuseMac;
|
||
|
|
||
|
bobFn = BobQyUses;
|
||
|
if (ClsOfBob(bob) != clsInst) return FALSE;
|
||
|
UseRangeOfInst(IinstFrBob(bob), &iuse, &iuseMac);
|
||
|
|
||
|
idxQyStart = (IDX)iuse;
|
||
|
idxQyMac = (IDX)iuseMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyCalledBy:
|
||
|
{
|
||
|
IUBY iuby, iubyMac;
|
||
|
|
||
|
bobFn = BobQyCalledBy;
|
||
|
if (ClsOfBob(bob) != clsInst) return FALSE;
|
||
|
UbyRangeOfInst(IinstFrBob(bob), &iuby, &iubyMac);
|
||
|
|
||
|
idxQyStart = (IDX)iuby;
|
||
|
idxQyMac = (IDX)iubyMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyUsedBy:
|
||
|
{
|
||
|
IUBY iuby, iubyMac;
|
||
|
|
||
|
bobFn = BobQyUsedBy;
|
||
|
if (ClsOfBob(bob) != clsInst) return FALSE;
|
||
|
UbyRangeOfInst(IinstFrBob(bob), &iuby, &iubyMac);
|
||
|
|
||
|
idxQyStart = (IDX)iuby;
|
||
|
idxQyMac = (IDX)iubyMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyUsedIn:
|
||
|
{
|
||
|
IREF iref, irefMac;
|
||
|
|
||
|
bobFn = BobQyUsedIn;
|
||
|
if (ClsOfBob(bob) != clsInst) return FALSE;
|
||
|
RefRangeOfInst(IinstFrBob(bob), &iref, &irefMac);
|
||
|
|
||
|
idxQyStart = (IDX)iref;
|
||
|
idxQyMac = (IDX)irefMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyDefinedIn:
|
||
|
{
|
||
|
IDEF idef, idefMac;
|
||
|
|
||
|
bobFn = BobQyDefinedIn;
|
||
|
if (ClsOfBob(bob) != clsInst) return FALSE;
|
||
|
DefRangeOfInst(IinstFrBob(bob), &idef, &idefMac);
|
||
|
|
||
|
idxQyStart = (IDX)idef;
|
||
|
idxQyMac = (IDX)idefMac;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyRefs:
|
||
|
{
|
||
|
IINST iinst, iinstMac;
|
||
|
|
||
|
bobFn = BobQyRefs;
|
||
|
|
||
|
switch (ClsOfBob(bob)) {
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
|
||
|
case clsSym:
|
||
|
InstRangeOfSym(IsymFrBob(bob), &iinst, &iinstMac);
|
||
|
|
||
|
idxQyStart = (IDX)iinst;
|
||
|
idxQyMac = (IDX)iinstMac;
|
||
|
break;
|
||
|
|
||
|
case clsInst:
|
||
|
idxQyStart = (IDX)IinstFrBob(bob);
|
||
|
idxQyMac = idxQyStart+1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case qyDefs:
|
||
|
{
|
||
|
IINST iinst, iinstMac;
|
||
|
|
||
|
bobFn = BobQyDefs;
|
||
|
|
||
|
switch (ClsOfBob(bob)) {
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
|
||
|
case clsSym:
|
||
|
InstRangeOfSym(IsymFrBob(bob), &iinst, &iinstMac);
|
||
|
|
||
|
idxQyStart = (IDX)iinst;
|
||
|
idxQyMac = (IDX)iinstMac;
|
||
|
break;
|
||
|
|
||
|
case clsInst:
|
||
|
idxQyStart = (IDX)IinstFrBob(bob);
|
||
|
idxQyMac = idxQyStart+1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
idxQyCur = idxQyStart;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOB BSC_API
|
||
|
BobNext()
|
||
|
// return the next Bob in the query
|
||
|
{
|
||
|
if (idxQyCur < idxQyMac && bobFn != NULL)
|
||
|
return (*bobFn)();
|
||
|
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyFiles()
|
||
|
// return the next File in a file query
|
||
|
//
|
||
|
{
|
||
|
BOB bob;
|
||
|
|
||
|
while (idxQyCur < idxQyMac) {
|
||
|
IMS ims1, ims2;
|
||
|
|
||
|
MsRangeOfMod((IMOD)idxQyCur, &ims1, &ims2);
|
||
|
if (ims1 != ims2) {
|
||
|
bob = BobFrClsIdx(clsMod, idxQyCur);
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
else
|
||
|
idxQyCur++;
|
||
|
}
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQySymbols ()
|
||
|
// get the next symbol in a symbol query
|
||
|
//
|
||
|
{
|
||
|
BOB bob;
|
||
|
|
||
|
bob = BobFrClsIdx(clsInst, idxQyCur);
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyContains ()
|
||
|
// get the next symbol in a contains query
|
||
|
//
|
||
|
{
|
||
|
BOB bob;
|
||
|
|
||
|
bob = BobFrClsIdx(clsInst, IinstOfIms((IMS)idxQyCur));
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyCalls ()
|
||
|
// get the next symbol which query focus calls
|
||
|
//
|
||
|
{
|
||
|
WORD cuse;
|
||
|
IINST iinst;
|
||
|
ISYM isym;
|
||
|
TYP typ;
|
||
|
ATR atr;
|
||
|
BOB bob;
|
||
|
|
||
|
for (; idxQyCur < idxQyMac; idxQyCur++) {
|
||
|
|
||
|
UseInfo((IUSE)idxQyCur, &iinst, &cuse);
|
||
|
InstInfo(iinst, &isym, &typ, &atr);
|
||
|
|
||
|
if (typ > INST_TYP_LABEL)
|
||
|
continue;
|
||
|
|
||
|
bob = BobFrClsIdx(clsInst, iinst);
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyCalledBy ()
|
||
|
// get the next symbol which query focus is called by
|
||
|
//
|
||
|
{
|
||
|
WORD cuse;
|
||
|
IINST iinst;
|
||
|
ISYM isym;
|
||
|
TYP typ;
|
||
|
ATR atr;
|
||
|
BOB bob;
|
||
|
|
||
|
for (; idxQyCur < idxQyMac; idxQyCur++) {
|
||
|
|
||
|
UbyInfo((IUBY)idxQyCur, &iinst, &cuse);
|
||
|
InstInfo(iinst, &isym, &typ, &atr);
|
||
|
|
||
|
if (typ > INST_TYP_LABEL)
|
||
|
continue;
|
||
|
|
||
|
bob = BobFrClsIdx(clsInst, iinst);
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyUses ()
|
||
|
// get the next symbol which query focus calls
|
||
|
//
|
||
|
{
|
||
|
WORD cuse;
|
||
|
IINST iinst;
|
||
|
BOB bob;
|
||
|
|
||
|
UseInfo((IUSE)idxQyCur, &iinst, &cuse);
|
||
|
bob = BobFrClsIdx(clsInst, iinst);
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyUsedBy ()
|
||
|
// get the next symbol which query focus calls
|
||
|
//
|
||
|
{
|
||
|
WORD cuse;
|
||
|
IINST iinst;
|
||
|
BOB bob;
|
||
|
|
||
|
UbyInfo((IUBY)idxQyCur, &iinst, &cuse);
|
||
|
bob = BobFrClsIdx(clsInst, iinst);
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyUsedIn ()
|
||
|
// get the next module which query focus is used in
|
||
|
//
|
||
|
{
|
||
|
WORD wLine;
|
||
|
BOB bob;
|
||
|
LSZ lszMod;
|
||
|
|
||
|
for ( ; idxQyCur < idxQyMac ; idxQyCur++) {
|
||
|
RefInfo((IREF)idxQyCur, &lszMod, &wLine);
|
||
|
|
||
|
if (strcmp(lszMod, lszModLast) == 0)
|
||
|
continue;
|
||
|
|
||
|
strcpy(lszModLast, lszMod);
|
||
|
|
||
|
bob = BobFrClsIdx(clsMod, ImodFrLsz(lszMod));
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyDefinedIn ()
|
||
|
// get the next module which query focus is defined in
|
||
|
//
|
||
|
{
|
||
|
WORD wLine;
|
||
|
LSZ lszMod;
|
||
|
BOB bob;
|
||
|
|
||
|
for ( ; idxQyCur < idxQyMac ; idxQyCur++) {
|
||
|
DefInfo((IDEF)idxQyCur, &lszMod, &wLine);
|
||
|
|
||
|
if (strcmp(lszMod, lszModLast) == 0)
|
||
|
continue;
|
||
|
|
||
|
strcpy(lszModLast, lszMod);
|
||
|
|
||
|
bob = BobFrClsIdx(clsMod, ImodFrLsz(lszMod));
|
||
|
idxQyCur++;
|
||
|
return bob;
|
||
|
}
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
LSZ BSC_API
|
||
|
LszNameFrBob(BOB bob)
|
||
|
// return the name of the given bob
|
||
|
//
|
||
|
{
|
||
|
switch (ClsOfBob(bob)) {
|
||
|
|
||
|
case clsMod:
|
||
|
return LszNameFrMod(ImodFrBob(bob));
|
||
|
|
||
|
case clsSym:
|
||
|
return LszNameFrSym(IsymFrBob(bob));
|
||
|
|
||
|
case clsInst:
|
||
|
{
|
||
|
ISYM isym;
|
||
|
TYP typ;
|
||
|
ATR atr;
|
||
|
|
||
|
InstInfo(IinstFrBob(bob), &isym, &typ, &atr);
|
||
|
return LszNameFrSym(isym);
|
||
|
}
|
||
|
|
||
|
case clsRef:
|
||
|
{
|
||
|
LSZ lsz;
|
||
|
WORD wLine;
|
||
|
|
||
|
RefInfo(IrefFrBob(bob), &lsz, &wLine);
|
||
|
return lsz;
|
||
|
}
|
||
|
|
||
|
case clsDef:
|
||
|
{
|
||
|
LSZ lsz;
|
||
|
WORD wLine;
|
||
|
|
||
|
DefInfo(IdefFrBob(bob), &lsz, &wLine);
|
||
|
return lsz;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return "?";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOB BSC_API
|
||
|
BobFrName(LSZ lszName)
|
||
|
// return the best bob we can find from the given name
|
||
|
//
|
||
|
{
|
||
|
ISYM isym;
|
||
|
IMOD imod, imodMac;
|
||
|
IINST iinst, iinstMac;
|
||
|
|
||
|
if ((isym = IsymFrLsz(lszName)) != isymNil) {
|
||
|
InstRangeOfSym(isym, &iinst, &iinstMac);
|
||
|
return BobFrClsIdx(clsInst, iinst);
|
||
|
}
|
||
|
|
||
|
if ((imod = ImodFrLsz(lszName)) != imodNil) {
|
||
|
return BobFrClsIdx(clsMod, imod);
|
||
|
}
|
||
|
|
||
|
imodMac = ImodMac();
|
||
|
|
||
|
// no exact match -- try short names
|
||
|
lszName = LszBaseName(lszName);
|
||
|
for (imod = 0; imod < imodMac; imod++)
|
||
|
if (_stricmp(lszName, LszBaseName(LszNameFrMod(imod))) == 0)
|
||
|
return BobFrClsIdx(clsMod, imod);
|
||
|
|
||
|
return bobNil;
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyRefs()
|
||
|
// return the next File in a file query
|
||
|
//
|
||
|
{
|
||
|
BOB bob;
|
||
|
static IREF iref, irefMac;
|
||
|
|
||
|
for (;;) {
|
||
|
if (!fWorking) {
|
||
|
for ( ; idxQyCur < idxQyMac ; idxQyCur++) {
|
||
|
|
||
|
RefRangeOfInst((IINST)idxQyCur, &iref, &irefMac);
|
||
|
if (iref != irefMac)
|
||
|
break;
|
||
|
}
|
||
|
if (idxQyCur >= idxQyMac)
|
||
|
return bobNil;
|
||
|
|
||
|
fWorking = TRUE;
|
||
|
}
|
||
|
|
||
|
if (iref < irefMac) {
|
||
|
bob = BobFrClsIdx(clsRef, iref);
|
||
|
iref++;
|
||
|
return bob;
|
||
|
}
|
||
|
|
||
|
idxQyCur++;
|
||
|
fWorking = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static BOB
|
||
|
BobQyDefs()
|
||
|
// return the next File in a file query
|
||
|
//
|
||
|
{
|
||
|
BOB bob;
|
||
|
static IDEF idef, idefMac;
|
||
|
|
||
|
for (;;) {
|
||
|
if (!fWorking) {
|
||
|
for ( ; idxQyCur < idxQyMac ; idxQyCur++) {
|
||
|
|
||
|
DefRangeOfInst((IINST)idxQyCur, &idef, &idefMac);
|
||
|
if (idef != idefMac)
|
||
|
break;
|
||
|
}
|
||
|
if (idxQyCur >= idxQyMac)
|
||
|
return bobNil;
|
||
|
|
||
|
fWorking = TRUE;
|
||
|
}
|
||
|
|
||
|
if (idef < idefMac) {
|
||
|
bob = BobFrClsIdx(clsDef, idef);
|
||
|
idef++;
|
||
|
return bob;
|
||
|
}
|
||
|
|
||
|
idxQyCur++;
|
||
|
fWorking = FALSE;
|
||
|
}
|
||
|
}
|