// // bsc.c -- manage queries on the database // // Copyright 1988, Microsoft Corporation // // Revision History: // // #include #include #include #include #include #define LINT_ARGS #if defined(OS2) #define INCL_NOCOMMON #define INCL_DOSPROCESS #define INCL_DOSSEMAPHORES #define INCL_DOSFILEMGR #define INCL_DOSERRORS #define INCL_DOSMISC #include #include #else #include #endif #include "hungary.h" #include "mbrcache.h" #include "version.h" #include "sbrbsc.h" #include "bsc.h" #define LISTALLOC 50 // Browser max list size // static data static FILEHANDLE fhBSC = (FILEHANDLE)(-1); // .BSC file handle static BYTE fCase; // TRUE for case compare static BYTE MaxSymLen; // longest symbol length static WORD ModCnt; // count of modules static ISYM Unknown; // UNKNOWN symbol index static WORD ModSymCnt; // count of modsyms static WORD SymCnt; // count of symbols static WORD PropCnt; // count of properties static DWORD RefCnt; // count of references static WORD DefCnt; // count of definitions static WORD CalCnt; // count of calls static WORD CbyCnt; // count of called bys static WORD lastAtomPage; // last atom page # static WORD lastAtomCnt; // last atom page size static WORD cbModSymCnt; // size of list of modsyms static WORD cbSymCnt; // size of list of symbols static WORD cbPropCnt; // size of list of properties static WORD cbRefCnt; // size of list of references static WORD cbDefCnt; // size of list of definitions static WORD cbCalCnt; // size of list of calls static WORD cbCbyCnt; // size of list of called bys static WORD MaxModSymCnt; // max list of modsyms static WORD MaxSymCnt; // max list of symbols static WORD MaxPropCnt; // max list of properties static WORD MaxRefCnt; // max list of references static WORD MaxDefCnt; // max list of references static WORD MaxCalCnt; // max list of calls static WORD MaxCbyCnt; // max list of called bys static DWORD lbModSymList; // modsym list file start static DWORD lbSymList; // symbol list file start static DWORD lbPropList; // property list file start static DWORD lbRefList; // reference list file start static DWORD lbDefList; // def'n list file start static DWORD lbCalList; // calls list file start static DWORD lbCbyList; // call bys list file start static DWORD lbSbrList; // sbr list file start static DWORD lbAtomCache; // atom cache file start static WORD CurModSymPage = 0; // Current page of modsyms static WORD CurSymPage = 0; // Current page of symbols static WORD CurPropPage = 0; // Current page of properties static WORD CurRefPage = 0; // Current page of references static WORD CurDefPage = 0; // Current page of definitions static WORD CurCalPage = 0; // Current page of calls static WORD CurCbyPage = 0; // Current page of called bys static LSZ lszBSCName = NULL; // name of .bsc file static MODLIST far *pfModList = NULL; // module list cache start static MODSYMLIST far *pfModSymList = NULL; // modsym list cache start static SYMLIST far *pfSymList = NULL; // symbol list cache start static PROPLIST far *pfPropList = NULL; // property list cache start static REFLIST far *pfRefList = NULL; // reference list cache start static REFLIST far *pfDefList = NULL; // def'n list cache start static USELIST far *pfCalList = NULL; // calls list cache start static USELIST far *pfCbyList = NULL; // call bys list cache start static WORD AtomPageTblMac = 0; // last cache page used static CACHEPAGE AtomPageTbl[MAXATOMPAGETBL]; // Atom Cache table #define bMOD(imod) (pfModList[imod]) #define bMODSYM(isym) (pfModSymList[isym]) #define bSYM(isym) (pfSymList[isym]) #define bPROP(iprop) (pfPropList[iprop]) #define bREF(iref) (pfRefList[iref]) #define bDEF(idef) (pfDefList[idef]) #define bCAL(iuse) (pfCalList[iuse]) #define bCBY(iuse) (pfCbyList[iuse]) #define bUSE(iuse) (pfCalList[iuse]) #define bUBY(iuse) (pfCbyList[iuse]) // prototypes // #define BSCIn(v) ReadBSC(&v, sizeof(v)); static VOID GetBSC (DWORD lpos, LPV lpv, WORD cb); static VOID ReadBSC(LPV lpv, WORD cb); static WORD SwapPAGE (DWORD, LPV, WORD, WORD, WORD *, DWORD); static LPCH GetAtomCache (WORD); static VOID ReadBSC(LPV lpv, WORD cb) // read a block of data from the BSC file // { if (BSCRead(fhBSC, lpv, cb) != cb) ReadError(lszBSCName); } static VOID GetBSC(DWORD lpos, LPV lpv, WORD cb) // Read a block of the specified size from the specified position // { #if defined (OS2) if (BSCSeek(fhBSC, lpos, SEEK_SET) == -1) #else if (BSCSeek(fhBSC, lpos, FILE_BEGIN) == -1) SeekError(lszBSCName); #endif if (BSCRead(fhBSC, lpv, cb) != cb) ReadError(lszBSCName); } static WORD SwapPAGE (DWORD lbuflist, LPV pfTABLE, WORD tblsiz, /* */ WORD lstsiz, WORD * pcurpage, DWORD idx) // // // SwapPAGE - Swap in the table page for the table pfTABLE[idx] // and return the table's new index in the page. { WORD page; WORD newidx; page = (WORD)(idx / lstsiz); newidx = (WORD)(idx % lstsiz); if (page == *pcurpage) return newidx; GetBSC(lbuflist+((long)tblsiz*(long)page), pfTABLE, tblsiz); *pcurpage = page; return newidx; } static WORD ModSymPAGE (IMOD imod) // Swap in the ModSym page for ModSym[imod] // return the ModSym's index in the page. // { return SwapPAGE (lbModSymList, pfModSymList, cbModSymCnt, MaxModSymCnt, &CurModSymPage, (IDX)imod); } static WORD SymPAGE (ISYM isym) // Swap in the Symbol page for symbol[isym] // return the Symbol's index in the page. // { return SwapPAGE (lbSymList, pfSymList, cbSymCnt, MaxSymCnt, &CurSymPage, (IDX)isym); } static WORD PropPAGE (IINST iinst) // Swap in the Property page for Property[idx] // return the Property's index in the page. // { return SwapPAGE (lbPropList, pfPropList, cbPropCnt, MaxPropCnt, &CurPropPage, (IDX)iinst); } static WORD RefPAGE (IREF iref) // Swap in the Reference page for Reference[idx] // return the Reference's index in the page. // { return SwapPAGE (lbRefList, pfRefList, cbRefCnt, MaxRefCnt, &CurRefPage, (IDX)iref); } static WORD DefPAGE (IDEF idef) // Swap in the Deference page for Definition[idef] // return the Definitions index in the page. // { return SwapPAGE (lbDefList, pfDefList, cbDefCnt, MaxDefCnt, &CurDefPage, (IDX)idef); } static WORD CalPAGE (IUSE iuse) // Swap in the Usage page for Usage[iuse] (cal/cby) // and return the Usage's index in the page. // { return SwapPAGE (lbCalList, pfCalList, cbCalCnt, MaxCalCnt, &CurCalPage, (IDX)iuse); } static WORD CbyPAGE (IUSE iuse) // Swap in the Usage page for Usage[iuse] (cal/cby) // and return the Usage's index in the page. // { return SwapPAGE (lbCbyList, pfCbyList, cbCbyCnt, MaxCbyCnt, &CurCbyPage, (IDX)iuse); } static LPCH GetAtomCache (WORD Page) // load the requested page into the cache // { register WORD ipg; WORD pagesize; LPCH pfAtomCsave; for (ipg = 0; ipg < AtomPageTblMac; ipg++) { if (AtomPageTbl[ipg].uPage == Page) return AtomPageTbl[ipg].pfAtomCache; } if (ipg != MAXATOMPAGETBL) { if (AtomPageTbl[ipg].pfAtomCache || (AtomPageTbl[ipg].pfAtomCache = LpvAllocCb(ATOMALLOC))) AtomPageTblMac++; } pfAtomCsave = AtomPageTbl[AtomPageTblMac-1].pfAtomCache; for (ipg = AtomPageTblMac-1; ipg; ipg--) AtomPageTbl[ipg] = AtomPageTbl[ipg-1]; // move up AtomPageTbl[0].pfAtomCache = pfAtomCsave; AtomPageTbl[0].uPage = Page; if (Page == lastAtomPage) pagesize = lastAtomCnt; else pagesize = ATOMALLOC; GetBSC(lbAtomCache+ATOMALLOC*(long)Page, AtomPageTbl[0].pfAtomCache, pagesize); return AtomPageTbl[0].pfAtomCache; } LSZ BSC_API LszNameFrSym (ISYM isym) // Swap in the Atom page for the symbol isym // return the atom's address in the page. // { SYMLIST sym; sym = bSYM(isym); return GetAtomCache (sym.Page) + sym.Atom; } LSZ BSC_API LszNameFrMod (IMOD imod) // Swap in the Atom page for the module isym // return the atom's address in the page. // { return LszNameFrSym(bMOD(imod).ModName); } int BSC_API CaseCmp(LSZ lsz1, LSZ lsz2) // // think of lsz1 and lsz2 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 lsz1 before, at, or after lsz2 in the list // { int ret; // do case insensitive compare ret = _stricmp(lsz1, lsz2); // 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(lsz1, lsz2); } ISYM BSC_API IsymFrLsz (LSZ lszReqd) // find the symbol with the specifed name // { ISYM Lo, Hi, Mid; int Cmp; LSZ lszCur; Lo = 0; Hi = (ISYM)(SymCnt - 1); while (Lo <= Hi) { Mid = (ISYM)((Hi + Lo) / 2); lszCur = LszNameFrSym (Mid); Cmp = CaseCmp (lszReqd, lszCur); if (Cmp == 0) return Mid; if (Cmp < 0) Hi = (ISYM)(Mid - 1); else Lo = (ISYM)(Mid + 1); } return isymNil; } IMOD BSC_API ImodFrLsz (LSZ lszReqd) // find the module with the specifed name // { IMOD imod; for (imod = 0; imod < ModCnt; imod++) { if (_stricmp (lszReqd, LszNameFrSym (bMOD(imod).ModName)) == 0) return imod; } return imodNil; } ISYM BSC_API IsymMac() // return the biggest isym in this database // { return SymCnt; } IMOD BSC_API ImodMac() // return the biggest imod in this database // { return ModCnt; } IINST BSC_API IinstMac() // return the biggest iinst in this database // { return PropCnt; } VOID BSC_API MsRangeOfMod(IMOD imod, IMS *pimsFirst, IMS *pimsLast) // fill in the module information // { *pimsFirst = imod ? bMOD(imod-1).mSymEnd : 0; *pimsLast = bMOD(imod).mSymEnd; } IINST BSC_API IinstOfIms(IMS ims) // give the instance (PROP) index of the modsym // { return bMODSYM(ims).ModSymProp; } VOID BSC_API InstRangeOfSym(ISYM isym, IINST *piinstFirst, IINST *piinstLast) // fill in the range of inst values for this symbol // { *piinstFirst = isym ? bSYM(isym-1).PropEnd:0; *piinstLast = bSYM(isym).PropEnd; } VOID BSC_API InstInfo(IINST iinst, ISYM *pisymInst, TYP *pTyp, ATR *pAtr) // get the information that qualifies this instance // { *pisymInst = bPROP(iinst).PropName; *pAtr = bPROP(iinst).PropAttr & 0x3ff; *pTyp = (bPROP(iinst).PropAttr >> 11) & 0x1f; } VOID BSC_API RefRangeOfInst(IINST iinst, IREF *pirefFirst, IREF *pirefLast) // fill in the reference ranges from the inst // { *pirefFirst = iinst ? bPROP(iinst-1).RefEnd : 0; *pirefLast = bPROP(iinst).RefEnd; } VOID BSC_API DefRangeOfInst(IINST iinst, IDEF *pidefFirst, IDEF *pidefLast) // fill in the definition ranges from the inst // { *pidefFirst = iinst ? bPROP(iinst-1).DefEnd : 0; *pidefLast = bPROP(iinst).DefEnd; } VOID BSC_API UseRangeOfInst(IINST iinst, IUSE *piuseFirst, IUSE *piuseLast) // fill in the use ranges from the inst // { *piuseFirst = iinst ? bPROP(iinst-1).CalEnd : 0; *piuseLast = bPROP(iinst).CalEnd; } VOID BSC_API UbyRangeOfInst(IINST iinst, IUBY *piubyFirst, IUBY *piubyLast) // fill in the used by ranges from the inst // { *piubyFirst = iinst ? bPROP(iinst-1).CbyEnd : 0; *piubyLast = bPROP(iinst).CbyEnd; } VOID BSC_API UseInfo(IUSE iuse, IINST *piinst, WORD *pcnt) // fill in the information about this things which an inst uses // { *piinst = bUSE(iuse).UseProp; *pcnt = bUSE(iuse).UseCnt; } VOID BSC_API UbyInfo(IUBY iuby, IINST *piinst, WORD *pcnt) // fill in the information about this things which an inst is used by // { *piinst = bUBY(iuby).UseProp; *pcnt = bUBY(iuby).UseCnt; } VOID BSC_API RefInfo(IREF iref, LSZ *plszName, WORD *pline) // fill in the information about this reference // { *pline = bREF(iref).RefLin; *plszName = LszNameFrSym(bREF(iref).RefNam); } VOID BSC_API DefInfo(IDEF idef, LSZ *plszName, WORD *pline) // fill in the information about this definition // { *pline = bDEF(idef).RefLin; *plszName = LszNameFrSym(bDEF(idef).RefNam); } VOID BSC_API CloseBSC() // close database and free as much memory as possible // { int i; // close file if open if (fhBSC != (FILEHANDLE)(-1)) { BSCClose (fhBSC); fhBSC = (FILEHANDLE)(-1); } // free any memory we may have allocated if (pfModList) { FreeLpv (pfModList); pfModList = NULL; } if (pfModSymList) { FreeLpv (pfModSymList); pfModSymList = NULL; } if (pfSymList) { FreeLpv (pfSymList); pfSymList = NULL; } if (pfPropList) { FreeLpv (pfPropList); pfPropList = NULL; } if (pfRefList) { FreeLpv (pfRefList); pfRefList = NULL; } if (pfDefList) { FreeLpv (pfDefList); pfDefList = NULL; } if (pfCalList) { FreeLpv (pfCalList); pfCalList = NULL; } if (pfCbyList) { FreeLpv (pfCbyList); pfCbyList = NULL; } for (i=0; i < MAXATOMPAGETBL; i++) { if (AtomPageTbl[i].pfAtomCache) { FreeLpv (AtomPageTbl[i].pfAtomCache); // dispose Atom Cache AtomPageTbl[i].pfAtomCache = NULL; } } } BOOL BSC_API FOpenBSC (LSZ lszName) // Open the specified data base. // Allocate buffers for cache areas // Initialize the data cache from the data base. // // Return TRUE iff successful, FALSE if database can't be read // { WORD pagesize; BYTE MajorVer; // .bsc version (major) BYTE MinorVer; // .bsc version (minor) BYTE UpdatVer; // .bsc version (updat) WORD MaxModCnt; // max list of modules WORD cbModCnt; // size of list of modules DWORD lbModList; // module list file start int i; #define ABORT_OPEN CloseBSC(); return FALSE; lszBSCName = lszName; #if defined (OS2) fhBSC = BSCOpen(lszBSCName, O_BINARY|O_RDONLY); #else fhBSC = BSCOpen(lszBSCName, GENERIC_READ); #endif // if the .bsc file doesn't exist then we don't do any work // this is the cold compile case // if (fhBSC == (FILEHANDLE)(-1)) {ABORT_OPEN;} // read and check BSC version (major, minor and update) BSCIn(MajorVer); BSCIn(MinorVer); BSCIn(UpdatVer); BSCPrintf("Browser Data Base: %s ver %d.%d.%d\n\n", lszBSCName, MajorVer, MinorVer, UpdatVer); if ((MajorVer != BSC_MAJ) || (MinorVer != BSC_MIN) || (UpdatVer != BSC_UPD)) { CloseBSC(); BadBSCVer(lszBSCName); return FALSE; } // read Case sense switch, max symbol length and Unknown module id BSCIn(fCase); BSCIn(MaxSymLen); BSCIn(Unknown); // this will make the formatting look more reasonable if there are // only very short names in the database if (MaxSymLen < 8 ) MaxSymLen = 8; // read counts (sizes) of each data area BSCIn(ModCnt); BSCIn(ModSymCnt); BSCIn(SymCnt); BSCIn(PropCnt); BSCIn(RefCnt); BSCIn(DefCnt); BSCIn(CalCnt); BSCIn(CbyCnt); BSCIn(lastAtomPage); BSCIn(lastAtomCnt); // read BSC data area offsets BSCIn(lbModList); BSCIn(lbModSymList); BSCIn(lbSymList); BSCIn(lbPropList); BSCIn(lbRefList); BSCIn(lbDefList); BSCIn(lbCalList); BSCIn(lbCbyList); BSCIn(lbAtomCache); BSCIn(lbSbrList); // determine data cache area sizes #define MIN(a,b) ((a)>(b) ? (b) : (a)) MaxModCnt = ModCnt; // max list of modules MaxModSymCnt = ModSymCnt; // max list of modsyms MaxSymCnt = SymCnt+ModCnt; // max list of symbols MaxPropCnt = PropCnt; // max list of props MaxRefCnt = RefCnt; // max list of refs MaxDefCnt = DefCnt; // max list of defs MaxCalCnt = CalCnt; // max list of cals MaxCbyCnt = CbyCnt; // max list of cbys cbModCnt = sizeof(MODLIST) * MaxModCnt; // size of mods list cbModSymCnt = sizeof(MODSYMLIST) * MaxModSymCnt; // size of modsyms list cbSymCnt = sizeof(SYMLIST) * MaxSymCnt; // size of syms list cbPropCnt = sizeof(PROPLIST) * MaxPropCnt; // size of props list cbRefCnt = sizeof(REFLIST) * MaxRefCnt; // size of refs list cbDefCnt = sizeof(REFLIST) * MaxDefCnt; // size of defs list cbCalCnt = sizeof(USELIST) * MaxCalCnt; // size of cals list cbCbyCnt = sizeof(USELIST) * MaxCbyCnt; // size of cbys list // Allocate buffers for each of the object types if (!(pfModList = LpvAllocCb(cbModCnt))) { ABORT_OPEN; } if (!(pfModSymList = LpvAllocCb(cbModSymCnt))) { ABORT_OPEN; } if (!(pfSymList = LpvAllocCb(cbSymCnt))) { ABORT_OPEN; } if (!(pfPropList = LpvAllocCb(cbPropCnt))) { ABORT_OPEN; } if (!(pfRefList = LpvAllocCb(cbRefCnt))) { ABORT_OPEN; } if (!(pfDefList = LpvAllocCb(cbDefCnt))) { ABORT_OPEN; } if (!(pfCalList = LpvAllocCb(cbCalCnt))) { ABORT_OPEN; } if (!(pfCbyList = LpvAllocCb(cbCbyCnt))) { ABORT_OPEN; } // read data areas if (lastAtomPage == 0) pagesize = lastAtomCnt; else pagesize = ATOMALLOC; // clear out the atom cache // we must be able to allocate at least one page AtomPageTblMac = 0; for (i=0; i < MAXATOMPAGETBL; i++) AtomPageTbl[i].pfAtomCache = NULL; AtomPageTbl[0].uPage = 65535; AtomPageTbl[0].pfAtomCache = LpvAllocCb(pagesize); if (!AtomPageTbl[0].pfAtomCache) { ABORT_OPEN; } GetBSC(lbModList, pfModList, cbModCnt); // Init Mod cache GetBSC(lbModSymList, pfModSymList, cbModSymCnt); // Init ModSym cache GetBSC(lbSymList, pfSymList, cbSymCnt); // Init Sym cache GetBSC(lbPropList, pfPropList, cbPropCnt); // Init Prop cache GetBSC(lbRefList, pfRefList, cbRefCnt); // Init Ref cache GetBSC(lbDefList, pfDefList, cbDefCnt); // Init Def cache GetBSC(lbCalList, pfCalList, cbCalCnt); // Init Cal cache GetBSC(lbCbyList, pfCbyList, cbCbyCnt); // Init Cby cache // current page for all database items is now page zero CurModSymPage = 0; CurSymPage = 0; CurPropPage = 0; CurRefPage = 0; CurDefPage = 0; CurCalPage = 0; CurCbyPage = 0; GetAtomCache (0); // Init Atom cache return TRUE; } WORD BSC_API BSCMaxSymLen() // return the length of the largest symbol in the database // { return MaxSymLen; } BOOL BSC_API FCaseBSC() // is this database built with a case sensitive language? // { return fCase; } VOID BSC_API SetCaseBSC(BOOL fNewCase) // set case sensitivity of database // { fCase = (BYTE)!!fNewCase; }