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.
 
 
 
 
 
 

1327 lines
26 KiB

/* symlow.c - low management of symbol database
*
* Symlow contains all routines necessary to look up symbols in database,
* find symbols in files, and index files.
*/
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <stdio.h>
#include <stddef.h>
#include <windows.h>
#include <tools.h>
#include "db.h"
#include "symref.h"
BOOL fStateInit = FALSE; /* TRUE => state info initialized */
/* SRCreate - create a new symref database, replacing current one
*
* psz name of database.
*
* returns TRUE if successful
*/
BOOL SRCreate (PSZ psz)
{
PSRHDR psrhdr;
OFFSET o;
char buf[MAX_PATH];
/* Set up reference database
*/
upd (psz, ".ref", buf);
if (!DBCreate (buf)) {
printf ("SRCreate: DBCreate couldn't create %s\n", buf);
return FALSE;
}
pdbRef = DBOpen (buf);
if (pdbRef == NULL) {
printf ("SRCreate: DBOpen couldn't open %s\n", buf);
return FALSE;
}
DBClose (pdbRef, TRUE);
/* Set up symbol database
*/
upd (psz, ".sym", buf);
if (!DBCreate (buf)) {
printf ("SRCreate: DBCreate couldn't create %s\n", buf);
return FALSE;
}
pdbSym = DBOpen (buf);
if (pdbSym == NULL) {
printf ("SRCreate: DBOpen couldn't open %s\n", buf);
return FALSE;
}
o = DBAlloc (pdbSym, (LENGTH) sizeof (SRHDR));
if (o != OHDR) {
printf ("SRCreate: DBAlloc for header allocated %x instead of %x\n", o, OHDR);
DBClose (pdbSym, FALSE);
return FALSE;
}
o = DBAlloc (pdbSym, (LENGTH)SYMMAXHASH * sizeof (OFFSET));
if (o != OHASHTAB) {
printf ("SRCreate: DBAlloc for hash table allocated %x instead of %x\n", o, OHASHTAB);
DBClose (pdbSym, FALSE);
return FALSE;
}
psrhdr = MAPHEADER (OHDR);
psrhdr->rev = SRREV;
psrhdr->symmaxhash = SYMMAXHASH;
DBClose (pdbSym, TRUE);
return TRUE;
}
/* SROpen - open an existing database
*
* psz name of database
*
* returns TRUE if successful
*/
BOOL SROpen (PSZ psz)
{
PSRHDR psrhdr;
char buf[MAX_PATH];
/* open reference database
*/
upd (psz, ".ref", buf);
pdbRef = DBOpen (buf);
if (pdbRef == NULL) {
printf ("SROpen: DBOpen couldn't open %s\n", buf);
return FALSE;
}
/* open symbol database
*/
upd (psz, ".sym", buf);
pdbSym = DBOpen (buf);
if (pdbSym == NULL) {
printf ("SROpen: DBOpen couldn't open %s\n", buf);
DBClose (pdbRef, FALSE);
return FALSE;
}
/* verify version number
*/
psrhdr = MAPHEADER (OHDR);
if (psrhdr->rev != SRREV) {
printf ("SROpen: Downlevel hash version\n");
DBClose (pdbSym, FALSE);
DBClose (pdbRef, FALSE);
return FALSE;
}
if (psrhdr->symmaxhash != SYMMAXHASH) {
printf ("SROpen: Unexpected hash number\n");
DBClose (pdbSym, FALSE);
DBClose (pdbRef, FALSE);
return FALSE;
}
return TRUE;
}
/* SRClose - close an open database
*
* fCommit TRUE => write out database
*/
void SRClose (BOOL fCommit)
{
DBClose (pdbSym, fCommit);
DBClose (pdbRef, fCommit);
}
/* hashFromSym - calculate hash value for symbol
*
* Engineering determined these values, not science.
*
* psz pointer to name for hash
*
* returns hash value
*/
HASH hashFromSym (PSZ psz)
{
HASH i = 0;
while (*psz)
i += (i << 5) + *psz++;
return i % SYMMAXHASH;
}
/* pshFind - find a symbol in the hash list
*
* psz pointer to name
* posh pointer to offset of symbol
*
* returns PSH of found symbol or NULL
*/
PSH pshFind (PSZ psz, OFFSET *posh)
{
HASH h = hashFromSym (psz);
OFFSET *phash = MAPHASH (OHASH (h));
OFFSET osh = *phash;
PSH psh;
while (osh != (OFFSET)0) {
psh = MAPSH (osh);
if (!strcmp (psz, SZ(psh))) {
if (posh != NULL)
*posh = osh;
return psh;
}
osh = psh->oshNext;
}
if (posh != NULL)
*posh = osh;
return NULL;
}
/* psymFind - find a symbol in the hash list
*
* psz pointer to name
* posym pointer to location of record
* fCreate TRUE => Create symbol if not found
*
* returns pointer to symbol or NULL
*/
PSYM psymFind (PSZ psz, OFFSET *posym, BOOL fCreate)
{
PSH psh;
int cch;
OFFSET osym;
PSYM psym;
PHASH phash;
psh = pshFind (psz, posym);
if (psh != NULL)
if (psh->type == TY_SYM)
return (PSYM) psh;
else
return NULL;
if (!fCreate)
return NULL;
cch = strlen (psz);
osym = DBAlloc (pdbSym, CBSYM (cch));
if (osym == (OFFSET)0)
return NULL;
psym = MAPSYM (osym);
phash = MAPHASH (OHASH (hashFromSym (psz)));
psym->sh.oshNext = *phash;
psym->sh.type = TY_SYM;
psym->sh.dName = offsetof (SYM, name);
psym->oref = (OFFSET)0;
psym->name.cch = (BYTE) cch;
strcpy (psym->name.sz, psz);
*phash = osym;
if (posym != NULL)
*posym = osym;
return psym;
}
/* pfilFind - find a file in the hash list
*
* psz pointer to name
* pofil pointer to location of record
* fCreate TRUE => create file
*
* returns pointer to file or NULL
*/
PFIL pfilFind (PSZ psz, OFFSET *pofil, BOOL fCreate)
{
PSH psh;
int cch;
OFFSET ofil;
PFIL pfil;
PHASH phash;
psh = pshFind (psz, pofil);
if (psh != NULL)
if (psh->type == TY_FIL)
return (PFIL) psh;
else
return NULL;
if (!fCreate)
return NULL;
cch = strlen (psz);
ofil = DBAlloc (pdbSym, CBFIL (cch));
if (ofil == (OFFSET)0)
return NULL;
pfil = MAPFIL (ofil);
phash = MAPHASH (OHASH (hashFromSym (psz)));
pfil->sh.oshNext = *phash;
pfil->sh.type = TY_FIL;
pfil->sh.dName = offsetof (FIL, name);
pfil->oref = (OFFSET)0;
pfil->ompBlkLine = (OFFSET)0;
pfil->tmMod.dwLowDateTime = (DWORD) 0;
pfil->tmMod.dwHighDateTime = (DWORD) 0;
pfil->cblk = 0;
pfil->name.cch = (BYTE) cch;
strcpy (pfil->name.sz, psz);
*phash = ofil;
if (pofil != NULL)
*pofil = ofil;
return pfil;
}
/* pdirFind - find a directory
*
* psz pointer to name
* podir pointer to location of record
* fCreate TRUE => create directory
*
* returns pointer to directory or NULL
*/
PDIR pdirFind (PSZ psz, OFFSET *podir, BOOL fCreate)
{
PSH psh;
int cch;
OFFSET odir;
PDIR pdir;
PHASH phash;
psh = pshFind (psz, podir);
if (psh != NULL)
if (psh->type == TY_DIR)
return (PDIR) psh;
else
return NULL;
if (!fCreate)
return NULL;
cch = strlen (psz);
odir = DBAlloc (pdbSym, CBDIR (cch));
if (odir == (OFFSET)0)
return NULL;
pdir = MAPDIR (odir);
phash = MAPHASH (OHASH (hashFromSym (psz)));
pdir->sh.oshNext = *phash;
pdir->sh.type = TY_DIR;
pdir->sh.dName = offsetof (DIR, name);
pdir->name.cch = (BYTE) cch;
strcpy (pdir->name.sz, psz);
*phash = odir;
if (podir != NULL)
*podir = odir;
return pdir;
}
/* pextFind - find an extention
*
* psz pointer to name
* poext pointer to location of record
* fCreate TRUE => create extention
*
* returns pointer to extention or NULL
*/
PEXT pextFind (PSZ psz, OFFSET *poext, BOOL fCreate)
{
PSH psh;
int cch;
OFFSET oext;
PEXT pext;
PHASH phash;
psh = pshFind (psz, poext);
if (psh != NULL)
if (psh->type == TY_EXT)
return (PEXT) psh;
else
return NULL;
if (!fCreate)
return NULL;
cch = strlen (psz);
oext = DBAlloc (pdbSym, CBEXT (cch));
if (oext == (OFFSET)0)
return NULL;
pext = MAPEXT (oext);
phash = MAPHASH (OHASH (hashFromSym (psz)));
pext->sh.oshNext = *phash;
pext->sh.type = TY_EXT;
pext->sh.dName = offsetof (EXT, name);
pext->name.cch = (BYTE) cch;
strcpy (pext->name.sz, psz);
*phash = oext;
if (poext != NULL)
*poext = oext;
return pext;
}
/* pnoiFind - find a noise word
*
* psz pointer to name
* ponoi pointer to location of record
* fCreate TRUE => create skipped extension
*
* returns pointer to skipped extension or NULL
*/
PNOI pnoiFind (PSZ psz, OFFSET *ponoi, BOOL fCreate)
{
PSH psh;
int cch;
OFFSET onoi;
PNOI pnoi;
PHASH phash;
psh = pshFind (psz, ponoi);
if (psh != NULL)
if (psh->type == TY_NOI)
return (PNOI) psh;
else
return NULL;
if (!fCreate)
return NULL;
cch = strlen (psz);
onoi = DBAlloc (pdbSym, CBNOI (cch));
if (onoi == (OFFSET)0)
return NULL;
pnoi = MAPNOI (onoi);
phash = MAPHASH (OHASH (hashFromSym (psz)));
pnoi->sh.oshNext = *phash;
pnoi->sh.type = TY_NOI;
pnoi->sh.dName = offsetof (NOI, name);
pnoi->name.cch = (BYTE) cch;
strcpy (pnoi->name.sz, psz);
*phash = onoi;
if (ponoi != NULL)
*ponoi = onoi;
return pnoi;
}
/* pvecAlloc - allocate block-to-line map
*
* pfil pointer to file symbol
* cblk number of blocks
*
* returns pointer to vector or NULL
*/
PLINE pvecAlloc (PFIL pfil, int cblk)
{
PLINE pvec;
LENGTH l;
if (pfil->ompBlkLine != (OFFSET)0 || pfil->cblk != 0)
printf ("pvecAllocAlready allocated map vector\n");
l = (LENGTH) cblk * sizeof (LINE);
pfil->ompBlkLine = DBAlloc (pdbRef, l);
if (pfil->ompBlkLine == (OFFSET)0)
return NULL;
pfil->cblk = cblk;
pvec = MAPVECTOR (pfil->ompBlkLine);
memset (pvec, 0xFF, l);
return pvec;
}
/* prefFind - find/create a reference
*
* Given a SYM, see if the first REFERENCE on the symbol is for
* the particular file. If one is not present, create one.
*
* psym SYM to scan
* osym symbol offset
* pfil FIL
* ofil file offset
* cblk size of file
*
* returns pointer to REFERENCE or NULL
*/
PREF prefFind (PSYM psym, OFFSET osym, PFIL pfil, OFFSET ofil, int cblk)
{
OFFSET oref = psym->oref;
PREF pref;
LENGTH l;
if (oref != (OFFSET)0) {
pref = MAPREFERENCE (oref);
if (pref->ofil == ofil)
return pref;
}
/* Allocate new reference
*/
l = CBREF (cblk);
oref = DBAlloc (pdbRef, l);
if (oref == (OFFSET)0)
return NULL;
pref = MAPREFERENCE (oref);
memset (pref, '\0', l);
pref->ofil = ofil;
pref->osym = osym;
pref->orefNext = psym->oref;
pref->orefFileNext = pfil->oref;
pfil->oref = oref;
psym->oref = oref;
return pref;
}
/* fSetRefSymBit - turn on a particular bit in a reference on a symbol
*
* Creates symbol and reference as needed
*
* psz name of symbol
* ibit which bit to turn on
* pfil FIL for owning file
* ofil offset to FIL for owning file
* cblk size in blocks of file
*
* returns TRUE if successful
*/
BOOL fSetRefSymBit (PSZ psz, int ibit, PFIL pfil, OFFSET ofil, int cblk)
{
PSYM psym;
PREF pref;
OFFSET osym;
psym = psymFind (psz, &osym, TRUE);
if (psym == NULL)
return TRUE;
pref = prefFind (psym, osym, pfil, ofil, cblk);
if (pref == NULL)
return FALSE;
pref->bm[ibit >> 3] |= (1 << (ibit & 0x7));
return TRUE;
}
/* Indexing of files uses a simple state machine that is set up as follows:
*
* State 0: (not building a symbol)
* valid first symbol char:
* Action 0:
* Store character
* Goto state 1
* LF: Action 1:
* New line processing
* Goto state 0
* Otherwise:
* Action 2:
* Stay in state 0
*
* State 1: (building a symbol)
* valid symbol char:
* Action 3:
* Store character
* Goto state 1
* LF: Action 4:
* Terminate symbol
* Index symbol
* New line processing
* Goto state 0
* Otherwise:
* Action 5:
* Terminate symbol
* Index symbol
* goto state 0
*/
int state0[256] = {-1};
int state1[256] = {-1};
void SRIndexInit ()
{
int c;
/* Initialize state tables */
for (c = 0; c < 256; c++) {
state0[c] = iscsymf (c) ? 0 : 2;
state1[c] = iscsym (c) ? 3 : 5;
}
state0[0x0D] = -1;
state1[0x0D] = -1;
state0[0x0A] = 1;
state1[0x0A] = 4;
}
/* IndexFile - grovel over a file and add all symbols to the database
*
* This routine is long and gross. We open the file. Read it in big
* chunks (future optimization would be to use a separate thread to
* do the reading). Parse off symbols one at a time, remembering line
* boundaries and block boundaries.
*
* hf open handle to file (caller may have openned it already)
* psz file name
*
* returns number of bytes in file or 0 if nothing indexed
*/
long IndexFile (HANDLE hf, PSZ psz)
{
PLINE pvec; /* pointer to blk-to-line map */
PFIL pfil; /* pointer to currently indexing file*/
OFFSET ofil; /* offset of FIL for file */
FILETIME tm;
char *pbuf; /* pointer to I/O buffer for reading */
char szSym[LINELEN]; /* symbol that's being built */
UCHAR *pch; /* roving pointer to pbuf */
char *pszSym; /* roving pointer to szSym */
long cbFile; /* number of characters left in pbuf */
long cbTotal; // number of chars in file
int c;
int cchline; /* length of line being built */
LINE line; /* current line */
int cblk; /* length of file in blocks */
int iblk; /* current block in file */
#define OCH(pch) ((pch)-pbuf)
#define IBLK(och) ((och) >> BLKSHFT)
int *pstate; /* state for building symbols */
if (!fStateInit) {
SRIndexInit ();
fStateInit = TRUE;
}
rootpath (psz, szSym);
/* Open the file for reading
*/
if (hf == HANDLE_BAD)
hf = CreateFile (psz,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hf == HANDLE_BAD) {
NOTEERROR ("IndexFile: CreateFile");
return 0;
}
//
// Load file into RAM
//
cbTotal = cbFile = GetFileSize (hf, NULL);
pbuf = malloc (cbFile);
if (!ReadFile (hf, pbuf, cbFile, &c, NULL))
NOTEERROR ("IndexFile: ReadFile");
if (!GetFileTime (hf, NULL, NULL, &tm))
NOTEERROR ("IndexFile: GetFileTime");
CloseHandle (hf);
//
// Create file record
//
pfil = pfilFind (szSym, &ofil, TRUE);
//
// Compute number of blocks in file and initialize block->line mapping
//
cblk = IBLK (cbFile + CBBLK - 1);
pvec = pvecAlloc (pfil, cblk);
pvec[0] = 0;
//
// Set up timestamp for syncronization
//
pfil->tmMod = tm;
//
// set up state machine info
//
pstate = state0; // State machine is looking for sym
pch = pbuf; // starting at beginning of file
line = 0; // building within line 0
iblk = IBLK(OCH(pch)); // correct block number
cchline = 0; // beginning of line
pszSym = NULL; // debugging!
//
// for each character advance state machine and process
//
while (cbFile != 0) {
c = tolower (*pch);
cbFile--;
pch++;
//
// We ignore \r's since they do not delimit lines nor do most
// editors retain them internally
//
if (c == '\r')
continue;
//
// Advance line length and check for linelength overflow
// Treat overflow as if there were a NL inserted.
// Only do this if the char that caused overflow is not a
// line ending char
//
cchline += (c == '\t') ? (8 - (cchline & 0x07)) : 1;
if (cchline >= LINELEN-1 && c != 0x0A) {
cbFile++;
pch--;
c = 0x0A;
}
//
// Perform state machine action
//
switch (pstate[c]) {
//
// [state0] We're not building a symbol but we see a valid first
// symbol character.
//
case 0:
pszSym = szSym;
*pszSym++ = (char) c;
pstate = state1;
break;
//
// [state0] We're not building a symbol and we see EOL
//
case 1:
//
// Set up for new line
//
line++;
cchline = 0;
iblk = IBLK (OCH (pch));
if (pvec[iblk] == BADLINE)
pvec[iblk] = (OCH (pch) & BLKMSK) == 0 ? line : (LINE) (line | 0x8000);
// pstate = state0;
break;
//
// [state0] We're not building a symbol and we see a non-symbol
// char
//
case 2:
// pstate = state0;
break;
//
// [state 1] We're building a symbol and we see a sybol char
//
case 3:
*pszSym++ = (char) c;
// pstate = state1;
break;
//
// [state 1] We're building a symbol and we see an EOL
//
case 4:
//
// Terminate symbol and index it
//
*pszSym = '\0';
if (!fSetRefSymBit (szSym, iblk, pfil, ofil, cblk)) {
cbFile = 0;
break;
}
//
// Set up for new line
//
line++;
cchline = 0;
iblk = IBLK (OCH (pch));
if (pvec[iblk] == BADLINE)
pvec[iblk] = (OCH (pch) & BLKMSK) == 0 ? line : (LINE) (line | 0x8000);
//
// Set up for not indexing symbol
//
pszSym = NULL;
pstate = state0;
break;
//
// [state 1] We're building a symbol and we see a non-symbol char
//
case 5:
//
// Terminate symbol and index it
//
*pszSym = '\0';
if (!fSetRefSymBit (szSym, iblk, pfil, ofil, cblk)) {
cbFile = 0;
break;
}
//
// Set up for not indexing symbol
//
pszSym = NULL;
pstate = state0;
break;
//
// Error trap
//
default:
printf ("IndexFile state is %d\n", pstate[c]);
}
}
free (pbuf);
return cbTotal;
}
/* UnlinkSH - unlink a symbol header
*
* psh pointer to symbol record
* osh offset to symbol record
*/
void UnlinkSH (PSH psh, OFFSET osh)
{
PHASH phash;
OFFSET oshScan;
PSH pshScan;
//
// Get the pointer to the beginning of the hash bucket
//
phash = MAPHASH (OHASH (hashFromSym (SZ (psh))));
oshScan = *phash;
//
// if the record is at the beginning of the hash bucket, simply unlink
// it
//
if (osh == oshScan)
*phash = psh->oshNext;
//
// otherwise, find the symbol that points to the record
//
else {
while (osh != oshScan) {
pshScan = MAPSH (oshScan);
oshScan = pshScan->oshNext;
}
//
// pshScan points to previous symbol (since pshScan->oshNext == osh)
// unlink file
//
pshScan->oshNext = psh->oshNext;
}
}
/* RemoveFile - remove a file from the database
*
* If the file is in the database, enumerate all symbol references and
* remove them from the relevant symbols. Free the line block map and
* remove the file itself.
*
* We assume that a file is not indexed more than once. We remove only
* the first reference to a file on a symbol.
*
* psz name of file
*/
void RemoveFile (PSZ psz)
{
OFFSET ofil;
PFIL pfil;
OFFSET orefCurrent;
PREF pref;
PSYM psym;
PREF prefPrev;
OFFSET orefScan;
//
// find file record in database
//
pfil = pfilFind (psz, &ofil, FALSE);
//
// if the file is in the database
//
if (pfil != NULL) {
//
// while there are symbol references in the file
//
while (pfil->oref != (OFFSET)0) {
//
// address the reference and the symbol referenced
//
orefCurrent = pfil->oref;
pref = MAPREFERENCE (orefCurrent);
psym = MAPSYM (pref->osym);
//
// if the reference is the first one on the symbol, unlink reference
//
orefScan = psym->oref;
if (orefCurrent == orefScan)
psym->oref = pref->orefNext;
//
// otherwise, walk through the references finding one whose "next"
// pointer points to the reference to remove.
//
else {
while (orefCurrent != orefScan) {
prefPrev = MAPREFERENCE (orefScan);
orefScan = prefPrev->orefNext;
}
//
// prefPrev points to previous reference (since
// prefPref->orefNext == pfil->oref). Unlink reference
//
prefPrev->orefNext = pref->orefNext;
}
//
// unlink the reference from the file
//
pfil->oref = pref->orefFileNext;
//
// free symbol record
//
DBFree (pdbRef, orefCurrent, CBREF (pfil->cblk));
}
//
// if there's a block-to-line map array then free it
//
if (pfil->ompBlkLine != (OFFSET)0)
DBFree (pdbRef, pfil->ompBlkLine, pfil->cblk * sizeof (LINE));
pfil->ompBlkLine = (OFFSET)0;
pfil->cblk = 0;
//
// File has no more references nor block-to-line map. Unlink
// it from it's hash chain.
UnlinkSH ((PSH) pfil, ofil);
//
// Free the file record
//
DBFree (pdbSym, ofil, CBFIL (pfil->name.cch));
}
}
/* RemoveSym - remove a symbol from the database
*
* We locate the symbol. If it is found, we enumerate all references
* to it and remove the references from the relevant files. When
* all references are gone, we remove the symbol from it's hash bucket.
*
* psz PSZ of symbol name to remove
*/
void RemoveSym (PSZ psz)
{
OFFSET osym;
PSYM psym;
OFFSET orefCurrent;
PREF pref;
PFIL pfil;
PREF prefPrev;
OFFSET orefScan;
//
// find symbol record in database
//
psym = psymFind (psz, &osym, FALSE);
//
// if the symbol is in the database
//
if (psym != NULL) {
//
// while there are file references in the symbol
//
while (psym->oref != (OFFSET)0) {
//
// address the reference and the file referenced
//
orefCurrent = psym->oref;
pref = MAPREFERENCE (orefCurrent);
pfil = MAPFIL (pref->ofil);
//
// if the reference is the first one on the file, unlink reference
//
orefScan = pfil->oref;
if (orefCurrent == orefScan)
pfil->oref = pref->orefFileNext;
//
// otherwise, walk through the references finding a reference
// whose "next" pointer points to the reference to remove
//
else {
while (orefCurrent != orefScan) {
prefPrev = MAPREFERENCE (orefScan);
orefScan = prefPrev->orefFileNext;
}
//
// prefPrev points to previous reference (since
// prefPref->orefFileNext == pfil->oref). Unlink reference
//
prefPrev->orefFileNext = pref->orefFileNext;
}
//
// unlink the reference from the symbol
//
psym->oref = pref->orefNext;
//
// free reference record
//
DBFree (pdbRef, orefCurrent, CBREF (pfil->cblk));
}
//
// Symbol has no more references. Unlink
// it from it's hash chain.
//
UnlinkSH ((PSH) psym, osym);
//
// Free the symbol record
//
DBFree (pdbSym, osym, CBSYM (psym->name.cch));
}
}
/* SRSymLocate - find a symbol in some files using the database
*
* pfn routine for reply
* h handle for response
* apsz array of strings controlling what's to be found
* apsz[0] is symbol to find
* apsz[1] is -f for filename only, -a for all occurrences
* apsz[2] [OPTIONAL] is scope
*/
void SRSymLocate (PFNFIND pfn, HANDLE h, PSZ apsz[])
{
PSYM psym;
PREF pref;
OFFSET oref;
BOOL fFound = FALSE;
PFIL pfil;
psym = psymFind (apsz[0], &oref, FALSE);
if (psym != NULL) {
oref = psym->oref;
while (oref != 0L) {
pref = MAPREFERENCE (oref);
pfil = MAPFIL (pref->ofil);
//
// if a scope wasn't given or file is within scope
//
if (apsz[2] == NULL || strpre (apsz[2], pfil->name.sz))
//
// if filename-only report desired then send response
//
if (!strcmp (apsz[1], "-f"))
(*pfn) (h, pfil->name.sz);
else
if (!fSymFileFind (pfn, h, apsz[0], pref))
break;
oref = pref->orefNext;
}
}
(*pfn) (h, NULL);
}
/* fSymFileFind - find a symbol in a file given a reference
*
* pfn routine for reply
* h handle
* psz symbol
* pref pointer to reference
*
* returns TRUE if message send OK
*/
BOOL fSymFileFind (PFNFIND pfn, HANDLE h, PSZ psz, PREF pref)
{
FILE *fh;
PFIL pfil;
PLINE pvec;
PSZ pch;
char szmsg[CBMSG];
int iblk;
int cch;
LINE iline;
BOOL fOK = TRUE;
char szBuf[LINELEN];
cch = strlen (psz);
pfil = MAPFIL (pref->ofil);
pvec = MAPVECTOR (pfil->ompBlkLine);
fh = fopen (pfil->name.sz, "rb");
if (fh != NULL) {
for (iblk = 0; iblk < pfil->cblk; iblk++)
if (pref->bm[iblk >> 3] & (1 << (iblk & 0x0007))) {
fseek (fh, (long) iblk << BLKSHFT, 0);
if (pvec[iblk] & 0x8000)
fgetl (szBuf, LINELEN, fh);
iline = 0;
while ((ftell (fh) >> BLKSHFT) == iblk &&
fgetl (szBuf, LINELEN, fh)) {
pch = szBuf;
while (TRUE) {
/* skip to beginning of first symbol
*/
while (*pch && !iscsymf (*pch))
pch++;
if (*pch == '\0')
break;
/* does symbol match?
*/
if (!_strnicmp (pch, psz, cch) && !iscsym (pch[cch])) {
sprintf (szmsg, "%s %d %d: %s", pfil->name.sz,
1 + (pvec[iblk] & 0x7FFF) + iline,
1 + pch - szBuf, szBuf);
fOK = (*pfn) (h, szmsg);
if (!fOK)
goto done;
}
/* skip symbol */
while (*pch && iscsymf (*pch))
pch++;
}
iline++;
}
}
done:
fclose (fh);
}
return fOK;
}
/* EnSym - enumerate all symbols, calling a procedure on each one
*
* pfnen enumeration function to call
* pv pointer to vector of arguments to enumeration function
* typeSym type of symbol desired, TY_ALL means all
*/
void EnSym (PFNENUM pfnen, void * pv, ULONG typeSym)
{
HASH h;
OFFSET osh, oshNext;
PSH psh;
//
// for each bucket in hash table
//
for (h = 0L; h < SYMMAXHASH; h++) {
//
// find first contents of hash bucket
//
osh = * (OFFSET *) DBMap (pdbSym, OHASH (h));
//
// for each symbol in chain
//
while (osh != (OFFSET)0) {
//
// address the symbol
//
psh = MAPSH (osh);
//
// get link to next (since call to enum function may
// delete symbol
//
oshNext = psh->oshNext;
//
// if symbol is of the type we are looking for the call enumerator
//
if (typeSym == TY_ALL || psh->type == typeSym)
(*pfnen) (h, osh, psh, pv);
//
// step to next symbol in bucket
//
osh = oshNext;
}
}
}