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.
 
 
 
 
 
 

1000 lines
24 KiB

/*** SHsymlb1.c - common library routines to find an
* omf symbol by name or address.
*
* Copyright <C> 1988, Microsoft Corporation
*
* Purpose: To supply a concise interface to the debug omf for symbols
*
* Revision History:
*
* [00] 15-nov-91 DavidGra
*
* Suppress hashing when the SSTR_NoHash bit it set.
*
*
*
*
*************************************************************************/
#include "shinc.h"
#pragma hdrstop
#include <errno.h>
//**********************************************************************
//**********************************************************************
// This is project dependent stuff used in this module
// the following is local to this module ONLY! It is here to force
// existing behavior. Statics are promised to be zero filled by compiler
extern CHAR SHszDir[_MAX_CVDIR], SHszDrive[_MAX_CVDRIVE];
extern CHAR SHszDebuggeeDir[_MAX_CVDIR], SHszDebuggeeDrive[_MAX_CVDRIVE];
#ifdef NEVER // MOVED TO SOURCE LINE HANDLER
/*** SHLineFromADDR
*
* Purpose: Given a FLS, get the closest line.
*
* Input:
* pFLS - A packet in which the hMod and addr fields must be
* valid.
*
* Output:
* Returns Returns the closest line number or 0 if none. The remaining
* fields of the LFS are filled in appropriately.
*
* Notes: Returns 0 on error. Offsets are sorted per table by the C compiler.
*
*************************************************************************/
LS LOADDS PASCAL SHLineFromADDR ( LPFLS lpfls ) {
LPMDS lpmds;
WORD i;
SEGMENT seg;
WORD csle;
WORD lnNbr = 0;
LPSLT lpslt;
LPLOE lploe;
CV_uoff32_t off;
ADDR addr;
HEXE hexe;
LPEXS lpexs = NULL;
// because no symbol table may be larger than 64k, there can be a max
// of 64/4 = 16k entries in the line offset table because there are
// at least 4 bytes per entry. The index can be expressed with a signed short.
// which has a positive range of 32k, twice possible for the table
signed int low, high, mid;
// assume we don't find it
//assert (!ADDR_IS_LI (lpfls->addr));
addr = lpfls->addr;
seg = GetAddrSeg ( addr );
off = GetAddrOff ( addr );
lpfls->hFile = NULL;
lpfls->dOffset = CV_MAXOFFSET;
lpfls->line = 0;
lpmds = (LPMDS) ( lpfls->hMod ?
(LPMDS) LLLock ( lpfls->hMod ) :
(LPMDS) NULL
);
// only do this if I have omf information
if ( lpmds && lpmds->pSrcLn ) {
hexe = SHHexeFromHmod ( lpfls->hMod );
// get my table
lpslt = (LPSLT) lpmds->pSrcLn;
// search for all of the same segment and file name
csle = lpslt->csle;
for ( i = 0; i < csle; i++ ) {
if ((WORD)lpslt->rgsle[i].loeSeg == (WORD)seg &&
(long)off < (long)lpslt->rgsle[i].loeEnd &&
emiAddr ( addr ) == hexe ) {
// set up for the search routine
low = 0;
high = lpslt->rgsle[i].cloe - 1;
lploe = lpslt->rgsle[i].lploe;
// binary search for the offset
while ( low <= high ) {
mid = ( low + high ) / 2;
if (off < lploe [ mid ].offset) {
high = mid - 1;
}
else if ( off > lploe[mid].offset ) {
low = mid + 1;
}
else {
lpfls->hFile = (HFL) &lpslt->rgsle[i];
lpfls->line = lploe[mid].ln;
lpfls->dOffset = 0;
high = mid;
goto found;
}
}
// if we didn't find it, get the closet but earlier line
// high should be one less than low.
if( low && (off - lploe[high].offset) < lpfls->dOffset ) {
lpfls->dOffset = (UOFFSET) (off - lploe[high].offset);
lpfls->hFile = (HFL) &lpslt->rgsle[i];
lpfls->line = lploe[high].ln;
goto found;
}
}
}
}
found:
if ( lpfls->line != 0 ) {
if ( high < (int) (lpslt->rgsle[i].cloe - 1)) {
lpfls->cbLine = lploe [ high+1 ].offset - lploe[high].offset;
}
else {
lpfls->cbLine =
( lpmds->dm_raCode + lpmds->dm_cbCode ) - lploe[high].offset;
}
}
if ( lpmds ) {
LLUnlock ( lpfls->hMod );
}
return lpfls->line;
}
/*** SHResolve
*
* Purpose: To resolve to take a new address, or keep the current address
* in the lrb table
*
* Input:
* hFileBase - The Base hFile.
* hFileCur, - The Current hFile.
* hFileNew, - The New hFile.
* pAddrBase - The base address to compare to.
* pAddrCur - The currently assigned lrb.
* pAddrNew - A new lrb address, see if this is better.
*
* Output:
* Returns:
* TRUE if the New lrb should be assigned, FALSE if no action should
* be taken.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
static int PASCAL NEAR SHResolve (
HFL hFileBase,
HFL hFileCur,
HFL hFileNew,
ADDR *paddrBase,
ADDR *paddrCur,
ADDR *paddrNew ) {
CV_uoff32_t diffCur;
CV_uoff32_t diffNew;
// chose the one in my hFile
if( hFileBase != hFileCur &&
hFileBase == hFileNew ) {
return TRUE;
}
// chose with the same segment
if( GetAddrSeg ( *paddrBase ) != GetAddrSeg ( *paddrCur ) &&
GetAddrSeg ( *paddrBase ) == GetAddrSeg ( *paddrNew ) ) {
return TRUE;
}
// chose closer offset
if( GetAddrSeg ( *paddrBase ) == GetAddrSeg ( *paddrCur ) &&
GetAddrSeg ( *paddrCur ) == GetAddrSeg ( *paddrNew ) ) {
diffCur = ( GetAddrOff ( *paddrCur ) > GetAddrOff ( *paddrBase ) ) ?
( GetAddrOff ( *paddrCur ) - GetAddrOff ( *paddrBase ) ) :
( GetAddrOff ( *paddrBase ) - GetAddrOff ( *paddrCur ) );
diffNew = ( GetAddrOff ( *paddrNew ) > GetAddrOff ( *paddrBase ) ) ?
( GetAddrOff ( *paddrNew ) - GetAddrOff ( *paddrBase ) ) :
( GetAddrOff ( *paddrBase ) - GetAddrOff ( *paddrNew ) );
if ( diffNew < diffCur ) {
return TRUE;
}
}
return FALSE;
}
/*** SHplrbNext
*
* Purpose: given an lrb, get the next one in the list
*
* Input:
* pcxt - A pointer to any valid cxt with the proper module index.
* plrb - A pointer to the current lrb.
*
* Output:
* plrb - A pointer to the next lrb if one exists, if not, the
* contents of the lrb are left unchanged.
* sleEnd - This is one past last valid address in this sle. If 0
* returned, the lrb was invalid!
*
* Returns:
* A pointer to the next lrb if any. If no next lrb, a NULL is returned.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
LPLRB LOADDS PASCAL SHplrbNext ( PCXT pcxt, LPLRB plrb, LPW sleEnd ) {
LPMDS lpmds;
HMOD hmod;
LPSLT lpslt;
LPLRB plrbRet = (LPLRB)NULL;
*sleEnd = 0;
// see if we have another one.
// only do this if I have omf information
if( (hmod = pcxt->hMod) &&
(lpmds = (LPMDS)LLLock(hmod))->pSrcLn &&
(lpslt = (LPSLT) lpmds->pSrcLn) &&
plrb->isle < lpslt->csle ) {
*sleEnd = (WORD)lpslt->rgsle[plrb->isle].loeEnd;
if( (plrb->iloe + 1) < lpslt->rgsle[plrb->isle].cloe ) {
plrb->iloe++;
plrbRet = plrb;
}
}
if ( hmod ) {
LLUnlock( hmod );
}
return plrbRet;
}
/*** SHXlszGetFile
*
* Purpose: To take a HFL and return the file name associated with that
* HFL.
*
* Input:
* hFile - The hFile of the file name needed.
*
* Output:
* Returns:
* - A far pointer to the //path\filename. NULL if error.
*
* Exceptions:
*
* Notes:
* There are strange ( and maybe undesirable ) side effects to
* this proc. First the file returned is not the file specifed
* by the omf, it is the file composed by //souredir\filename.
* Then the omf dir, then the current working directory, then
* the dir that cvp was executed from.
* If the omf record is searched and fails to open the file,
* the found path will be substituted. This is so the next time
* them omf record will pass. The behavior was copied from the
* original routine find_file.
*
*************************************************************************/
LSZ LOADDS PASCAL SHXlszGetFile ( HFL hFile ) {
static CHAR szPath [ _MAX_CVPATH ];
static CHAR szFile [ _MAX_CVFNAME ];
static CHAR szExt [ _MAX_CVEXT ];
CHAR FAR * szPathOMF;
PCH pch;
struct stat statInfo;
LPSLE lpsle;
if ( !hFile )
return NULL;
// split the name up
lpsle = (LPSLE) hFile;
szPathOMF = lpsle->pifl->lszFileName;
SHSplitPath ( szPathOMF, NULL, NULL, szFile, szExt );
// now go thru the search order and recompose paths
// try SHszDir (the cached dir)
pch = szPath;
_makepath ( szPath, SHszDrive, SHszDir, szFile, szExt );
if( !(*SHszDrive || *SHszDir) ||
stat ( pch, &statInfo ) ||
!(statInfo.st_mode & S_IFREG) ) {
// try exe path
pch = szPath;
_makepath ( szPath,
SHszDebuggeeDrive,
SHszDebuggeeDir,
szFile,
szExt );
if( !( *SHszDebuggeeDrive || *SHszDebuggeeDir ) ||
stat(pch, &statInfo) ||
!(statInfo.st_mode & S_IFREG) ) {
// try OMF path
pch = szPathOMF;
if( stat ( pch, &statInfo ) || !(statInfo.st_mode & S_IFREG) ) {
// try current dir
pch = szPath;
_makepath ( szPath, NULL, NULL, szFile, szExt );
if ( stat ( pch, &statInfo) || !(statInfo.st_mode & S_IFREG) ) {
// everyone failed, so return NULL
//errno = errnoT;
return NULL;
}
}
}
}
// preserve the errno
// errno = errnoT;
// at this point we know that we have a path, therefore pch may not
// be NULL
// if this is different than the omf path, allocate a new block and
// save the path there, update the omf path to this one
if ( pch != szPathOMF && _ftcsicmp ( pch, szPathOMF ) ) {
// free the old memory area
MHFree ( lpsle->pifl->lszFileName );
// allocate some new space and copy the name
lpsle->pifl->lszFileName = STRDUP ( pch );
lpsle->pifl->SrcFlags.fFarFreeName = FALSE;
// Invalidate the file length
lpsle->pifl->cLnInFile = 0;
}
// return a pointer to the filename, we always know that the omf path
// will have this name, it was stored there
return lpsle->pifl->lszFileName;
}
/*** SHGetLineInfo
*
* Purpose: Given an lrb, get seg, offset, ovl, and line associated
* with that lrb handle.
*
* Input:
* pcxt - A pointer to any of the files cxt with the proper
* module index.
* plrb - A pointer to a valid lrb.
*
* Output:
* paddr - A pointer to an address pkt to contain the segment and
* offset.
* pLn - A pointer to an unsigned short to put the line number.
*
* Returns:
* TRUE if the lrb was found, FALSE if error
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
int LOADDS PASCAL SHGetLineInfo ( PCXT pcxt, LPLRB plrb, LPADDR paddr, LPW pLn ) {
LPMDS lpmds;
HMOD hmod;
LPSLT lpslt;
LPLOE lploe;
WORD fRet = FALSE;
//assert (ADDR_IS_LI (*paddr));
// only do this if I have omf information
if ( (hmod = pcxt->hMod ) &&
(lpmds = (LPMDS)LLLock(hmod))->pSrcLn &&
(lpslt = (LPSLT) lpmds->pSrcLn) &&
plrb->isle < lpslt->csle &&
plrb->iloe < lpslt->rgsle[plrb->isle].cloe ) {
// get the segment
SetAddrSeg ( paddr , lpslt->rgsle[plrb->isle].loeSeg );
// get the emi
paddr->emi = pcxt->addr.emi;
// load the lploe table
lploe = lpslt->rgsle[plrb->isle].lploe;
// load the rest of the information
SetAddrOff ( paddr , (UOFFSET)lploe[plrb->iloe].offset );
*pLn = lploe[plrb->iloe].ln;
ADDR_IS_LI (*paddr) = TRUE;
fRet = TRUE;
}
if ( hmod ) {
LLUnlock( hmod );
}
return fRet;
}
/*** SHGetfip
*
* Purpose: To get information about an HFL
*
* Input:
* hFile - An HFL representing the requested file info.
*
* Output:
* pfip - A pointer to a fip to be filled in.
* Returns:
*
* Exceptions:
*
* Notes:
* The Seg, oStart, oEnd is unique to the HFL. While cLnInFile,
* SrcFlags, szFileName are unique to the file name within any
* one compiled unit (the module).
*
* On return, if there are no line offset associated with the
* valid, oStart == oEnd. However the value will be random.
*
* If nothing could be filled in (NULL hFile), a zeroed fip is
* returned.
*
*************************************************************************/
void LOADDS PASCAL SHGetfip( HFL hFile, LPFIP pfip ) {
LPSLE lpsle;
// clear the packet out
MEMSET ( pfip, 0, sizeof (FIP) );
// if we have a file handle, fill in the file info.
if ( hFile != NULL ) {
lpsle = (LPSLE) hFile;
// load up the fip
pfip->Seg = lpsle->loeSeg;
if ( lpsle->cloe ) {
pfip->oStart = lpsle->lploe->offset;
}
else {
pfip->oStart = lpsle->loeEnd;
}
pfip->oEnd = lpsle->loeEnd;
pfip->cLnInFile = lpsle->pifl->cLnInFile;
pfip->SrcFlags = lpsle->pifl->SrcFlags;
pfip->lszFileName = lpsle->pifl->lszFileName;
}
}
/*** SHSetfip
*
* Purpose: To set information about an HFL
*
* Input:
* hFile - An HFL representing the file info.
* pfip - A pointer to a fip containing the new file info.
*
* Output:
* Returns:
*
* Exceptions:
*
* Notes:
* The Seg, oStart, oEnd is unique to the HFL. While cLnInFile,
* SrcFlags, lszFileName are unique to the file name within any
* one compiled unit (the module).
*
* If the infomation can't be set, the set will not take place.
* No warning is given in this case.
*
* This can be a very dangerous call. It is recommend that
* a SHGetfip be used to initialize the fip. Then modifing only
* the fields that need to be changed. Then call SHSetfip.
*
*************************************************************************/
void LOADDS PASCAL SHSetfip ( HFL hFile, LPFIP pfip ) {
LPSLE lpsle;
// if we have a file handle, fill in the file info.
if ( hFile ) {
lpsle = (LPSLE) hFile;
// load up the fip
lpsle->loeSeg = pfip->Seg;
if ( lpsle->cloe ) {
lpsle->lploe->offset = pfip->oStart;
}
lpsle->loeEnd = pfip->oEnd;
lpsle->pifl->cLnInFile = pfip->cLnInFile;
lpsle->pifl->SrcFlags = pfip->SrcFlags;
lpsle->pifl->lszFileName = pfip->lszFileName;
}
}
/*** SHlrbToHFL
*
* Purpose: To convert an lrb to an HFL (hFile).
*
* Input:
* hmod - an HMOD that describes the module of the lrb
* plrb - an lrb than the desired HFL should be made from
*
* Output:
* Returns:
* The HFL, or NULL on error.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
HFL LOADDS PASCAL SHlrbToHFL ( HMOD hmod, LPLRB plrb ) {
LPSLT lpslt;
LPMDS lpmds;
// go get the Source Line Entry pointed to, make that an HFL
if ( hmod ) {
lpmds = LLLock ( hmod );
lpslt = (LPSLT) lpmds->pSrcLn;
LLUnlock( hmod );
if ( lpslt ) {
return &lpslt->rgsle [ plrb->isle ];
}
}
return NULL;
}
/*** SHXlasFill
*
* Purpose: Given a context, lookup the address offset.
*
* Input:
* pcxt - A pointer to a cxt containing the module for the source
* lines. Any module entry with the proper module index
* will work
* plas - A pointer to a las structure, with the first line to search
* for initialized in plas->ln and the number of line to
* include there after in plas->clrb. Note that rglrb[] must
* be large enough for plas->clrb entries.
*
* Output:
* Returns Returns a filled las, lines that couldn't be found will be
* denoted with a NULL entry in plas->rglrb[x].pslt.
*
* Exceptions:
*
* Notes: There must be room for at least one lrb in the las!
*
*************************************************************************/
void LOADDS PASCAL SHXlasFill ( PCXT pcxt, HFL hFile, LPLAS plas ) {
HMOD hmod;
LPMDS lpmds;
WORD i;
WORD j;
WORD ilrb;
WORD csle;
WORD cloe;
WORD clrb;
LPSLT lpslt;
LPSLE lpsle;
LPLOE lploe;
LSZ lszBaseName;
WORD lnStart;
WORD lnEnd;
ADDR addrBase = {0};
ADDR addrCur = {0};
ADDR addrNew = {0};
HEXE hexe;
LPEXS lpexs;
// clear the users lrb's
MEMSET ( plas->rglrb, 0xFF, plas->clrb * sizeof ( LRB ) );
// only do this if I have omf information
if ( hFile != NULL ) {
lpsle = (LPSLE) hFile;
lszBaseName = lpsle->pifl->lszFileName;
SetAddrSeg ( &addrBase , lpsle->loeSeg );
ADDR_IS_LI (addrBase) = TRUE;
if ( lpsle->cloe != 0 ) {
SetAddrOff ( &addrBase , (UOFFSET)lpsle->lploe->offset );
}
else {
SetAddrOff ( &addrBase , 0 );
}
hmod = pcxt->hMod;
lpmds = hmod ? LLLock ( hmod ) : NULL;
if ( hmod ) {
hexe = SHHexeFromHmod( hmod );
}
if ( lszBaseName && lpmds->pSrcLn ) {
// get module level stuff for conflict resolution
if ( lpexs ) {
emiAddr ( addrBase ) = hexe;
emiAddr ( addrCur ) = hexe;
emiAddr ( addrNew ) = hexe;
}
ADDR_IS_LI (addrNew) = TRUE;
ADDR_IS_LI (addrCur) = TRUE;
// get my slt table
lpslt = (LPSLT) lpmds->pSrcLn;
// only look at this file in the module
clrb = plas->clrb;
lnStart = plas->ln;
lnEnd = lnStart + clrb;
// search all tables for this file name
csle = lpslt->csle;
for( i = 0; i < csle; i++ ) {
if( lpslt->rgsle[i].pifl->lszFileName == lszBaseName ) {
// set up for the search routine
cloe = lpslt->rgsle[i].cloe;
lploe = lpslt->rgsle[i].lploe;
// seek this inner table
for ( j = 0; j < cloe; j++, lploe++ ) {
if( lnStart <= lploe->ln &&
lploe->ln < lnEnd ) {
// ok we found one, save away the stuff required
// to get back here quickly
ilrb = lploe->ln - lnStart;
// see if we have a collision
if(plas->rglrb[ilrb].isle < csle) {
// get the current segment and offset
SetAddrSeg ( &addrCur ,
lpslt->rgsle[plas->rglrb[ilrb].isle].loeSeg );
SetAddrOff ( &addrCur ,
(UOFFSET)lpslt->rgsle[plas->rglrb[ilrb].isle].lploe[plas->rglrb[ilrb].iloe].offset );
// get the suggested segment and offset
SetAddrSeg ( &addrNew , lpslt->rgsle[i].loeSeg );
SetAddrOff ( &addrNew , (UOFFSET)lploe->offset );
// resolve whether to take new or old loe??
if( SHResolve ( hFile,
(HFL) &lpslt->rgsle[plas->rglrb[ilrb].isle],
&lpslt->rgsle[i],
&addrBase,
&addrCur,
&addrNew) ) {
plas->rglrb[ilrb].isle = i;
plas->rglrb[ilrb].iloe = j;
}
}
// yes we want the new line number
else {
plas->rglrb[ilrb].isle = i;
plas->rglrb[ilrb].iloe = j;
}
}
}
}
}
if ( hmod ) {
LLUnlock( hmod );
}
}
}
}
HFL LOADDS PASCAL SHGETMODHFL ( HMOD hmod ) {
HFL hfl = ((LPMDS)LLLock(hmod))->hFile;
LLUnlock( hmod );
return hfl;
}
/*** SHGetSourceName
*
* Purpose: To return a source root.exe name given a hFile
*
* Input:
* hFile - A handle to the file pointer.
* pch - A pointer to where the source name is to be copied.
*
* Output:
* Returns .....
* pch if copied, NULL terminated string otherwise
*
* Exceptions:
*
* Notes: A very expensive call for what it does.
*
*************************************************************************/
LSZ LOADDS PASCAL SHGetSourceName ( HFL hFile, LPCH lpch ) {
char fname[_MAX_CVFNAME];
char ext[_MAX_CVEXT];
LPSLE lpsle;
*lpch = '\0';
// if there is a source file, get the file and extension
if ( hFile && (lpsle = (LPSLE) hFile ) ) {
SHSplitPath ( lpsle->pifl->lszFileName, NULL, NULL, fname, ext );
_ftcscpy ( lpch, fname );
_ftcscat ( lpch, ext );
}
return lpch;
}
SFG LOADDS PASCAL SHSrcFlag ( HMOD hmod ) {
SFG sfg;
LPMDS lpmds;
lpmds = LLLock( hmod );
sfg = ( ( LPSLT ) lpmds->pSrcLn )->rgsle[0].pifl->SrcFlags;
LLUnlock( hmod );
return sfg;
}
LPSLT LOADDS PASCAL SHGETSRC ( HMOD hmod ) {
LPSLT lpslt = ((LPMDS)LLLock(hmod))->pSrcLn;
LLUnlock( hmod );
return lpslt;
}
BOOL LOADDS PASCAL SHModHasSrc ( HMOD hmod ) {
BOOL fRet = ((LPMDS)LLLock(hmod))->pSrcLn != (LPSLT)NULL;
LLUnlock( hmod );
return fRet;
}
#endif // MOVED TO SOURCE LINE HANDLER
BOOL LOADDS PASCAL SHCanDisplay ( HSYM hsym ) {
switch ( ( (SYMPTR) hsym)->rectyp ) {
case S_REGISTER:
case S_CONSTANT:
case S_BPREL16:
case S_LDATA16:
case S_GDATA16:
case S_PUB16:
case S_BPREL32:
case S_REGREL32:
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
case S_PUB32:
return TRUE;
default:
return FALSE;
}
}
/*** SHlszGetSymName
*
* Purpose: To return a pointer to the length prefixed symbol name.
*
* Input:
* lpSym - The pointer to the symbol, this must not be a tag
*
* Output:
* Returns .....
* - a far pointer to the length prefixed name or NULL.
*
* Exceptions:
*
* Notes:
*
*************************************************************************/
LPB PASCAL SHlszGetSymName( SYMPTR lpSym ) {
WORD fSkip;
if ( !lpSym ) {
return NULL;
}
switch (lpSym->rectyp) {
case S_COMPILE: // [00]
return NULL; // [00]
case S_REGISTER:
return ((REGPTR) lpSym)->name;
case S_UDT:
case S_COBOLUDT:
return ((UDTPTR) lpSym)->name;
case S_CONSTANT:
fSkip = offsetof (CONSTSYM, name);
if (((CONSTPTR)lpSym)->value >= LF_CHAR) {
switch(((CONSTPTR)lpSym)->value) {
case LF_CHAR:
fSkip += sizeof (CHAR);
break;
case LF_SHORT:
case LF_USHORT:
fSkip += sizeof (WORD);
break;
case LF_LONG:
case LF_ULONG:
case LF_REAL32:
fSkip += sizeof (LONG);
break;
case LF_REAL64:
fSkip += 8;
break;
case LF_REAL80:
fSkip += 10;
break;
case LF_REAL128:
fSkip += 16;
break;
case LF_VARSTRING:
fSkip += ((lfVarString FAR *)&(((CONSTPTR)lpSym)->value))->len +
sizeof (((lfVarString FAR *)&(((CONSTPTR)lpSym)->value))->len);
break;
default:
assert (FALSE);
break;
}
}
return ((LPB)lpSym) + fSkip;
case S_BPREL16:
return ((BPRELPTR16)lpSym)->name;
case S_LDATA16:
case S_GDATA16:
case S_PUB16:
return ((DATAPTR16)lpSym)->name;
case S_LABEL16:
return ((LABELPTR16) lpSym)->name;
case S_LPROC16:
case S_GPROC16:
//case S_ENTRY:
return ((PROCPTR16) lpSym)->name;
case S_BLOCK16:
return ((BLOCKPTR16)lpSym)->name;
case S_BPREL32:
return ((BPRELPTR32)lpSym)->name;
case S_REGREL32:
return ((LPREGREL32)lpSym)->name;
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
case S_PUB32:
return ((DATAPTR32)lpSym)->name;
case S_LABEL32:
return ((LABELPTR32) lpSym)->name;
case S_LPROC32:
case S_GPROC32:
//case S_ENTRY:
return ((PROCPTR32) lpSym)->name;
case S_LPROCMIPS:
case S_GPROCMIPS:
return ((PROCPTRMIPS) lpSym)->name;
case S_BLOCK32:
return ((BLOCKPTR32)lpSym)->name;
}
return NULL;
}
// Nasty source line stuff - get rid of it sooooooon
/*** SHSetUserDir
*
* Purpose: To initialize SHszDir[_MAX_CVDIR] and SHszDrive[_MAX_CVDRIVE]
* to the specified path.
*
* Input:
* szDir - The pointer to the new directory
*
* Output:
* Returns:
*
* Exceptions:
*
* Notes: szDir may not exceed _MAX_CVDIR
*
*************************************************************************/
void LOADDS PASCAL SHSetUserDir ( LSZ lszDir ) {
LPCH lpch;
// skip white space
lpch = lszDir;
while ( *lpch && _istspace ( *lpch ) ) {
lpch = _ftcsinc( lpch );
}
// process the drive
SHszDrive[ 0 ] = 0;
if ( *lpch && lpch[1] == ':' ) {
SHszDrive[0] = *lpch;
SHszDrive[1] = ':';
SHszDrive[2] = '\0';
lpch += 2; // point past the :
}
_ftcscpy ( SHszDir, lpch );
}