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.
 
 
 
 
 
 

6674 lines
224 KiB

/*** DEBSYM.C - symbol lookup routines for expression evaluator
*
*
*/
extern bool_t FNtsdEvalType;
// enum specifying return from IsDominated
typedef enum {
DOM_ambiguous,
DOM_keep,
DOM_replace
} DOM_t;
// Return values from SearchClassName
typedef enum {
SCN_error, // error, abort search
SCN_notfound, // not found
SCN_found, // found
SCN_rewrite // found and this pointer inserted
} SCN_t;
// Return values from MatchMethod
typedef enum {
MTH_error, // error - abort search
MTH_found // found without error
} MTH_t;
typedef struct HSL_restart_t {
search_t Name;
HSYM hSym;
HSYML_t state;
ushort mask;
} HSL_restart_t;
static char *vtabptr = "#vptr#";
static HDEP hSymClass = 0;
static psymclass_t pSymClass = NULL;
static HDEP hVBDom = 0;
static pdombase_t pVBDom = NULL;
static HDEP hVBSearch = 0;
static pdombase_t pVBSearch = NULL;
static psearch_t pNameFirst = NULL;
LOCAL pnode_t AddETConst (pnode_t, OFFSET, CV_typ_t);
LOCAL pnode_t AddETExpr (pnode_t, CV_typ_t, OFFSET, OFFSET, CV_typ_t);
LOCAL pnode_t AddETInit (pnode_t, CV_typ_t);
LOCAL bool_t AddHSYM (psearch_t, HSYM, PHSL_HEAD, uint);
LOCAL SCN_t AddVBList (psymclass_t, pdombase_t *, HDEP *);
LOCAL SCN_t AddVBType (pdombase_t *, HDEP *, CV_typ_t);
LOCAL ushort AmbFromList (psearch_t);
LOCAL bool_t AmbToList (psearch_t);
LOCAL HR_t ClAmbToList (psearch_t);
LOCAL bool_t DebLoadConst (peval_t, CONSTPTR, HSYM);
LOCAL SCN_t DupSymCl (psearch_t);
LOCAL SCN_t FindIntro (psearch_t);
LOCAL SCN_t GenQualExpr (psearch_t);
LOCAL HDEP GenQualName (psearch_t, psymclass_t);
LOCAL bool_t GrowTMList (void);
LOCAL SCN_t IncrSymBase (void);
LOCAL bool_t InitMod (psearch_t);
LOCAL DOM_t IsDominated (psymclass_t, psymclass_t);
LOCAL bool_t IsIntroVirt (ushort, CV_typ_t, ushort *);
LOCAL bool_t LineNumber (psearch_t);
LOCAL void MatchArgs (peval_t, psearch_t, CV_fldattr_t, UOFFSET, bool_t);
LOCAL HR_t __fastcall MatchFunction (psearch_t);
LOCAL void MoveSymCl (HDEP hSymCl);
LOCAL SCN_t OverloadToAmbList (psearch_t, psymclass_t);
LOCAL SCN_t MethodsToAmbList (psearch_t, psymclass_t);
LOCAL bool_t ParseRegister (psearch_t);
LOCAL void PurgeAmbCl (psearch_t);
LOCAL SCN_t RecurseBase (psearch_t, CV_typ_t, CV_typ_t, OFFSET, OFFSET, CV_fldattr_t, bool_t);
LOCAL SCN_t RemoveAmb (psearch_t);
LOCAL SCN_t SearchBases (psearch_t);
LOCAL SCN_t SearchBType (psearch_t);
LOCAL SCN_t SearchClassName (psearch_t);
LOCAL bool_t SearchQualName (psearch_t, psymclass_t, HDEP, bool_t);
LOCAL SCN_t SearchRoot (psearch_t);
LOCAL SCN_t SetBase (psearch_t, CV_typ_t, CV_typ_t, OFFSET, OFFSET, CV_fldattr_t, bool_t);
LOCAL SCN_t SetBPValue (psearch_t);
LOCAL SCN_t SetValue (psearch_t);
LOCAL HR_t SymAmbToList (psearch_t);
LOCAL bool_t SymToNode (psearch_t);
LOCAL bool_t VBSearched (CV_typ_t);
LOCAL bool_t VBaseFound (psearch_t);
LOCAL CV_typ_t SkipModifiers(HMOD, CV_typ_t);
LOCAL bool_t CheckDupAmb ( psearch_t );
LOCAL bool_t __fastcall InsertThis (psearch_t);
LOCAL MTH_t MatchMethod (psearch_t, psymclass_t);
__inline BOOL
getBaseDefnFromDecl(
CV_typ_t typeIn,
peval_t pv,
CV_typ_t* ptypeOut)
{
peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
Unreferenced (pv);
return getDefnFromDecl (typeIn, pvBase, ptypeOut);
}
__inline unsigned char
SkipPad(
unsigned char *pb)
{
if (*pb >= LF_PAD0) {
// there is a pad field
return(*pb & 0x0f);
}
return(0);
}
OPNAME OpName[] = {
{"\x004""this"}, // OP_this
{"\x00b""operator->*"}, // OP_Opmember
{"\x00b""operator>>="}, // OP_Orightequal
{"\x00b""operator<<="}, // OP_Oleftequal
{"\x00a""operator()"}, // OP_Ofunction
{"\x00a""operator[]"}, // OP_Oarray
{"\x00a""operator+="}, // OP_Oplusequal
{"\x00a""operator-="}, // OP_Ominusequal
{"\x00a""operator*="}, // OP_Otimesequal
{"\x00a""operator/="}, // OP_Odivequal
{"\x00a""operator%="}, // OP_Opcentequal
{"\x00a""operator&="}, // OP_Oandequal
{"\x00a""operator^="}, // OP_Oxorequal
{"\x00a""operator|="}, // OP_Oorequal
{"\x00a""operator<<"}, // OP_Oshl
{"\x00a""operator>>"}, // OP_Oshr
{"\x00a""operator=="}, // OP_Oequalequal
{"\x00a""operator!="}, // OP_Obangequal
{"\x00a""operator<="}, // OP_Olessequal
{"\x00a""operator>="}, // OP_Ogreatequal
{"\x00a""operator&&"}, // OP_Oandand
{"\x00a""operator||"}, // OP_Ooror
{"\x00a""operator++"}, // OP_Oincrement
{"\x00a""operator--"}, // OP_Odecrement
{"\x00a""operator->"}, // OP_Opointsto
{"\x009""operator+"}, // OP_Oplus
{"\x009""operator-"}, // OP_Ominus
{"\x009""operator*"}, // OP_Ostar
{"\x009""operator/"}, // OP_Odivide
{"\x009""operator%"}, // OP_Opercent
{"\x009""operator^"}, // OP_Oxor
{"\x009""operator&"}, // OP_Oand
{"\x009""operator|"}, // OP_Oor
{"\x009""operator~"}, // OP_Otilde
{"\x009""operator!"}, // OP_Obang
{"\x009""operator="}, // OP_Oequal
{"\x009""operator<"}, // OP_Oless
{"\x009""operator>"}, // OP_Ogreater
{"\x009""operator,"}, // OP_Ocomma
{"\x012""operator new"}, // OP_Onew
{"\x015""operator delete"} // OP_Odelete
};
extern char Suffix;
// Symbol searching and search initialization routines
/** InitSearchBase - initialize search for base class
*
* InitSearchBase (bnOp, typD, typ, pName, pv)
*
* Entry bnOp = based pointer to OP_cast node
* bn = based pointer to cast string
* typD = type of derived class
* typB = type of desired base class
* pName = pointer to symbol search structure
* pv = pointer to value node
*
* Exit search structure initialized for SearchSym
*
* Returns pointer to search symbol structure
*/
void
InitSearchBase (
bnode_t bnOp,
CV_typ_t typD,
CV_typ_t typB,
psearch_t pName,
peval_t pv
)
{
// set starting context for symbol search to current context
_fmemset (pName, 0, sizeof (*pName));
pName->initializer = INIT_base;
pName->pv = pv;
pName->typeIn = typD;
pName->typeOut = typB;
pName->scope = SCP_class;
pName->CXTT = *pCxt;
pName->bn = 0;
pName->bnOp = bnOp;
pName->state = SYM_bclass;
pName->CurClass = typD;
}
/** InitSearchtDef - initialize typedef symbol search
*
* InitSearctDef (pName, iClass, tDef, scope, clsmask)
*
* Entry iClass = initial class if explicit class reference
* tDef = index of typedef
* scope = mask describing scope of search
* clsmask = mask describing permitted class elements
*
* Exit search structure initialized for SearchSym
*
* Returns pointer to search symbol structure
*/
void
InitSearchtDef (
psearch_t pName,
peval_t pv,
ushort scope
)
{
char NullString = 0;
// set starting context for symbol search to current context
_fmemset (pName, 0, sizeof (*pName));
pName->initializer = INIT_tdef;
pName->sstr.lpName = &NullString;
pName->sstr.cb = 0;
pName->pfnCmp = TDCMP;
pName->scope = scope;
pName->CXTT = *pCxt;
pName->pv = pv;
pName->typeIn = EVAL_TYP (pv);
pName->sstr.searchmask |= SSTR_symboltype | SSTR_NoHash;
pName->sstr.symtype = S_UDT;
pName->state = SYM_init;
}
/** SearchCFlag - initialize compile flags symbol search
*
* SearchCFlag (pName, iClass, scope, clsmask)
*
* Entry pName = pointer to symbol search structure
*
* Exit search structure initialized for SearchSym
*
* Returns pointer to search symbol structure
*/
HSYM
SearchCFlag (
void
)
{
search_t Name;
CXT CXTTOut;
// set starting context for symbol search to current context
_fmemset (&Name, 0, sizeof (Name));
Name.pfnCmp = CSCMP;
Name.CXTT = *pCxt;
Name.sstr.searchmask |= SSTR_symboltype;
Name.sstr.symtype = S_COMPILE;
if (InitMod (&Name) == TRUE) {
SHGetCxtFromHmod (Name.hMod, &Name.CXTT);
if ((Name.hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
(LPSSTR)&Name, pExState->state.fCase,
Name.pfnCmp,
&CXTTOut)) != 0) {
return (Name.hSym);
}
}
// error in context initialization or compile flag symbol not found
return (0);
}
/** SetAmbiant - set ambiant code or data model
*
* mode = SetAmbiant (flag)
*
* Entry flag = TRUE if ambiant data model
* flag = FALSE if ambiant code model
*
* Exit none
*
* Returns ambiant model C7_... from the compile flags symbol
* if the compile flags symbol is not found, C7_NEAR is returned
*/
CV_ptrmode_e
SetAmbiant (
bool_t isdata
)
{
HSYM hCFlag;
CFLAGPTR pCFlag;
CV_ptrmode_e mode;
Unreferenced( isdata );
if ((hCFlag = SearchCFlag ()) == 0) {
// compile flag symbol not found, set model to near
mode = (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) ? CV_PTR_NEAR32 : CV_PTR_NEAR;
}
else {
pCFlag = MHOmfLock ((HDEP)hCFlag);
switch (pCFlag->flags.ambdata) {
default:
DASSERT (FALSE);
case CV_CFL_DNEAR:
// NOTENOTE Compiler is always sending us this one...
// convert it to something appropriate sounding.
mode = (ADDR_IS_OFF32(*SHpADDRFrompCXT(pCxt))) ? CV_PTR_NEAR32 : CV_PTR_NEAR;
break;
case CV_CFL_DFAR:
mode = CV_PTR_FAR;
break;
case CV_CFL_DHUGE:
mode = CV_PTR_HUGE;
break;
}
MHOmfUnLock ((HDEP)hCFlag);
}
return (mode);
}
/** GetHSYMList - get HSYM list for context
*
* status = EEGetHSYMList (phSYMl, pCXT, mask, pRE, fEnableProlog)
*
* Entry phSYML = pointer to handle to symbol list
* pCXT = pointer to context
* mask = selection mask
* pRE = pointer to regular expression
* fEnableProlog = FALSE if function scoped symbols only after prolog
* fEnableProlog = TRUE if function scoped symbols during prolog
*
* Exit *phMem = handle for HSYM list buffer
*
* Returns EENOERROR if no error
* status code if error
*/
EESTATUS
GetHSYMList (
HDEP *phSYML,
PCXT pCxt,
ushort mask,
uchar *pRE,
SHFLAG fEnableProlog
)
{
search_t Name = {0};
CXT CXTTOut;
HSYM hSym = 0;
PHSL_HEAD pHSLHead;
HSYML_t state;
HSL_restart_t *pRestart;
bool_t fRestart;
bool_t isprolog;
bool_t fCaseSensitive = TRUE;
if (mask & HSYMR_nocase) {
mask &= ~HSYMR_nocase;
fCaseSensitive = FALSE;
}
if (*phSYML == 0) {
// allocate and initialize buffer
if ((*phSYML = MHMemAllocate (HSYML_SIZE)) == 0) {
return (EECATASTROPHIC);
}
pHSLHead = MHMemLock (*phSYML);
_fmemset (pHSLHead, 0, HSYML_SIZE);
pHSLHead->size = HSYML_SIZE;
pHSLHead->blockcnt = 1;
pHSLHead->remaining = HSYML_SIZE - sizeof ( HSL_HEAD );
pHSLHead->pHSLList = (PHSL_LIST)(((uchar *)pHSLHead) + sizeof (HSL_HEAD));
state = HSYML_lexical;
Name.initializer = INIT_RE;
Name.pfnCmp = FNCMP;
Name.sstr.searchmask |= SSTR_RE;
Name.CXTT = *pCxt;
Name.hMod = pCxt->hMod;
if ( pCxt->hMod ) {
Name.hExe = SHHexeFromHmod ( pCxt->hMod );
}
else {
// not valid to call SHHexeFromHmod with an Hmod of 0,
// so set Hexe explicitly
Name.hExe = 0;
}
if ( pRE && *pRE ) {
Name.sstr.pRE = pRE;
}
fRestart = FALSE;
}
else {
pHSLHead = MHMemLock (*phSYML);
pRestart = MHMemLock (pHSLHead->restart);
Name = pRestart->Name;
mask = pRestart->mask;
state = pRestart->state;
hSym = pRestart->hSym;
pHSLHead->blockcnt = 1;
pHSLHead->symbolcnt = 0;
pHSLHead->remaining = HSYML_SIZE - sizeof ( HSL_HEAD );
pHSLHead->pHSLList = (PHSL_LIST)(((uchar *)pHSLHead) + sizeof (HSL_HEAD));
MHMemUnLock (pHSLHead->restart);
_fmemset ((uchar *)pHSLHead + sizeof (HSL_HEAD), 0,
HSYML_SIZE - sizeof (HSL_HEAD));
AddHSYM (&Name, hSym, pHSLHead, state);
fRestart = TRUE;
Name.hSym = hSym;
}
switch (state) {
case HSYML_lexical:
if (mask & HSYMR_lexical) {
// search up the lexical scope to but not including the
// function level
while (SHIsCXTBlk (&Name.CXTT)) {
while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
(LPSSTR)&Name, fCaseSensitive, FNCMP, &CXTTOut)) != 0) {
if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_lexical) == FALSE) {
goto hsyml_exit;
}
Name.hSym = hSym;
}
// go to the parent scope
SHGoToParent (&Name.CXTT, &CXTTOut);
// reset current symbol
Name.CXTT = CXTTOut;
Name.hSym = 0;
}
mask &= ~HSYMR_lexical;
}
case HSYML_function:
if (mask & HSYMR_function) {
if (fRestart == FALSE) {
Name.hSym = 0;
Name.CXTT.hBlk = 0;
}
fRestart = FALSE;
state = HSYML_function;
if ( Name.CXTT.hMod != 0 ) {
isprolog = SHIsInProlog (&Name.CXTT);
}
while (!SHIsCXTMod (&Name.CXTT) && Name.CXTT.hMod != 0) {
while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
(LPSSTR)&Name, fCaseSensitive, FNCMP, &CXTTOut)) != 0) {
if ((isprolog == TRUE) && (fEnableProlog == FALSE)) {
// we want to reject bp_relative and register
// stuff if we are in the prolog or epilog of
// a function
if ((Name.lastsym != S_BPREL16) &&
(Name.lastsym != S_BPREL32) &&
(Name.lastsym != S_REGISTER)) {
if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_function) == FALSE) {
goto hsyml_exit;
}
}
}
else {
if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_function) == FALSE) {
goto hsyml_exit;
}
}
Name.hSym = hSym;
}
// go to the parent scope
SHGoToParent (&Name.CXTT, &CXTTOut);
// reset current symbol
Name.CXTT = CXTTOut;
Name.hSym = 0;
}
mask &= ~HSYMR_function;
}
case HSYML_class:
if (mask & HSYMR_class) {
if (fRestart == FALSE) {
Name.hSym = 0;
if (ClassImp != 0) {
Name.CurClass = ClassImp;
}
}
fRestart = FALSE;
if ((Name.CurClass != 0)) {
DASSERT (FALSE);
// need to do equivalent of EEGetChild on this
}
mask &= ~HSYMR_class;
}
case HSYML_module:
if (mask & HSYMR_module) {
if (fRestart == FALSE) {
SHGetCxtFromHmod (Name.hMod, &Name.CXTT);
Name.hSym = 0;
}
fRestart = FALSE;
Name.state = HSYML_module;
while ((hSym = SHFindNameInContext (Name.hSym, &Name.CXTT,
(LPSSTR)&Name, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) {
if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_module) == FALSE) {
goto hsyml_exit;
}
Name.hSym = hSym;
}
mask &= ~HSYMR_module;
}
case HSYML_global:
// search global symbol table
if (mask & HSYMR_global) {
if (fRestart == FALSE) {
Name.hSym = 0;
}
fRestart = FALSE;
Name.state = HSYML_global;
Name.sstr.searchmask |= SSTR_NoHash;
while ((hSym = SHFindNameInGlobal (Name.hSym, &Name.CXTT,
(LPSSTR)&Name, fCaseSensitive, Name.pfnCmp, &CXTTOut)) != 0) {
if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_global) == FALSE) {
goto hsyml_exit;
}
Name.hSym = hSym;
}
mask &= ~HSYMR_global;
}
case HSYML_exe:
if (mask & HSYMR_exe) {
Name.state = HSYML_exe;
if (fRestart == FALSE) {
Name.hModCur = SHGetNextMod (Name.hExe, Name.hMod);
Name.hSym = 0;
}
fRestart = FALSE;
Name.sstr.searchmask |= SSTR_NoHash;
do {
if (SHGetCxtFromHmod (Name.hModCur, &Name.CXTT)) {
while ((hSym = SHFindNameInContext (Name.hSym,
&Name.CXTT,
(LPSSTR)&Name,
fCaseSensitive,
Name.pfnCmp,
&CXTTOut)
) != 0)
{
if (AddHSYM (&Name,
hSym,
pHSLHead,
HSYMR_exe)
== FALSE)
{
goto hsyml_exit;
}
Name.hSym = hSym;
}
}
} while (Name.hSym = 0,
(Name.hModCur = SHGetNextMod (Name.hExe, Name.hModCur)) != Name.hMod);
mask &= ~HSYMR_exe;
}
case HSYML_public:
if (mask & HSYMR_public && Name.hExe) {
if (fRestart == FALSE) {
hSym = 0;
}
fRestart = FALSE;
Name.state = HSYML_public;
Name.sstr.searchmask |= SSTR_NoHash;
while ((hSym = PHFindNameInPublics (hSym, Name.hExe,
(LPSSTR)&Name, fCaseSensitive, Name.pfnCmp)) != 0) {
if (AddHSYM (&Name, hSym, pHSLHead, HSYMR_public) == FALSE) {
goto hsyml_exit;
}
Name.hSym = hSym;
}
mask &= ~HSYMR_public;
}
}
pHSLHead->status.endsearch = TRUE;
MHMemUnLock (*phSYML);
return (EENOERROR);
hsyml_exit:
if (pHSLHead->restart == 0) {
// allocate restart buffer
if ((pHSLHead->restart = MHMemAllocate (sizeof (HSL_restart_t))) == 0) {
pHSLHead->status.fatal = TRUE;
MHMemUnLock (*phSYML);
return (EENOMEMORY);
}
}
pRestart = MHMemLock (pHSLHead->restart);
pRestart->Name = Name;
pRestart->mask = mask;
pRestart->state = state;
pRestart->hSym = hSym;
MHMemUnLock (pHSLHead->restart);
MHMemUnLock (*phSYML);
return (EENOERROR);
}
LOCAL bool_t
AddHSYM (
psearch_t pName,
HSYM hSym,
PHSL_HEAD pHSLHead,
uint request
)
{
PHSL_LIST pHSLList;
pHSLList = pHSLHead->pHSLList;
// check usability of current block
if (pHSLList->status.isused == TRUE) {
// block has been used, check for same context
if (_fmemcmp (&pHSLList->Cxt, &pName->CXTT, sizeof (CXT)) != 0) {
// context has changed
pHSLList->status.complete = TRUE;
pHSLHead->pHSLList = (PHSL_LIST)((uchar *)pHSLList +
sizeof ( HSL_LIST ) +
pHSLList->symbolcnt * sizeof ( HSYM ) );
pHSLList = pHSLHead->pHSLList;
pHSLHead->blockcnt++;
}
}
if (pHSLList->status.hascxt == FALSE) {
if (pHSLHead->remaining < (sizeof (HSL_LIST) + sizeof (HSYM))) {
return (FALSE);
}
pHSLHead->remaining -= sizeof (HSL_LIST);
pHSLList->status.hascxt = TRUE;
pHSLList->Cxt = pName->CXTT;
pHSLList->request = (ushort) request;
}
if (pHSLHead->remaining < sizeof (HSYM)) {
return (FALSE);
}
pHSLList->status.isused = TRUE;
pHSLList->hSym[pHSLList->symbolcnt++] = hSym;
pHSLHead->remaining -= sizeof (HSYM);
return (TRUE);
}
// search for the base sym of the base pointer
//
// Entry pName = structure describing the base pointer name
//
// Exit pName.eval reflects the bound base info
//
// Returns HR_ if base sym found
HR_t
SearchBasePtrBase (
psearch_t pName
)
{
search_t lName = *pName;
plfPointer pType;
SYMPTR pSym;
unsigned short lrectyp;
eval_t eval;
peval_t lpv = &eval;
ushort savefEProlog = pExState->state.fEProlog;
HR_t retval = HR_notfound;
pExState->state.fEProlog = TRUE; // KLUDGE to get around CXT complications
eval = *pName->pv;
CLEAR_EVAL_FLAGS (lpv);
// an enregistered primitive
EVAL_IS_REG (lpv) = EVAL_IS_REG(pName->pv);
EVAL_IS_BPREL (lpv) = EVAL_IS_BPREL(pName->pv);
lName.hSym = 0; // start search at beginning of CXT
lName.pv = lpv;
DASSERT(!CV_IS_PRIMITIVE (EVAL_TYP(lpv)));
DASSERT (EVAL_MOD (lpv) != 0);
EVAL_TYPDEF (lpv) = THGetTypeFromIndex (EVAL_MOD (lpv), EVAL_TYP(lpv));
DASSERT (EVAL_TYPDEF (lpv) != 0);
_fmemset (&lpv->data, 0, sizeof (lpv->data));
pType = (plfPointer)(&((TYPPTR)(MHOmfLock (EVAL_TYPDEF(lpv))))->leaf);
DASSERT(pType->leaf == LF_POINTER);
DASSERT((pType->attr.ptrtype >= CV_PTR_BASE_VAL) &&
(pType->attr.ptrtype <= CV_PTR_BASE_SEGADDR));
pSym = (SYMPTR)(&((plfPointer)pType)->pbase.Sym);
PTR_BSYMTYPE (pName->pv) = pSym->rectyp;
emiAddr (PTR_ADDR (pName->pv)) = pCxt->addr.emi;
switch (pSym->rectyp) {
case S_BPREL16:
lName.sstr.lpName = &((BPRELPTR16)pSym)->name[1];
lName.sstr.cb = ((BPRELPTR16)pSym)->name[0];
if (SearchSym(&lName) != HR_found) {
goto ReturnNotFound;;
}
PopStack();
SetAddrSeg (&PTR_ADDR (pName->pv), 0);
pSym = (SYMPTR)MHOmfLock(lName.hSym);
if (((BPRELPTR16)pSym)->rectyp == S_BPREL16) {
SetAddrOff (&PTR_ADDR (pName->pv), ((BPRELPTR16)pSym)->off);
ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = FALSE;
ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = FALSE;
ADDR_IS_LI (PTR_ADDR (pName->pv)) = FALSE;
PTR_STYPE (pName->pv) = ((BPRELPTR16)pSym)->typind;
}
else {
goto ReturnNotFound;;
}
pExState->state.bprel = TRUE;
break;
case S_LDATA16:
case S_GDATA16:
lName.sstr.lpName = &((DATAPTR16)pSym)->name[1];
lName.sstr.cb = ((DATAPTR16)pSym)->name[0];
lrectyp = pSym->rectyp;
do {
if (SearchSym(&lName) != HR_found) {
goto ReturnNotFound;;
}
PopStack();
pSym = (SYMPTR)MHOmfLock(lName.hSym);
} while (pSym->rectyp != lrectyp);
pExState->state.fLData = TRUE;
SetAddrSeg (&PTR_ADDR (pName->pv), ((DATAPTR16)pSym)->seg);
SetAddrOff (&PTR_ADDR (pName->pv), ((DATAPTR16)pSym)->off);
ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = FALSE;
ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = FALSE;
ADDR_IS_LI (PTR_ADDR (pName->pv)) = TRUE;
PTR_STYPE (pName->pv) = ((DATAPTR16)pSym)->typind;
break;
case S_BPREL32:
lName.sstr.lpName = &((BPRELPTR32)pSym)->name[1];
lName.sstr.cb = ((BPRELPTR32)pSym)->name[0];
if (SearchSym(&lName) != HR_found) {
goto ReturnNotFound;;
}
PopStack();
SetAddrSeg (&PTR_ADDR (pName->pv), 0);
if (((BPRELPTR32)pSym)->off != 0) {
SetAddrOff (&PTR_ADDR (pName->pv), ((BPRELPTR32)pSym)->off);
ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = TRUE;
ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = TRUE;
ADDR_IS_LI (PTR_ADDR (pName->pv)) = FALSE;
PTR_STYPE (pName->pv) = ((BPRELPTR32)pSym)->typind;
}
else {
goto ReturnNotFound;;
}
pExState->state.bprel = TRUE;
break;
case S_LDATA32:
case S_GDATA32:
case S_LTHREAD32:
case S_GTHREAD32:
lName.sstr.lpName = &((DATAPTR32)pSym)->name[1];
lName.sstr.cb = ((DATAPTR32)pSym)->name[0];
lrectyp = pSym->rectyp;
do {
if (SearchSym(&lName) != HR_found) {
goto ReturnNotFound;;
}
PopStack();
pSym = (SYMPTR)MHOmfLock(lName.hSym);
} while (pSym->rectyp != lrectyp);
pExState->state.fLData = TRUE;
SetAddrSeg (&PTR_ADDR (pName->pv), ((DATAPTR32)pSym)->seg);
SetAddrOff (&PTR_ADDR (pName->pv), ((DATAPTR32)pSym)->off);
ADDR_IS_OFF32 (PTR_ADDR (pName->pv)) = TRUE;
ADDR_IS_FLAT (PTR_ADDR (pName->pv)) = TRUE;
ADDR_IS_LI (PTR_ADDR (pName->pv)) = TRUE;
PTR_STYPE (pName->pv) = ((DATAPTR32)pSym)->typind;
break;
case S_REGISTER:
break;
default:
DASSERT(FALSE);
break;
}
retval = HR_found;
ReturnNotFound:
pExState->state.fEProlog = savefEProlog;
return(retval);
}
/** SearchSym - search for symbol
*
* status = SearchSym (pName)
*
* Entry pName = structure describing state of search
*
* Exit pName updated to reflect search results
* pName->hSym = handle of symbol
* pName->CXTT = context of symbol
*
* Returns HR_... enum specifying search result
*/
HR_t
SearchSym (
psearch_t pName
)
{
CXT CXTTOut;
HSYM hSym = 0;
bool_t isprolog;
SCN_t retval;
char NameNew[ 256 ];
LPB NameOld = ((LPSSTR) pName)->lpName;
unsigned char cbNew;
unsigned char cbOld = ((LPSSTR) pName)->cb;
BOOL SearchWithSuffix;
// NOTE: this routine may be called recursively through MatchFunction
if ((hBPatch != 0) && (pExState->ambiguous != 0) &&
(pExState->ambiguous == pName->bn)) {
// this is a request for a symbol that was previously found to
// be ambiguous. Pop the next ambiguous symbol off the list and
// return it to the caller.
return (AmbFromList (pName));
}
// If we encounter a lone '.', handle as the CUR PC operator (for any platform).
if ((pName->sstr.cb == 1 ) &&
*(pName->sstr.lpName) == '.') {
EVAL_STATE( pName->pv ) = EV_rvalue;
EVAL_TYP( pName->pv ) = T_PCHAR;
EVAL_IS_PTR( pName->pv ) = TRUE;
EVAL_IS_CURPC( pName->pv ) = TRUE;
PushStack (pName->pv);
return (HR_found);
}
SearchWithSuffix = ( Suffix && !(((LPSSTR)pName)->searchmask & SSTR_RE) );
if ( SearchWithSuffix ) {
cbNew = cbOld+1;
memcpy( NameNew, NameOld, cbOld );
NameNew[ cbOld ] = Suffix;
NameNew[ cbNew ] = '\0';
}
// this routine will terminate on the following conditions:
// 1. A symbol is found that is not a function address
// 2. A symbol is found that is a function and is not a method
// and the end of the symbol table is reached
// 3. A symbol is found that is a method and the end of the
// inheritance tree for the class is reached.
// If BindingBP is set, all function/method addresses that match
// the expression are entered into the TMList pointed to by pTMList
for (;;) {
switch (pName->state) {
case SYM_bclass:
// this state is a special entry for searching for the base
// class of a class when only the type of the base is known
if (InitMod (pName) == FALSE) {
// error in context
return (HR_notfound);
}
pName->state = SYM_class;
continue;
case SYM_init:
if (InitMod (pName) == FALSE) {
/*
* For line numbers (@linenumber) to be error
*/
if ((pName->scope & ~SCP_class) &&
(*pName->sstr.lpName == '@') &&
(isdigit (*(pName->sstr.lpName + 1)))
) {
return HR_notfound;
}
// error in context so we will allow check for registers
return (ParseRegister (pName));
}
if ((pName->scope & ~SCP_class) && *pName->sstr.lpName == '@') {
//search for @register, @linenumber, fastcall routine
if (isdigit (*(pName->sstr.lpName + 1))) {
return (LineNumber (pName));
}
else if ((hSym = PHFindNameInPublics ((HSYM) NULL,
pName->hExe, (LPSSTR)pName, pExState->state.fCase,
pName->pfnCmp)) != 0) {
goto found;
}
else if (ParseRegister (pName) == HR_found) {
return (HR_found);
}
else {
return (HR_notfound);
}
}
else if (*pName->sstr.lpName == 0xff) {
// search for handle to symbol. The handle to
// symbol comes from CV when a specific symbol
// is to be searched. The most common case is
// when a specific variable is to be displayed
// in the locals window
pName->sstr.lpName++;
hSym = *((HSYM UNALIGNED *)(pName->sstr.lpName));
goto found;
}
// start normal symbol search
pName->state = SYM_lexical;
case SYM_lexical:
if (pName->scope & SCP_lexical) {
// search up the lexical scope to the function level
// but do not search the module level because of the
// class search required for method functions
isprolog = SHIsInProlog (&pName->CXTT);
while (!SHIsCXTMod (&pName->CXTT) ) {
hSym = SHFindNameInContext (pName->hSym,
&pName->CXTT,
(LPSSTR)pName,
pExState->state.fCase,
FNCMP,
&CXTTOut);
if ( hSym ) {
if (isprolog && (pExState->state.fEProlog == FALSE)) {
// we want to reject bp_relative and register
// stuff if we are in the prolog or epilog of
// a function
// M00FLAT32 - need another check here
if ((pName->lastsym != S_BPREL16) &&
(pName->lastsym != S_BPREL32) &&
(pName->lastsym != S_REGISTER)) {
goto foundsave;
}
else {
// stop the search here: we have
// already found a symbol, but cannot
// evaluate it. --caviar #5898
pExState->err_num = ERR_NOSTACKFRAME;
return HR_error;
}
}
else {
goto foundsave;
}
}
// go to the parent scope
SHGoToParent (&pName->CXTT, &CXTTOut);
// reset current symbol
pName->hSym = 0;
pName->CXTT = CXTTOut;
}
}
pName->state = SYM_class;
if (pName->scope & SCP_class) {
if (pName->ExpClass != 0) {
// search an explicit class
pName->CurClass = pName->ExpClass;
}
else if (ClassImp != 0) {
pName->CurClass = ClassImp;
}
}
case SYM_class:
if ((pName->CurClass != 0) && (pName->scope & SCP_class)) {
retval = SearchClassName (pName);
switch (retval) {
case SCN_found:
// the symbol is a member of the class. If
// an explict class was not specified and
// the current context is implicitly a class,
// then we rewrote the tree to change the
// symbol reference to this->symbol
DASSERT (pName->hFound == 0);
DASSERT (pName->hAmbCl == 0);
if (EVAL_TYP (pName->pv) != T_NOTYPE) {
if (PushStack (pName->pv) == FALSE)
return (HR_error);
goto nopush;
}
else {
if (EVAL_IS_STMEMBER(pName->pv)) {
pExState->err_num = ERR_STATICNOOMF;
} else {
pExState->err_num = ERR_BADOMF;
}
return (HR_error);
}
case SCN_rewrite:
return (HR_rewrite);
case SCN_error:
return (HR_error);
default:
DASSERT (pName->hFound == 0);
DASSERT (pName->hAmbCl == 0);
if (pName->initializer == INIT_base) {
// we were searching for the base class of
// a class which was not found.
return (HR_notfound);
}
break;
}
}
SHGetCxtFromHmod (pName->hMod, &pName->CXTT);
pName->hSym = 0;
pName->state = SYM_module;
case SYM_module:
if (pName->scope & SCP_module) {
if ((hSym = SHFindNameInContext (pName->hSym, &pName->CXTT,
(LPSSTR)pName, pExState->state.fCase, pName->pfnCmp,
&CXTTOut)) != 0) {
goto foundsave;
}
}
pName->state = SYM_global;
pName->hSym = 0;
case SYM_global:
// users specified a context on a break point command
// we have already searched the module specified so end the search
// here
// sps - 7/24/92
if (pBindBPCxt && pBindBPCxt->hMod &&(pBindBPCxt->hMod != pName->hModCur) &&
(pExState->ambiguous != 0) && (pExState->ambiguous == pName->bn)) {
return(HR_end);
}
// search global symbol table
if (pName->scope & SCP_global) {
hSym = SHFindNameInGlobal( pName->hSym,
&pName->CXTT,
(LPSSTR)pName,
pExState->state.fCase,
pName->pfnCmp,
&CXTTOut);
if ( !hSym && SearchWithSuffix ) {
((LPSSTR)pName)->lpName = NameNew;
((LPSSTR)pName)->cb = cbNew;
hSym = SHFindNameInGlobal( pName->hSym,
&pName->CXTT,
(LPSSTR)pName,
pExState->state.fCase,
pName->pfnCmp,
&CXTTOut );
((LPSSTR)pName)->lpName = NameOld;
((LPSSTR)pName)->cb = cbOld;
}
if ( hSym ) {
goto foundsave;
}
}
pName->hModCur = SHGetNextMod (pName->hExe, pName->hMod);
pName->hSym = 0;
pName->state = SYM_exe;
case SYM_exe:
if (pName->scope & SCP_global) {
if (pName->hModCur == 0) {
pName->hModCur = SHGetNextMod(pName->hExe,
pName->hModCur);
}
while (pName->hModCur != pName->hMod) {
if (SHGetCxtFromHmod (pName->hModCur, &pName->CXTT)) {
hSym = SHFindNameInContext (pName->hSym,
&pName->CXTT,
(LPSSTR)pName,
pExState->state.fCase,
pName->pfnCmp,
&CXTTOut);
if ( !hSym && SearchWithSuffix ) {
((LPSSTR)pName)->lpName = NameNew;
((LPSSTR)pName)->cb = cbNew;
hSym = SHFindNameInContext (pName->hSym,
&pName->CXTT,
(LPSSTR)pName,
pExState->state.fCase,
pName->pfnCmp,
&CXTTOut);
((LPSSTR)pName)->lpName = NameOld;
((LPSSTR)pName)->cb = cbOld;
}
if ( hSym ) {
goto foundsave;
}
}
pName->hSym = 0;
pName->hModCur = SHGetNextMod (pName->hExe,
pName->hModCur);
if (pName->hModCur == 0) {
pName->hModCur = SHGetNextMod(pName->hExe,
pName->hModCur);
}
}
}
// we are at the end of the normal symbol search. If the
// symbol has not been found, we will search the public
// symbol table.
if (!BindingBP) {
// if we are not binding breakpoints and we have
// found a symbol in previous calls, return. Otherwise,
// we will look in the publics table. Note that
// finding a symbol in the publics table has a
// large probability of finding one with a type of
// zero which will limit it's usefulness
if (pName->hSym != 0) {
if (pName->possibles > 1) {
pExState->err_num = ERR_AMBIGUOUS;
return (HR_ambiguous);
}
return (HR_notfound);
}
}
else {
// we are binding breakpoints. We need to see if
// one or more symbols have matched. If so, we
// are done with the symbol search. If we have
// not found the symbol, we search the publics table.
// For breakpoints, we do not need type information,
// only the address, so symbols found in the publics
// table are much more useful.
if ((pExState->ambiguous != 0) &&
(pExState->ambiguous == pName->bn)) {
// we have found at least one symbol to this
// point. this is indicated by SymAmbToList
// setting the node of the function's symbol
// into the expression state structure. By
// this point all ambiguous symbols have been
// added to the back patch list. If we have
// not found any symbol yet, we search the
// publics table. Note also that there cannot
// be any ambiguity in the publics table because
// the function names have to be unique in the
// publics table.
return HR_end;
}
}
// search public symbol table
pName->state = SYM_public;
case SYM_public:
//
// some searches such as finding a UDT by type
// do not require a symbol
//
if (pName->scope & SCP_global) {
hSym = PHFindNameInPublics ( (HSYM)NULL,
pName->hExe,
(LPSSTR)pName,
pExState->state.fCase,
pName->pfnCmp);
if ( !hSym && SearchWithSuffix ) {
((LPSSTR)pName)->lpName = NameNew;
((LPSSTR)pName)->cb = cbNew;
hSym = PHFindNameInPublics ( (HSYM)NULL,
pName->hExe,
(LPSSTR)pName,
pExState->state.fCase,
pName->pfnCmp );
((LPSSTR)pName)->lpName = NameOld;
((LPSSTR)pName)->cb = cbOld;
}
if (!hSym) {
char rgch[256];
*rgch = '_';
strcpy(&rgch[1], NameOld);
((LPSSTR)pName)->lpName = rgch;
((LPSSTR)pName)->cb = cbOld + 1;
hSym = PHFindNameInPublics ( (HSYM)NULL,
pName->hExe,
(LPSSTR) pName,
pExState->state.fCase,
pName->pfnCmp );
if ( !hSym && SearchWithSuffix ) {
*rgch = '_';
strcpy(&rgch[1], NameNew);
((LPSSTR)pName)->lpName = rgch;
((LPSSTR)pName)->cb = cbNew + 1;
hSym = PHFindNameInPublics ( (HSYM)NULL,
pName->hExe,
(LPSSTR) pName,
pExState->state.fCase,
pName->pfnCmp );
}
//
// now look for fastcall names
//
if (!hSym) {
*rgch = '@';
strcpy(&rgch[1], NameOld);
((LPSSTR)pName)->lpName = rgch;
((LPSSTR)pName)->cb = cbOld + 1;
hSym = PHFindNameInPublics ( (HSYM)NULL,
pName->hExe,
(LPSSTR) pName,
pExState->state.fCase,
pName->pfnCmp );
}
((LPSSTR)pName)->lpName = NameOld;
((LPSSTR)pName)->cb = cbOld;
}
if ( hSym ) {
if (hSym == pName->hSym) {
// We found this symbol last call! There
// are no more to be found (or worth finding).
return HR_notfound;
}
goto foundsave;
}
}
if (EVAL_IS_REG (pName->pv)) {
return (HR_notfound); // found it last time - quite looking
}
else if ((pName->scope & ~SCP_class) && ParseRegister (pName) == HR_found) {
return (HR_found);
}
pExState->err_num = ERR_UNKNOWNSYMBOL;
return (HR_notfound);
}
}
foundsave:
pName->CXTT = CXTTOut;
found:
pName->hSym = hSym;
EVAL_HSYM (pName->pv) = pName->hSym;
if (pName->initializer == INIT_tdef) {
// the routines that search for UDTs only need the
// hsym and the stack pointer may not be valid at this
// point (FormatUDT for example), so return now
return (HR_found);
}
if (SymToNode (pName) == FALSE) {
return (HR_notfound);
}
if (PushStack (pName->pv) == FALSE)
return (HR_error);
nopush:
if (!EVAL_IS_FCN (ST)) {
// if this symbol is not a function and we have not processed
// a function previously, then the search is done
if (pExState->ambiguous == 0) {
return (HR_found);
}
else if (pExState->ambiguous == pName->bn) {
pExState->err_num = ERR_SYMCONFLICT;
return (HR_error);
}
else {
return (HR_found);
}
}
else if (EVAL_IS_METHOD (ST)) {
// ambiguous methods were entered into the ambiguous breakpoint
// list by SetBPValue which was called in SearchClassName
return (HR_found);
}
else if (pName->state == SYM_public) {
// we will take the first function symbol found in the
// publics table since the names have to be unique in the
// publics table
return (HR_found);
}
else if ((BindingBP == TRUE) && (bArgList == 0)) {
// if we are binding breakpoints and there is not an
// argument list, we will enter all functions found with
// this name into the breakpoint ambiguity list.
return (SymAmbToList (pName));
}
else {
// the found symbol is non-member function. continue
// search to end of symbols to find the best function.
// in the case of a breakpoint with argument list, there
// must be an exact match on the argument types
EVAL_MOD (pName->pv) = SHHMODFrompCXT (&pName->CXTT);
if (pName->scope & SCP_nomatchfn)
return (HR_found);
return (MatchFunction (pName));
}
}
LOCAL bool_t
InitMod (
psearch_t pName
)
{
if (((pName->hMod = SHHMODFrompCXT (&pName->CXTT)) == 0) ||
((pName->hExe = SHHexeFromHmod (pName->hMod)) == 0)) {
// error in context
return (FALSE);
}
return (TRUE);
}
// Class searching and main support routines
/*** SearchClassName - Search a class and bases for element by name
*
* flag = SearchClassName (pName)
*
* Entry pName = pointer to struct describing search
*
* Exit pName updated to reflect type
*
* Returns SCN_... enum describing result
*/
LOCAL SCN_t
SearchClassName (
psearch_t pName
)
{
SCN_t retval;
ushort max;
CV_fldattr_t attr = {0};
// allocate and initialize list of dominated virtual bases
if (hVBDom == 0) {
if ((hVBDom = MHMemAllocate (sizeof (dombase_t) +
DOMBASE_DEFAULT * sizeof (CV_typ_t))) == 0) {
pExState->err_num == ERR_NOMEMORY;
return (SCN_error);
}
pVBDom = MHMemLock (hVBDom);
pVBDom->MaxIndex = DOMBASE_DEFAULT;
}
else {
pVBDom = MHMemLock (hVBDom);
}
pVBDom->CurIndex = 0;
// allocate and initialize list of searched virtual bases
if (hVBSearch == 0) {
if ((hVBSearch = MHMemAllocate (sizeof (dombase_t) +
DOMBASE_DEFAULT * sizeof (CV_typ_t))) == 0) {
pExState->err_num == ERR_NOMEMORY;
MHMemUnLock (hVBDom);
return (SCN_error);
}
pVBSearch = MHMemLock (hVBSearch);
pVBSearch->MaxIndex = DOMBASE_DEFAULT;
}
else {
pVBSearch = MHMemLock (hVBSearch);
}
pVBSearch->CurIndex = 0;
// allocate and initialize structure for recursive base searches
if (hSymClass == 0) {
if ((hSymClass = MHMemAllocate (sizeof (symclass_t) +
SYMBASE_DEFAULT * sizeof (symbase_t))) == 0) {
pExState->err_num == ERR_NOMEMORY;
MHMemUnLock (hVBDom);
MHMemUnLock (hVBSearch);
return (SCN_error);
}
pSymClass = MHMemLock (hSymClass);
pSymClass->MaxIndex = SYMBASE_DEFAULT;
}
else {
pSymClass = MHMemLock (hSymClass);
}
pSymClass->CurIndex = 0;
pSymClass->hNext = 0;
max = pSymClass->MaxIndex;
_fmemset (pSymClass, 0, max * sizeof (symbase_t) + sizeof (symclass_t));
pSymClass->MaxIndex = max;
// recurse through the inheritance tree searching for the feature
if ((retval = RecurseBase (pName, pName->CurClass, 0, 0, 0,
attr, FALSE)) != SCN_error) {
// at this point we need to check for dominance and then clean
// up the allocated memory and return the search results
if (pName->possibles == 0) {
// if the count was zero, the handle of found list must be zero
DASSERT (pName->hFound == 0);
retval = SCN_notfound;
}
else if (pName->cFound == 0) {
if (pName->hFound == 0) {
DASSERT (pSymClass->s.viable == TRUE);
// the found value is in the permanent stack. This means
// the feature was found in the most derived class
retval = SetValue (pName);
}
}
else if (pName->cFound == 1) {
// the feature was not found in the most derived class
// but no other matching feature was found. Move the feature
// descriptor pointed to by pName->hFound into the permanent
// feature descriptor pSymClass. An important thing to remember
// here is that there can only be one feature descriptor pSymClass
// when calling SetValue unless we are binding breakpoints.
// If we are binding breakpoints we can have multiple feature
// descriptors in pSymClass and the list pointed to by
// pName->hAmbCl. If we have an argument list, these must
// resolve to one feature. If we do not have an argument
// list, all of the features are valid and must be added
// to the breakpoint list.
MoveSymCl (pName->hFound);
pName->hFound = 0;
pName->cFound--;
DASSERT (pSymClass->s.viable == TRUE);
retval = SetValue (pName);
}
else {
// since two or more features were found, we need to cull the
// feature list to remove dominated features and features which
// are the same static item. Ambiguity is removed strictly on
// the name of the feature. Overloaded methods are resolved later.
if ((retval = RemoveAmb (pName)) == SCN_found) {
retval = SetValue (pName);
}
}
}
MHMemUnLock (hVBDom);
MHMemUnLock (hVBSearch);
MHMemUnLock (hSymClass);
DASSERT (pName->hAmbCl == 0);
return (retval);
}
/*** RecurseBase - Search a class and its bases for element by name
*
* status = RecurseBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual)
*
* Entry pName = pointer to struct describing search
* type = type index of class
* vbptr = type index of virtual base pointer
* vbpoff = offset of virtual base pointer from address point
* thisadjust = offset of base from previous class
* thisadjust = virtual base index if virtual base
* attr = attribute of base class
* virtual = TRUE if this is a virtual base
*
* Exit pName updated to reflect type
*
* Returns SCN_... enum describing result
*/
LOCAL SCN_t
RecurseBase (
psearch_t pName,
CV_typ_t type,
CV_typ_t vbptr,
OFFSET vbpoff,
OFFSET thisadjust,
CV_fldattr_t attr,
bool_t virtual
)
{
SCN_t retval;
// save offset of base from address point for this pointer adjustment
if (SetBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual) != SCN_found) {
return (SCN_error);
}
if (pName->initializer == INIT_base) {
retval = SearchBType (pName);
}
else {
retval = SearchRoot (pName);
}
switch (retval) {
case SCN_found:
if ((pName->clsmask & CLS_virtintro) == FALSE) {
// add virtual bases to searched and dominated base lists
// if we were searching for the introducing virtual function,
// the fact that we found one is sufficient.
if ((pSymClass->s.isvbase == TRUE) &&
(VBaseFound (pName) == TRUE)) {
// the found feature is a previously found
// virtual base class.
pSymClass->s.isdupvbase = TRUE;
}
if ((retval = AddVBList
(pSymClass, &pVBSearch, &hVBSearch)) != SCN_error) {
retval = AddVBList (pSymClass, &pVBDom, &hVBDom);
}
}
case SCN_error:
return (retval);
case SCN_notfound:
// we did not find the element in the root of this class
// so we search the inheritance tree.
if (pExState->state.fSupBase == FALSE) {
return (SearchBases (pName));
}
else {
return (SCN_notfound);
}
default:
return (SCN_error);
}
}
/** VBaseFound - search to see if virtual base already found
*
* status = VBaseFound (pName)
*
* Entry pName = structure describing search
* pSymClass = structure describing most recent class search
*
* Exit pName updated to reflect search
* pSymClass updated to unambiguous feature
*
* Returns TRUE if duplicate virtual base found
* FALSE if not duplicate virtual base
*/
LOCAL bool_t
VBaseFound (
psearch_t pName
)
{
psymclass_t pSymCl;
HDEP hSymCl;
CV_typ_t type = EVAL_TYP (&pSymClass->evalP);
hSymCl = pName->hFound;
while (hSymCl != 0) {
pSymCl = MHMemLock (hSymCl);
if (pSymCl == pSymClass) {
return (FALSE);
}
if ((pSymCl->s.isvbase == TRUE) && (type == EVAL_TYP (&pSymCl->evalP))) {
// the virtual base is already in the list
MHMemUnLock( hSymCl );
return (TRUE);
}
DASSERT( FALSE );
MHMemUnLock( hSymCl );
hSymCl = 0; // NOTENOTE -- jimsch -- was no linking to next
}
return (FALSE);
}
/** RemoveAmb - remove ambiguity
*
* status = RemoveAmb (pName)
*
* Entry pName = structure describing search
* pSymClass = structure describing most recent class search
*
* Exit pName updated to reflect search
* pSymClass updated to unambiguous feature
*
* Returns SCN_found if unambiguous feature found
* SCN_error otherwise
*/
LOCAL SCN_t
RemoveAmb (
psearch_t pName
)
{
psymclass_t pSymCl;
// we know that at this point two or more features were found
// the list of features are pointed to by pName->hFound.
// The permanent stack cannot contain a viable feature
DASSERT (pSymClass->s.viable == FALSE);
MoveSymCl (pName->hFound);
pName->hFound = pSymClass->hNext;
while (pName->hFound != 0) {
// lock and check next list element
pSymCl = MHMemLock (pName->hFound);
switch (IsDominated (pSymClass, pSymCl)) {
case DOM_ambiguous:
// the new feature does not dominate the current best
MHMemUnLock (pName->hFound);
if (BindingBP == FALSE) {
pExState->err_num = ERR_AMBIGUOUS;
return (SCN_error);
}
// feature is ambiguous and we are setting breakpoints
// save the feature in the ambiguous list and advance to
// the next feature
pSymClass->hNext = pSymCl->hNext;
pSymCl->hNext = pName->hAmbCl;
pName->hAmbCl = pName->hFound;
MHMemUnLock (pName->hAmbCl);
pName->hFound = pSymClass->hNext;
break;
case DOM_replace:
// decrement the number of possible matches by the
// count in the current best structure
pName->possibles -= pSymClass->possibles;
pName->cFound--;
MHMemUnLock (pName->hFound);
MoveSymCl (pName->hFound);
pName->hFound = pSymClass->hNext;
PurgeAmbCl (pName);
break;
case DOM_keep:
// decrement the number of possible matches by the
// count in the structure being discarded
pName->possibles -= pSymCl->possibles;
pName->cFound--;
pSymClass->hNext = pSymCl->hNext;
MHMemUnLock (pName->hFound);
pName->hFound = pSymClass->hNext;
break;
}
}
// decrement the count of found features to account for the one we kept
pName->cFound--;
return (SCN_found);
}
/*** SearchBases - Search for an element in the bases of a class
*
* flag = SearchBases (pName, pvClass)
*
* Entry pName = pointer to struct describing search
*
* Exit pName updated to reflect type
*
* Returns enum describing search state
*
*/
LOCAL SCN_t
SearchBases (
psearch_t pName
)
{
ushort cnt; // count of number of elements in struct
HTYPE hField; // handle to type record for struct field list
char *pField; // pointer to field list
uint fSkip = 0; // offset in the field list
SCN_t retval = SCN_notfound;
CV_typ_t newindex;
CV_typ_t vbptr;
OFFSET offset;
OFFSET vbpoff;
CV_fldattr_t attr;
CV_fldattr_t vattr;
peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
bool_t virtual;
// Set to head of type record and search the base classes in order
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) {
// set error and stop search
DASSERT (FALSE);
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
fSkip += SkipPad(((uchar *)pField) + fSkip);
newindex = 0;
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// switch to next part of type record
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
DASSERT (FALSE);
pExState->err_num = ERR_INTERNAL;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
fSkip = 0;
// the LF_INDEX is not part of the field count
cnt++;
break;
case LF_BCLASS:
// read type index of base class offset of base pointer
// from address point
attr = ((plfBClass)(pField + fSkip))->attr;
newindex = ((plfBClass)(pField + fSkip))->index;
fSkip += sizeof (struct lfBClass);
offset = (OFFSET)RNumLeaf (pField + fSkip, &fSkip);
vbptr = 0;
vbpoff = 0;
virtual = FALSE;
goto foo;
case LF_VBCLASS:
// read type index of base class, type index of virtual
// base pointer, offset of virtual base pointer from
// address point and offset of virtual base displacement
// from virtual base table
vattr = ((plfVBClass)(pField + fSkip))->attr;
newindex = ((plfVBClass)(pField + fSkip))->index;
vbptr = ((plfVBClass)(pField + fSkip))->vbptr;
virtual = TRUE;
fSkip += sizeof (struct lfVBClass);
vbpoff = (OFFSET)RNumLeaf (pField + fSkip, &fSkip);
offset = (OFFSET)RNumLeaf (pField + fSkip, &fSkip);
if ((pName->clsmask & CLS_virtintro) == FALSE) {
// if we are searching for the introducing virtual method
// then we want to search all bases
if (VBSearched (newindex) == TRUE) {
break;
}
retval = AddVBType (&pVBSearch, &hVBSearch, newindex);
}
foo:
// check base class
MHOmfUnLock (hField);
// Advance to next base class structure
if (IncrSymBase () != SCN_found) {
return (SCN_error);
}
retval = RecurseBase (pName, newindex, vbptr, vbpoff,
offset, attr, virtual);
switch (retval) {
case SCN_error:
// if we got an error, abort the search
newindex = 0;
break;
case SCN_found:
// we have found the feature in a base class.
// Dup the class search structure and continue the
// search to the end of the inheritance tree
if ((pName->clsmask & CLS_virtintro) == FALSE) {
if ((retval = DupSymCl (pName)) != SCN_found) {
// if we got an error duping, abort the search
newindex = 0;
}
// set not found, so the unwinding of the call stack
// does not reduplicate the class search structure
retval = SCN_notfound;
}
else {
// we were searching for the introducing virtual
// method. Since there can be only one in the
// tree above the virtual method, we can terminate
// the search immediately
return (retval);
}
break;
default:
break;
}
pSymClass->CurIndex--;
MHOmfLock (hField);
break;
default:
// we have reached the end of the base classes.
// exit loop and check search results.
break;
}
if (newindex == 0) {
// all base classes must appear first in the field list.
break;
}
}
MHOmfUnLock (hField);
return (retval);
}
bool_t
getDefnFromDecl(
CV_typ_t typeIn,
peval_t pv,
CV_typ_t* ptypeOut)
{
HTYPE hType;
uint skip;
TYPPTR pType;
eval_t localEval;
neval_t nv = &localEval;
*nv = *pv;
DASSERT (!CV_IS_PRIMITIVE (typeIn));
if ((hType = THGetTypeFromIndex (EVAL_MOD (nv), typeIn)) == 0) {
pExState->err_num = ERR_BADOMF;
return FALSE;
}
pType = (TYPPTR)MHOmfLock(hType);
switch (pType->leaf) {
case LF_STRUCTURE:
case LF_CLASS:
{
plfClass pClass = (plfClass)(&pType->leaf);
if (pClass->property.fwdref) {
skip = offsetof (lfClass, data);
RNumLeaf (((char *)(&pClass->leaf)) + skip, &skip);
// forward ref - look for the definition of the UDT
if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, ((char *)&(pClass->leaf)) + skip)) == T_NOTYPE) {
goto failed;
}
}
else
*ptypeOut = typeIn;
break;
}
case LF_UNION:
{
plfUnion pUnion = (plfUnion)(&pType->leaf);
if (pUnion->property.fwdref) {
skip = offsetof (lfUnion, data);
RNumLeaf (((char *)(&pUnion->leaf)) + skip, &skip);
// forward ref - look for the definition of the UDT
if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, ((char *)&(pUnion->leaf)) + skip)) == T_NOTYPE) {
goto failed;
}
}
else
*ptypeOut = typeIn;
break;
}
case LF_ENUM:
{
plfEnum pEnum = (plfEnum)(&pType->leaf);
if (pEnum->property.fwdref) {
// forward ref - look for the definition of the UDT
if ((*ptypeOut = GetUdtDefnTindex (typeIn, nv, (char *) pEnum->Name)) == T_NOTYPE) {
goto failed;
}
}
else
*ptypeOut = typeIn;
break;
}
default:
*ptypeOut = typeIn;
}
MHOmfUnLock (hType);
return TRUE;
failed:
MHOmfUnLock (hType);
pExState->err_num = ERR_BADOMF;
return FALSE;
}
/*** SearchBType - Search for an base by type
*
* flag = SearchBType (pName)
*
* Entry pName = pointer to struct describing search
* pSymClass = pointer to base class path list structure
*
* Exit pName updated to reflect search
*
* Return enum describing search
*
* If the base class is found, the base class value is stored in the
* the symbase[], not in pSymClass->evalP. This is to simplify the
* GenQualExpr code.
*/
LOCAL SCN_t
SearchBType (
psearch_t pName
)
{
ushort cnt; // count of number of elements in struct
HTYPE hField; // handle to type record for struct field list
char *pField; // pointer to field list
uint fSkip = 0; // offset in the field list
ushort anchor = 0; // offset in the field list to start of type
CV_typ_t newindex;
CV_typ_t vbptr;
ushort retval = SCN_notfound;
OFFSET offset;
OFFSET vbpoff;
bool_t termflag = FALSE;
CV_fldattr_t attr;
CV_fldattr_t vattr;
peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
// set hField to the handle of the field list for the class
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
// walk field list for the class
for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
fSkip += SkipPad(((uchar *)pField) + fSkip);
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// switch to new type record because compiler split it up
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_INTERNAL;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
fSkip = 0;
// the LF_INDEX is not part of the field count
cnt++;
break;
case LF_BCLASS:
attr = ((plfBClass)(pField + fSkip))->attr;
if (!getBaseDefnFromDecl(((plfBClass)(pField + fSkip))->index, pName->pv, &newindex))
return SCN_error;
// newindex = ((plfBClass)(pField + fSkip))->index;
fSkip += offsetof (lfBClass, offset[0]);
offset = (ushort)RNumLeaf (pField + fSkip, &fSkip);
if (pName->typeOut == newindex) {
// base has been found, set result values
MHOmfUnLock (hField);
if (IncrSymBase () != SCN_found) {
return (SCN_error);
}
// save offset of base from address point for this
// pointer adjustment
if (SetBase (pName, newindex, 0, 0, offset, attr, FALSE) != SCN_found) {
return (SCN_error);
}
pSymClass->s.viable = TRUE;
pName->possibles++;
return (SCN_found);
}
break;
case LF_VBCLASS:
vattr = ((plfVBClass)(pField + fSkip))->attr;
if (!getBaseDefnFromDecl(((plfVBClass)(pField + fSkip))->index, pName->pv, &newindex))
return SCN_error;
// newindex = ((plfVBClass)(pField + fSkip))->index;
vbptr = ((plfVBClass)(pField + fSkip))->vbptr;
fSkip += offsetof (lfVBClass, vbpoff[0]);
vbpoff = (ushort)RNumLeaf (pField + fSkip, &fSkip);
offset = (ushort)RNumLeaf (pField + fSkip, &fSkip);
if (pName->typeOut == newindex) {
// base has been found, set result values
MHOmfUnLock (hField);
if (IncrSymBase () != SCN_found) {
return (SCN_error);
}
// save offset of base from address point for this
// pointer adjustment
if (SetBase (pName, newindex, vbptr, vbpoff, offset, attr, TRUE) != SCN_found) {
return (SCN_error);
}
pSymClass->s.viable = TRUE;
pName->possibles++;
return (SCN_found);
}
break;
default:
termflag = TRUE;
break;
}
if (termflag == TRUE) {
break;
}
}
MHOmfUnLock (hField);
return (retval);
}
/*** SearchRoot - Search for an element of a class
*
* flag = SearchRoot (pName)
*
* Entry pName = pointer to struct describing search
* pvBase = pointer to value describing base to be searched
*
* Exit pName updated to reflect search
*
* Return enum describing search
*/
LOCAL SCN_t
SearchRoot (
psearch_t pName
)
{
ushort cnt; // count of number of elements in struct
HTYPE hField; // handle to type record for struct field list
char *pField; // pointer to field list
HTYPE hBase; // handle to type record for base class
uint fSkip = 0; // offset in the field list
uint anchor; // offset in the field list to start of type
uint tSkip; // temporary offset in the field list
bool_t cmpflag = 1;
CV_typ_t newindex;
CV_typ_t vbptr;
ushort retval = SCN_notfound;
char *pc;
ulong value;
OFFSET offset;
OFFSET vbpoff;
CV_fldattr_t access;
short count;
CV_typ_t vfpType = T_NOTYPE;
peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
CV_typ_t type;
peval_t pvF = &pSymClass->evalP;
ushort vtabind;
ushort vbind;
// set hField to the handle of the field list for the class
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase),
CLASS_FIELD (pvBase))) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock ((HDEP)hField))->data[0]);
// walk field list for the class
#if 0
for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
fSkip += SkipPad(((uchar *)pField) + fSkip);
anchor = fSkip;
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// switch to new type record because compiler split it up
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock ((HDEP)hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock ((HDEP)hField))->data[0]);
fSkip = 0;
// the LF_INDEX is not part of the field count
cnt++;
break;
case LF_MEMBER:
fSkip += offsetof (lfMember, offset[0]);
offset = (short)RNumLeaf (pField + fSkip, &fSkip);
access = ((plfMember)(pField + anchor))->attr;
pc = pField + fSkip;
fSkip += (*(pField + fSkip) + sizeof (char));
if (pName->clsmask & CLS_member) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc,
pExState->state.fCase)) == 0) {
type = ((plfMember)(pField + anchor))->index;
MHOmfUnLock ((HDEP)hField);
hField = 0;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_lvalue;
// save the casting data for the this pointer
pSymClass->offset = offset;
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
}
}
break;
case LF_ENUMERATE:
access = ((plfEnumerate)(pField + fSkip))->attr;
fSkip += offsetof (lfEnumerate, value[0]);
value = RNumLeaf (pField + fSkip, &fSkip);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (pName->clsmask & CLS_enumerate) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc,
pExState->state.fCase)) == 0) {
pSymClass->possibles = 1;
pName->possibles++;
}
}
break;
#if !defined(C_ONLY)
case LF_STMEMBER:
type = ((plfSTMember)(pField + anchor))->index;
fSkip += offsetof (lfSTMember, Name[0]);
if (pName->clsmask & CLS_member) {
if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pField + fSkip,
pExState->state.fCase)) == 0) {
pSymClass->access =
((plfSTMember)(pField + anchor))->attr;
MHOmfUnLock (hField);
hField = 0;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_lvalue;
EVAL_IS_STMEMBER (pvF) = TRUE;
pSymClass->possibles = 1;
pName->possibles++;
}
}
fSkip += *(pField + fSkip) + sizeof (char);
break;
case LF_BCLASS:
type = ((plfBClass)(pField + anchor))->index;
access = ((plfBClass)(pField + anchor))->attr;
fSkip += offsetof (lfBClass, offset[0]);
newindex = ((plfBClass)(pField + anchor))->index;
offset = (short)RNumLeaf (pField + fSkip, &fSkip);
if ((pName->clsmask & CLS_bclass) != 0) {
// switch to the base class type record to check the name
MHOmfUnLock (hField);
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
tSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + tSkip, &tSkip);
pc = pField + tSkip;
cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc, pExState->state.fCase);
MHOmfUnLock (hBase);
// reset to original field list
if (cmpflag == 0) {
// element has been found, set result values
pSymClass->s.isbase = TRUE;
pSymClass->s.isvbase = FALSE;
pSymClass->offset += offset;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_type;
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
}
break;
case LF_VBCLASS:
type = ((plfBClass)(pField + anchor))->index;
access = ((plfVBClass)(pField + anchor))->attr;
newindex = ((plfVBClass)(pField + anchor))->index;
vbptr = ((plfVBClass)(pField + anchor))->vbptr;
fSkip += offsetof (lfVBClass, vbpoff[0]);
vbpoff = (short)RNumLeaf (pField + fSkip, &fSkip);
vbind = (short)RNumLeaf (pField + fSkip, &fSkip);
if ((pName->clsmask & CLS_bclass) != 0) {
// switch to the base class type record to check the name
MHOmfUnLock (hField);
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
tSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + tSkip, &tSkip);
pc = pField + tSkip;
cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc, pExState->state.fCase);
MHOmfUnLock (hBase);
// reset to original field list
if (cmpflag == 0) {
// element has been found, set result values
pSymClass->s.isbase = FALSE;
pSymClass->s.isvbase = TRUE;
pSymClass->vbind = vbind;
pSymClass->vbpoff = vbpoff;
pSymClass->vbptr = vbptr;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_type;
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
}
break;
case LF_IVBCLASS:
fSkip += offsetof (lfVBClass, vbpoff[0]);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
break;
case LF_FRIENDCLS:
newindex = ((plfFriendCls)(pField + fSkip))->index;
fSkip += sizeof (struct lfFriendCls);
if ((pName->clsmask & CLS_fclass) != 0) {
DASSERT (FALSE);
// switch to the base class type record to check the name
MHOmfUnLock (hField);
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_INTERNAL;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->data[0]);
tSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + tSkip, &tSkip);
pc = pField + tSkip;
cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc, pExState->state.fCase);
MHOmfUnLock (hBase);
// reset to original field list
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
if (cmpflag == 0) {
// element has been found, set result values
pName->typeOut = newindex;
}
}
break;
case LF_FRIENDFCN:
newindex = ((plfFriendFcn)(pField + fSkip))->index;
fSkip += sizeof (struct lfFriendFcn) +
((plfFriendFcn)(pField + fSkip))->Name[0];
if ((pName->clsmask & CLS_frmethod) != 0) {
DASSERT (FALSE);
}
break;
case LF_VFUNCTAB:
fSkip += sizeof (struct lfVFuncTab);
// save the type of the virtual function pointer
vfpType = ((plfVFuncTab)(pField + anchor))->type;
pc = vfuncptr;
if (pName->clsmask & CLS_vfunc) {
if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc,
pExState->state.fCase)) == 0) {
MHOmfUnLock (hField);
hField = 0;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, vfpType);
EVAL_STATE (pvF) = EV_lvalue;
// save the casting data for the this pointer
if (pName->bnOp != 0) {
pSymClass->offset = 0;
pSymClass->access.access = CV_public;
}
pSymClass->possibles = 1;
pName->possibles++;
}
}
break;
case LF_METHOD:
count = ((plfMethod)(pField + fSkip))->count;
cnt -= count - 1;
newindex = ((plfMethod)(pField + fSkip))->mList;
pc = pField + anchor + offsetof (lfMethod, Name[0]);
fSkip += sizeof (struct lfMethod) + *pc;
if (pName->clsmask & CLS_method) {
if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc,
pExState->state.fCase)) == 0) {
// note that the OMF specifies that the vfuncptr will
// be emitted as the first field after the bases
if (pName->clsmask & CLS_virtintro) {
// we are looking for the introducing virtual
// method. We need to find a method with the
// correct name of the correct type index that
// is introducing.
MHOmfUnLock (hField);
if (IsIntroVirt (count, newindex, &vtabind) == FALSE) {
cmpflag = 1;
}
else {
if (FCN_VFPTYPE (pvF) == T_NOTYPE) {
FCN_VFPTYPE (pvF) = vfpType;
FCN_VFPTYPE (pName->pv) = vfpType;
FCN_VTABIND (pvF) = vtabind;
FCN_VTABIND (pName->pv) = vtabind;
}
cmpflag = 0;
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
}
else {
// save the type index of the method list, the
// count of methods overloaded on this name,
// the type index of the vfuncptr. Also,
// increment the number of possible features by
// the overload count
pSymClass->possibles = count;
pName->possibles += count;
pSymClass->mlist = newindex;
pSymClass->vfpType = vfpType;
}
}
}
break;
case LF_NESTTYPE:
newindex = ((plfNestType)(pField + fSkip))->index;
fSkip += offsetof (lfNestType, Name[0]);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (pName->clsmask & CLS_ntype) {
if ((cmpflag = fnCmp ((LPV) pName, (HVOID) NULL, pc,
pExState->state.fCase)) == 0) {
// set type of typedef symbol
EVAL_STATE (pvF) = EV_type;
}
}
break;
#else
Unreferenced( vbpoff );
Unreferenced( hBase );
Unreferenced( vbptr );
Unreferenced( tSkip );
Unreferenced( count );
Unreferenced( vtabind );
Unreferenced( vbind );
#endif
default:
pExState->err_num = ERR_BADOMF;
retval = SCN_notfound;
}
if (cmpflag == 0) {
pSymClass->s.viable = TRUE;
retval = SCN_found;
break;
}
}
#endif
#if 1
for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
fSkip += SkipPad(((uchar *)pField) + fSkip);
anchor = fSkip;
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// switch to new type record because compiler split it up
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
fSkip = 0;
// the LF_INDEX is not part of the field count
cnt++;
break;
case LF_MEMBER:
fSkip += offsetof (lfMember, offset);
offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip);
access = ((plfMember)(pField + anchor))->attr;
pc = pField + fSkip;
fSkip += (*(pField + fSkip) + sizeof (char));
if (pName->clsmask & CLS_member) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
type = ((plfMember)(pField + anchor))->index;
MHOmfUnLock (hField);
hField = 0;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_lvalue;
// save the casting data for the this pointer
pSymClass->offset = offset;
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
}
}
break;
case LF_ENUMERATE:
access = ((plfEnumerate)(pField + fSkip))->attr;
fSkip += offsetof (lfEnumerate, value);
value = (ulong) RNumLeaf (pField + fSkip, &fSkip);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (pName->clsmask & CLS_enumerate) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
pSymClass->possibles = 1;
pName->possibles++;
}
}
break;
case LF_STMEMBER:
type = ((plfSTMember)(pField + anchor))->index;
fSkip += offsetof (lfSTMember, Name);
if (pName->clsmask & CLS_member) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pField + fSkip, pExState->state.fCase)) == 0) {
pSymClass->access =
((plfSTMember)(pField + anchor))->attr;
MHOmfUnLock (hField);
hField = 0;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_lvalue;
EVAL_IS_STMEMBER (pvF) = TRUE;
pSymClass->possibles = 1;
pName->possibles++;
}
}
fSkip += *(pField + fSkip) + sizeof (char);
break;
case LF_BCLASS:
type = ((plfBClass)(pField + anchor))->index;
access = ((plfBClass)(pField + anchor))->attr;
fSkip += offsetof (lfBClass, offset);
newindex = ((plfBClass)(pField + anchor))->index;
offset = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip);
if ((pName->clsmask & CLS_bclass) != 0) {
// switch to the base class type record to check the name
MHOmfUnLock (hField);
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
tSkip = offsetof (lfClass, data);
RNumLeaf (pField + tSkip, &tSkip);
pc = pField + tSkip;
cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase);
MHOmfUnLock (hBase);
// reset to original field list
if (cmpflag == 0) {
// element has been found, set result values
pSymClass->s.isbase = TRUE;
pSymClass->s.isvbase = FALSE;
pSymClass->offset += offset;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_type;
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
}
break;
case LF_VBCLASS:
type = ((plfBClass)(pField + anchor))->index;
access = ((plfVBClass)(pField + anchor))->attr;
newindex = ((plfVBClass)(pField + anchor))->index;
vbptr = ((plfVBClass)(pField + anchor))->vbptr;
fSkip += offsetof (lfVBClass, vbpoff);
vbpoff = (UOFFSET)RNumLeaf (pField + fSkip, &fSkip);
vbind = (short)RNumLeaf (pField + fSkip, &fSkip);
if ((pName->clsmask & CLS_bclass) != 0) {
// switch to the base class type record to check the name
MHOmfUnLock (hField);
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->leaf);
tSkip = offsetof (lfClass, data);
RNumLeaf (pField + tSkip, &tSkip);
pc = pField + tSkip;
cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase);
MHOmfUnLock (hBase);
// reset to original field list
if (cmpflag == 0) {
// element has been found, set result values
pSymClass->s.isbase = FALSE;
pSymClass->s.isvbase = TRUE;
pSymClass->vbind = vbind;
pSymClass->vbpoff = vbpoff;
pSymClass->vbptr = vbptr;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, type);
EVAL_STATE (pvF) = EV_type;
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
}
break;
case LF_IVBCLASS:
fSkip += offsetof (lfVBClass, vbpoff);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
break;
case LF_FRIENDCLS:
newindex = ((plfFriendCls)(pField + fSkip))->index;
fSkip += sizeof (struct lfFriendCls);
if ((pName->clsmask & CLS_fclass) != 0) {
DASSERT (FALSE);
// switch to the base class type record to check the name
MHOmfUnLock (hField);
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_INTERNAL;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hBase))->data);
tSkip = offsetof (lfClass, data);
RNumLeaf (pField + tSkip, &tSkip);
pc = pField + tSkip;
cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase);
MHOmfUnLock (hBase);
// reset to original field list
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
if (cmpflag == 0) {
// element has been found, set result values
pName->typeOut = newindex;
}
}
break;
case LF_FRIENDFCN:
newindex = ((plfFriendFcn)(pField + fSkip))->index;
fSkip += sizeof (struct lfFriendFcn) +
((plfFriendFcn)(pField + fSkip))->Name[0];
if ((pName->clsmask & CLS_frmethod) != 0) {
DASSERT (FALSE);
}
break;
case LF_VFUNCTAB:
fSkip += sizeof (struct lfVFuncTab);
// save the type of the virtual function pointer
vfpType = ((plfVFuncTab)(pField + anchor))->type;
pc = vfuncptr;
if (pName->clsmask & CLS_vfunc) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
MHOmfUnLock (hField);
hField = 0;
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, vfpType);
EVAL_STATE (pvF) = EV_lvalue;
// save the casting data for the this pointer
if (pName->bnOp != 0) {
pSymClass->offset = 0;
pSymClass->access.access = CV_public;
}
pSymClass->possibles = 1;
pName->possibles++;
}
}
break;
case LF_METHOD:
count = ((plfMethod)(pField + fSkip))->count;
cnt -= count - 1;
newindex = ((plfMethod)(pField + fSkip))->mList;
pc = pField + anchor + offsetof (lfMethod, Name);
fSkip += sizeof (struct lfMethod) + *pc;
if (pName->clsmask & CLS_method) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
// note that the OMF specifies that the vfuncptr will
// be emitted as the first field after the bases
if (pName->clsmask & CLS_virtintro) {
// we are looking for the introducing virtual
// method. We need to find a method with the
// correct name of the correct type index that
// is introducing.
MHOmfUnLock (hField);
if (IsIntroVirt (count, newindex, &vtabind) == FALSE) {
cmpflag = 1;
}
else {
if (FCN_VFPTYPE (pvF) == T_NOTYPE) {
FCN_VFPTYPE (pvF) = vfpType;
FCN_VFPTYPE (pName->pv) = vfpType;
FCN_VTABIND (pvF) = vtabind;
FCN_VTABIND (pName->pv) = vtabind;
}
cmpflag = 0;
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data);
}
else {
// save the type index of the method list, the
// count of methods overloaded on this name,
// the type index of the vfuncptr. Also,
// increment the number of possible features by
// the overload count
pSymClass->possibles = count;
pName->possibles += count;
pSymClass->mlist = newindex;
pSymClass->vfpType = vfpType;
}
}
}
break;
case LF_NESTTYPE:
newindex = ((plfNestType)(pField + fSkip))->index;
fSkip += offsetof (lfNestType, Name);
pc = pField + fSkip;
fSkip += *(pField + fSkip) + sizeof (char);
if (pName->clsmask & CLS_ntype) {
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
// set type of typedef symbol
pSymClass->possibles = 1;
pName->possibles++;
EVAL_STATE (pvF) = EV_type;
EVAL_TYP(pvF) = newindex;
}
else if (pName->clsmask & CLS_enumerate) {
// check if the nested type is an enum. if it is
// we gotta search thru its field list for a matching
// enumerate
// sps - 9/14/92
HTYPE hEnum, hEnumField; // nested handle
plfEnum pEnum;
char *pEnumField; // field list of the enum record
ushort enumCount;
uint fSkip = 0; // offset in the field list
uint anchor; // offset in the field list to start of type
if (CV_IS_PRIMITIVE(newindex)) {
break;
}
if ((hEnum = THGetTypeFromIndex (EVAL_MOD (pvBase),
newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pEnum = (plfEnum) (&((TYPPTR)MHOmfLock (hEnum))->leaf);
if (pEnum->leaf == LF_ENUM) {
if (pEnum->property.fwdref) {
eval_t localeval = *pvBase;
neval_t nv = &localeval;
// forward ref - look for the definition of the UDT
if ((newindex = GetUdtDefnTindex (newindex, pvBase, (char *)&(pEnum->Name[0]))) != T_NOTYPE) {
if ((hEnum = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pEnum = (plfEnum) (&((TYPPTR)MHOmfLock (hEnum))->leaf);
}
else
break; // No Fwd ref found... no CVInfo for nested type... proceed with search [rm]
}
if ((hEnumField = THGetTypeFromIndex (EVAL_MOD (pvBase),
pEnum->field)) == 0) {
if ( BindingBP ) {
break;
}
else {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
}
pEnumField = (char *)(&((TYPPTR)MHOmfLock (hEnumField))->data);
for (enumCount = pEnum->count; enumCount > 0; enumCount--) {
fSkip += SkipPad(((uchar *)pEnumField) + fSkip);
anchor = fSkip;
DASSERT ((((plfEasy)(pEnumField + fSkip))->leaf) == LF_ENUMERATE);
access = ((plfEnumerate)(pEnumField + fSkip))->attr;
fSkip += offsetof (lfEnumerate, value);
value = (ulong) RNumLeaf (pEnumField + fSkip, &fSkip);
pc = pEnumField + fSkip;
fSkip += *(pEnumField + fSkip) + sizeof (char);
if ((cmpflag = fnCmp ((LPSSTR) pName, NULL, pc, pExState->state.fCase)) == 0) {
EVAL_MOD (pvF) = SHHMODFrompCXT (&pName->CXTT);
SetNodeType (pvF, pEnum->utype);
EVAL_STATE (pvF) = EV_constant;
EVAL_LONG (pvF) = value;
// save the casting data for the this pointer
pSymClass->access = access;
pSymClass->possibles = 1;
pName->possibles++;
break;
}
}
MHOmfUnLock (hEnumField);
}
MHOmfUnLock (hEnum);
}
}
break;
default:
pExState->err_num = ERR_BADOMF;
retval = SCN_notfound;
}
#ifdef NEVER
// if ((cnt == 0) && ************ (pName->tTypeDef != 0)) {
if ((cnt == 0) && (pName->tTypeDef != 0)) {
// we found a typedef name that was not hidden by
// a member or method name
}
#endif
if (cmpflag == 0) {
pSymClass->s.viable = TRUE;
retval = SCN_found;
break;
}
}
#endif
if (hField != 0) {
MHOmfUnLock ((HDEP)hField);
}
return (retval);
}
/** SetBPValue - set the breakpoint list from a class search
*
* status = SetBPValue (pName)
*
* Entry pName = pointer to structure describing search
* pSymCl = pointer to class element
*
* Exit pName updated to reflect found feature
* this pointer inserted in bind tree if feature is part of
* the class pointed to by this pointer of method
*
* Returns SCN_rewrite if this pointer inserted (rebind required)
* SCN_found if no error
* SCN_error otherwise
*/
LOCAL SCN_t
SetBPValue (
psearch_t pName
)
{
peval_t pv;
DASSERT ((pName->cFound == 0) && (pName->hFound == 0));
if (pSymClass->mlist != T_NOTYPE) {
if ((pName->possibles == 1) || (bArgList != 0)) {
switch (MatchMethod (pName, pSymClass)) {
default:
DASSERT (FALSE);
case MTH_error:
return (SCN_error);
case MTH_found:
break;
}
}
else {
// we have a list of functions and no argument list.
// This means that we have an ambiguous breakpoint
// and need to add the functions to the breakpoint
// list for user disambiguation. Basically what
// we are going to do is force all of the methods
// into the breakpoint list and let later
// binding resolve any errors.
return (OverloadToAmbList (pName, pSymClass));
}
}
// at this point, the following values are set
// pName->addr = address of method if not virtual method
// pName->typeOut = type index of method
// pName->hSym = handle of symbol for function
pv = &pSymClass->evalP;
if ((FCN_ATTR (pv).mprop == CV_MTvirtual) ||
(FCN_ATTR (pv).mprop == CV_MTintro)) {
pExState->err_num = ERR_NOVIRTUALBP;
return (SCN_error);
}
pv = pName->pv;
*pv = pSymClass->evalP;
EVAL_ACCESS (pv) = (uchar)(pSymClass->access.access);
pName->typeOut = EVAL_TYP (pv);
// save the offset of a class member
// (caviar #1756) --gdp 9-10-92
if (pName->bnOp) {
peval_t pvOp = &(pnodeOfbnode(pName->bnOp))->v[0];
EVAL_IS_MEMBER(pvOp) = TRUE;
MEMBER_OFFSET(pvOp) = pName->initializer == INIT_right ?
pSymClass->offset : 0;
}
return (SCN_found);
}
LOCAL SCN_t
OverloadToAmbList (
psearch_t pName,
psymclass_t pSymCl
)
{
SCN_t retval;
// add the first list of methods
if ((retval = MethodsToAmbList (pName, pSymCl)) != SCN_found) {
return (retval);
}
// loop through the remaining class descriptors adding them to the list
while (pName->hAmbCl != 0) {
MoveSymCl (pName->hAmbCl);
if ((retval = MethodsToAmbList (pName,pSymCl)) != SCN_found) {
return (retval);
}
}
if (pExState->ambiguous == 0) {
// no instantiated function has been found
return (SCN_notfound);
}
SymToNode (pName);
DASSERT (EVAL_TYP (pName->pv) != T_NOTYPE);
return (SCN_found);
}
/** MethodsToAmbList - add a list of methods to ambiguous breakpoints
*
* flag = MethodsToAmbList (pName, pSymCl)
*
* Entry pName = pointer to search descriptor
* pSymCl = pointer to symbol class structure
*
* Exit methods added to list of ambiguous breakpoints
*
* Returns SCN_found if methods added
* SCN_error if error during addition
*
*/
LOCAL SCN_t
MethodsToAmbList (
psearch_t pName,
psymclass_t pSymCl
)
{
HTYPE hMethod;
pmlMethod pMethod;
uint skip;
CV_fldattr_t attr;
CV_typ_t type;
ushort vtabind;
HDEP hQual;
peval_t pvF;
ushort count = pSymCl->possibles;
peval_t pvB;
HMOD hMod;
HDEP hTemp;
psearch_t pTemp;
bool_t retval;
pvB = &pSymCl->symbase[pSymCl->CurIndex].Base;
hMod = EVAL_MOD (pvB);
// we now walk the list of methods adding each method to the list of
// ambiguous breakpoints
if ((hMethod = THGetTypeFromIndex (hMod, pSymCl->mlist)) == (HTYPE) NULL) {
DASSERT (FALSE);
return (MTH_error);
}
// set the number of methods overloaded on this name and the index into
// the method list
skip = 0;
while (count-- > 0) {
// lock the omf record, extract information for the current entry in
// the method list and increment to field for next method
pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1);
pMethod = (pmlMethod)((uchar *)pMethod + skip);
attr = pMethod->attr;
type = pMethod->index;
skip += sizeof (mlMethod);
if (pMethod->attr.mprop == CV_MTintro) {
vtabind = (short)RNumLeaf (((char *)pMethod) + skip, &skip);
}
else {
vtabind = 0;
}
MHOmfUnLock (hMethod);
// now add the method to the list
pvF = &pSymCl->evalP;
EVAL_MOD (pvF) = hMod;
DASSERT (type != T_NOTYPE);
if (SetNodeType (pvF, type) == FALSE) {
return (MTH_error);
}
else {
FCN_ATTR (pvF) = attr;
FCN_VTABIND (pvF) = vtabind;
FCN_VFPTYPE (pvF) = pSymCl->vfpType;
pName->best.match = type;
if (((hQual = GenQualName (pName, pSymCl)) == 0) ||
(SearchQualName (pName, pSymCl, hQual, TRUE) == FALSE)) {
if (hQual != 0) {
MHMemFree (hQual);
}
return (SCN_error);
}
MHMemFree (hQual);
}
/*
* Function must be present in the exe and the one we found must
* be of the correct type (it will find others for some reason)
* or else it should be ignored. We will conver all possible
* function types so throwing this one away should make no
* difference
*/
if ((FCN_NOTPRESENT (pvF) == FALSE) && (EVAL_TYP( pvF ) == type)) {
if (pExState->ambiguous == 0) {
// we have found the first function. We need to set all of
// the return values in the pointer to the search entry
pExState->ambiguous = pName->bn;
// at this point, the following values are set
// pName->addr = address of method if not virtual method
// pName->typeOut = type index of method
// pName->hSym = handle of symbol for function
*pName->pv = pSymClass->evalP;
EVAL_ACCESS (pName->pv) = (uchar)(pSymClass->access.access);
pName->typeOut = EVAL_TYP (pName->pv);
pName->hSym = EVAL_HSYM (pvF);
}
else {
if ((hTemp = MHMemAllocate (sizeof (search_t))) == 0) {
pExState->err_num = ERR_NOMEMORY;
return (SCN_error);
}
pTemp = MHMemLock (hTemp);
*pTemp = *pName;
pTemp->hSym = pvF->hSym;
retval = AmbToList (pTemp);
MHMemUnLock (hTemp);
MHMemFree (hTemp);
if (retval == FALSE) {
return (SCN_error);
}
}
}
}
if (pExState->ambiguous == 0) {
return SCN_notfound;
}
return (SCN_found);
}
/** SetValue - set the result of the class search
*
* status = SetValue (pName)
*
* Entry pName = pointer to structure describing search
* pSymClass = pointer to class element
*
* Exit pName updated to reflect found feature
* this pointer inserted in bind tree if feature is part of
* the class pointed to by this pointer of method
*
* Returns SCN_rewrite if this pointer inserted (rebind required)
* SCN_found if no error
* SCN_error otherwise
*/
LOCAL SCN_t
SetValue (
psearch_t pName
)
{
peval_t pv;
peval_t pvOp;
SCN_t retval;
HDEP hQual;
// When we get here, the situation is a bit complex.
// If we are not binding breakpoints, the following conditions
// must be true:
// pName->hAmbCl = 0 (only one feature can remain after dominance)
// pName->cFound = 0
// pName->hFound = 0
// pSymClass->s.viable = TRUE
// If the feature is a data item (pSymClass->mlist == T_NOTYPE), then
// pName->possibles = 1
// If the feature is a method, then
// pName->possibles = number of overloads on name
// pSymClass->mlist = type index of member list
// bArgList = based pointer to argument list tree (cannot be 0)
// Argument matching must result in a best match to a single method
//
// If we are binding breakpoints, the following conditions must be true
// pName->cFound = 0
// pName->hFound = 0
// pName->possibles = total number of methods in pSymClass and
// pName->hAmbCl
// pName->hAmbCl > 0 if two or more features survived dominance
// Each of the features in pSymClass and the pName->hAmbCl list
// must be a method list (pSymClass->mlist != T_NOTYPE)
//
// If we do not have an argument list, then we accept all methods in
// pSymClass->mlist and pName->hAmbCl.mlist. The number of methods is
// pName->possibles.
//
// If we do have an argument list, then we accept all methods in
// pSymClass->mlist and pName->hAmbCl.mlist that are exact matches
// for the argument list. Implicit conversions are not considered.
// The number of methods must less than 1 + number of elements in the
// list pName->hAmbCl and must be less than or equal to pName->possibles.
if (BindingBP == TRUE) {
// call the set of routines that will process breakpoints on methods
// of a class, the inheritance tree of the class and the derivation
// tree of the class. If the routine returns without error, pName
// describes the first function breakpoint and hTMList describes the
// remainder of the list of methods that match the function and
// signature if one is specified.
return (SetBPValue (pName));
}
// At this point, there must be only one class after dominance resolution,
// the count of the found items must be zero, and the handle of the found
// item list must be null. Otherwise there was a failure in dominance
// resolution.
DASSERT ((pName->hAmbCl == 0) &&
(pName->cFound == 0) &&
(pName->hFound == 0) &&
(pSymClass->s.viable == TRUE));
if (pSymClass->mlist == T_NOTYPE) {
DASSERT (pName->possibles == 1);
}
else if (bArgList == 0) {
pExState->err_num = ERR_NOARGLIST;
return (SCN_error);
}
// if we are processing C++, then we can allow for overloaded methods
// which is specified by the type index of the method list not being
// zero. If this is true, then we select the best of the overloaded
// methods.
if (pSymClass->mlist != T_NOTYPE) {
switch (MatchMethod (pName, pSymClass)) {
default:
DASSERT (FALSE);
case MTH_error:
return (SCN_error);
case MTH_found:
// at this point, the following values are set
// pName->addr = address of method if not virtual method
// pName->typeOut = type index of method
// pName->hSym = handle of symbol for function
pv = &pSymClass->evalP;
if (FCN_ATTR (pv).mprop == CV_MTvirtual) {
// search to introducing virtual method
if ((retval = FindIntro (pName)) != SCN_found) {
return (retval);
}
}
break;
}
}
// the symbol is a data member of the class (C or C++). If an
// explict class was not specified and the current context is
// implicitly a class (we are in the scope of the method of the class),
// then we rewrite the tree to change the symbol reference to this->symbol
if ((pName->initializer != INIT_base) &&
(pName->initializer != INIT_sym) &&
(pName->ExpClass == 0)) {
//DASSERT (FALSE);
pExState->err_num = ERR_INTERNAL;
return (SCN_error);
}
else if ((pName->ExpClass == 0) && (ClassImp != 0) &&
(pName->initializer != INIT_base)) {
// if the feature is a member of *this class of a method, then
// we need to rewrite
// feature
// to
// this->feature
// The calling routine will need to rebind the expression
InsertThis (pName);
return (SCN_rewrite);
}
// the initializer for the search must be INIT_right or INIT_base.
// by the time we get to here we know that bnOp is the based pointer to
// the node that will receive the casting expression and pv points
// to the feature node.
pv = pName->pv;
pvOp = &(pnodeOfbnode(pName->bnOp)->v[0]);
switch (pName->initializer) {
case INIT_right:
EVAL_CBTOK(&pSymClass->evalP) = EVAL_CBTOK(pv);
EVAL_ITOK(&pSymClass->evalP) = EVAL_ITOK(pv);
*pv = pSymClass->evalP;
EVAL_ACCESS (pv) = (uchar)(pSymClass->access.access);
pName->typeOut = EVAL_TYP (pv);
EVAL_IS_MEMBER (pvOp) = TRUE;
MEMBER_TYPE (pvOp) = EVAL_TYP (pv);
MEMBER_OFFSET (pvOp) = pSymClass->offset;
MEMBER_ACCESS (pvOp) = pSymClass->access;
if ((pSymClass->s.isvbase == TRUE) || (pSymClass->s.isivbase == TRUE)) {
MEMBER_VBASE (pvOp) = pSymClass->s.isvbase;
MEMBER_IVBASE (pvOp) = pSymClass->s.isivbase;
MEMBER_VBPTR (pvOp) = pSymClass->vbptr;
MEMBER_VBPOFF (pvOp) = pSymClass->vbpoff;
MEMBER_VBIND (pvOp) = pSymClass->vbind;
}
break;
case INIT_base:
*pv = pSymClass->symbase[pSymClass->CurIndex].Base;
EVAL_ACCESS (pv) = (uchar)(pSymClass->symbase[pSymClass->
CurIndex].attrBC.access);
pName->typeOut = EVAL_TYP (pv);
EVAL_IS_MEMBER (pvOp) = TRUE;
EVAL_ACCESS (pvOp) = (uchar)(pSymClass->symbase[pSymClass->
CurIndex].attrBC.access);
MEMBER_OFFSET (pvOp) = 0;
break;
default:
DASSERT (FALSE);
return (SCN_error);
}
if (EVAL_IS_STMEMBER (pv) == FALSE) {
// the feature is not a static data member of the class
return (GenQualExpr (pName));
}
else {
// the feature is a static member so we need to generate the
// qualified path and search for a symbol of the correct type
// so we can set the address
if (((hQual = GenQualName (pName, pSymClass)) == 0) ||
(SearchQualName (pName, pSymClass, hQual, FALSE) == FALSE)) {
if (hQual != 0) {
MHMemFree (hQual);
}
return (SCN_error);
}
*pv = pSymClass->evalP;
EVAL_STATE (pv) = EV_lvalue;
MHMemFree (hQual);
return (SCN_found);
}
}
// Support routines
/** AddETConst - add evalthisconst node
*
* pn = AddETConst (pnP, off, btype)
*
* Entry pnP = pointer to previous node
*
* Exit OP_evalthisconst node added to bind tree
* current node linked to pnP as left child if pnP != NULL
* pTree->node_next advanced
* btype = type of the base class
*
* Returns pointer to node just allocated
*/
LOCAL pnode_t
AddETConst (
pnode_t pnP,
OFFSET off,
CV_typ_t btype
)
{
pnode_t pn;
padjust_t pa;
pn = (pnode_t)(((char *)pTree) + pTree->node_next);
pa = (padjust_t)(&pn->v[0]);
_fmemset (pn, 0, sizeof (node_t) + sizeof (adjust_t));
NODE_OP (pn) = OP_thisconst;
pa->btype = btype;
pa->disp = off;
if (pnP != NULL) {
NODE_LCHILD (pnP) = bnodeOfpnode(pn);
}
pTree->node_next += sizeof (node_t) + sizeof (adjust_t);
return (pn);
}
/** AddETInit - add evalthisinit node
*
* pn = AddETInit (pnP, btype)
*
* Entry pnP = pointer to previous node
*
* Exit OP_evalthisinit node added to bind tree
* current node linked to pnP as left child if pnP != NULL
* pTree->node_next advanced
* btype = type of the base class
*
* Returns pointer to node just allocated
*/
LOCAL pnode_t
AddETInit (
pnode_t pnP,
CV_typ_t btype
)
{
pnode_t pn;
padjust_t pa;
pn = (pnode_t)(((char *)pTree) + pTree->node_next);
pa = (padjust_t)(&pn->v[0]);
_fmemset (pn, 0, sizeof (node_t) + sizeof (adjust_t));
NODE_OP (pn) = OP_thisinit;
pa->btype = btype;
if (pnP != NULL) {
NODE_LCHILD (pnP) = bnodeOfpnode(pn);
}
pTree->node_next += sizeof (node_t) + sizeof (adjust_t);
return (pn);
}
/** AddETExpr - add evalthisexpr node
*
* pn = AddETExpr (pnP, vbptr, vbpoff, vbind, btype)
*
* Entry pnP = pointer to previous node
* vbptr = type index of virtual base pointer
* vboff = offset of vbptr from address point
* vbdisp = offset of displacement in virtual base table
* btype = type of the base class
*
* Exit OP_evalthisconst node added to bind tree
* current node linked to pnP as left child if pnP != NULL
* pTree->node_next advanced
*
* Returns pointer to node just allocated
*
* The evaluation of this node will result in
*
* ab = (ap * vbpoff) + *(*(ap +vbpoff) + vbdisp)
* where
* ab = address of base class
* ap = current address point
*/
LOCAL pnode_t
AddETExpr (
pnode_t pnP,
CV_typ_t vbptr,
OFFSET vbpoff,
OFFSET vbdisp,
CV_typ_t btype
)
{
pnode_t pn;
padjust_t pa;
pn = (pnode_t)(((char *)pTree) + pTree->node_next);
pa = (padjust_t)(&pn->v[0]);
_fmemset (pn, 0, sizeof (node_t) + sizeof (adjust_t));
NODE_OP (pn) = OP_thisexpr;
pa->btype = btype;
pa->disp = vbdisp;
pa->vbpoff = vbpoff;
pa->vbptr = vbptr;
if (pnP != NULL) {
NODE_LCHILD (pnP) = bnodeOfpnode(pn);
}
pTree->node_next += sizeof (node_t) + sizeof (adjust_t);
return (pn);
}
/*** AddVBList - Add virtual bases to searched or dominated list
*
* status = AddVBList (pSymClass, ppList, phMem)
*
* Entry pSymClass = pointer to base class path list structure
* ppList = pointer to dominated or searched list
* phMem = pointer to handle for ppList
*
* Exit virtual bases added to list
*
* Return SCN_found if all bases added to list
* SCN_error if bases could not be added
*/
LOCAL SCN_t
AddVBList (
psymclass_t pSymClass,
pdombase_t *ppList,
HDEP * phList
)
{
ushort cnt; // count of number of elements in struct
HTYPE hField; // handle to type record for struct field list
char *pField; // pointer to field list
uint fSkip = 0; // offset in the field list
uint anchor; // offset in the field list to start of type
CV_typ_t newindex;
ushort retval = SCN_found;
bool_t termflag = FALSE;
peval_t pvBase = &pSymClass->symbase[pSymClass->CurIndex].Base;
ushort pad;
// set hField to the handle of the field list for the class
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), CLASS_FIELD (pvBase))) == 0) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
// walk field list for the class
for (cnt = CLASS_COUNT (pvBase); cnt > 0; cnt--) {
if ((pad = *(((char *)pField) + fSkip)) >= LF_PAD0) {
// there is a pad field
fSkip += pad & 0x0f;
}
anchor = fSkip;
switch (((plfEasy)(pField + fSkip))->leaf) {
case LF_INDEX:
// switch to new type record because compiler split it up
newindex = ((plfIndex)(pField + fSkip))->index;
MHOmfUnLock (hField);
if ((hField = THGetTypeFromIndex (EVAL_MOD (pvBase), newindex)) == 0) {
pExState->err_num = ERR_INTERNAL;
return (SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock (hField))->data[0]);
fSkip = 0;
// the LF_INDEX is not part of the field count
cnt++;
break;
case LF_BCLASS:
// skip direct base class
fSkip += offsetof (lfBClass, offset[0]);
RNumLeaf (pField + fSkip, &fSkip);
break;
case LF_VBCLASS:
case LF_IVBCLASS:
newindex = ((plfVBClass)(pField + fSkip))->index;
if ((retval = AddVBType (ppList, phList, newindex)) == SCN_error) {
termflag = TRUE;
break;
}
fSkip += offsetof (lfVBClass, vbpoff[0]);
RNumLeaf (pField + fSkip, &fSkip);
RNumLeaf (pField + fSkip, &fSkip);
break;
default:
termflag = TRUE;
break;
}
if (termflag == TRUE) {
break;
}
}
MHOmfUnLock (hField);
return (retval);
}
/*** AddVBType - Add virtual base to list
*
* status = AddVBType (ppList, phList, type)
*
* Entry ppList = pointer to dominated or searched list
* phList = pointer to handle for ppList
* type = type index
*
* Exit type added to list
*
* Return SCN_found if all bases added to list
* SCN_error if bases could not be added
*/
LOCAL SCN_t
AddVBType (
pdombase_t *ppList,
HDEP *phList,
CV_typ_t type
)
{
ushort i;
bool_t add = TRUE;
ushort len;
pdombase_t pList = *ppList;
for (i = 0; i < pList->CurIndex; i++) {
if (type == pList->dom[i]) {
add = FALSE;
break;
}
}
if (add == TRUE) {
if (pList->CurIndex >= pList->MaxIndex) {
len = sizeof (dombase_t) + (pList->MaxIndex + 10) * sizeof (CV_typ_t);
MHMemUnLock (*phList);
if ((*phList = MHMemReAlloc (*phList, len)) == 0) {
pExState->err_num = ERR_NOMEMORY;
pList = MHMemLock (*phList);
return (SCN_error);
}
else {
pList = MHMemLock (*phList);
pVBDom->MaxIndex += 10;
}
}
pList->dom[pList->CurIndex++] = type;
}
return (SCN_found);
}
/** AmbFromList - add get next ambiguous symbol from list
*
* status = AmbFromList (pName)
*
* Entry pName = pointer to list describing search
*
* Exit breakpoint added to list of breakpoints
* pName reset to continue breakpoint search
*
* Returns HR_found if breakpoint added
* HR_error if breakpoint could not be added to list
*/
LOCAL ushort
AmbFromList (
psearch_t pName
)
{
psearch_t pBPatch;
pBPatch = MHMemLock (hBPatch);
*pName = *pBPatch;
MHMemUnLock (hBPatch);
pName->pv = &(pnodeOfbnode(pName->bn)->v[0]);
EVAL_HSYM (pName->pv) = pName->hSym;
if ((SymToNode (pName) == TRUE) && (PushStack (pName->pv) == TRUE)) {
return (HR_found);
}
else {
return (HR_error);
}
}
/** AmbToList - add ambiguous symbol to list
*
* fSuccess = AmbToList (pName)
*
* Entry pName = pointer to list describing search
*
* Exit ambiguous symbol added to list pointed to by pTMList
* pTMLbp
*
* Returns TRUE if symbol added
* FALSE if error
*/
LOCAL bool_t
AmbToList (
psearch_t pName
)
{
HDEP hBPatch;
psearch_t pBPatch;
if (iBPatch >= (USHORT)pTMLbp->cTMListMax) {
// the back patch list has filled the TM list
if (!GrowTMList ()) {
pExState->err_num = ERR_NOMEMORY;
return (FALSE);
}
}
if ((hBPatch = MHMemAllocate (sizeof (search_t))) != 0) {
pTMList[iBPatch++] = hBPatch;
pBPatch = MHMemLock (hBPatch);
*pBPatch = *pName;
MHMemUnLock (hBPatch);
return (TRUE);
}
else {
pExState->err_num = ERR_NOMEMORY;
return (FALSE);
}
}
/** ClAmbToList - add class ambiguous symbol to list
*
* status = ClAmbToList (pName)
*
* Entry pName = pointer to list describing search
*
* Exit ambiguous symbol added to list pointed to by pTMList
* pTMLbp
* pName reset to continue breakpoint search
*
* Returns HR_... describing state
*/
LOCAL HR_t
ClAmbToList (
psearch_t pName
)
{
HDEP hSearch;
psearch_t pSearch;
HR_t retval;
HDEP hevalT;
PopStack ();
if (pExState->ambiguous == 0) {
// this is the first breakpoint symbol found.
// indicate the only node in the tree that is
// allowed ambiguity and initialize list of
// symbols for later back patching into duplicated
// expression trees. We save the initial search packet
// so that the first symbol will be set into the breakpoint
// list.
pExState->ambiguous = pName->bn;
if ((hSearch = MHMemAllocate (sizeof (search_t))) == 0) {
pExState->err_num = ERR_NOMEMORY;
return (HR_error);
}
if ((hSearch = MHMemAllocate (sizeof (eval_t))) == 0) {
MHMemFree (hSearch);
pExState->err_num = ERR_NOMEMORY;
return (HR_error);
}
pSearch = MHMemLock (hSearch);
*pSearch = *pName;
pSearch->pv = (peval_t)MHMemLock (hevalT);
retval = SearchSym (pSearch);
PushStack (pName->pv);
MHMemUnLock (hSearch);
MHMemFree (hSearch);
MHMemUnLock (hevalT);
MHMemFree (hevalT);
return (retval);
}
else if (pExState->ambiguous != pName->bn) {
// there has already been a ambiguous symbol that is
// not at this node in the tree
pExState->err_num = ERR_BPAMBIGUOUS;
return (HR_error);
}
else {
if (AmbToList (pName) == FALSE) {
return (HR_error);
}
// reset search to allow more symbols
pName->possibles = 0;
return (SearchSym (pName));
}
}
/** DupSymCl - duplicate symbol class structure and link to list
*
* DupSymCl (pName);
*
* Entry pName = handle of structure describing search
* *pSymClass = symbol class structure
*
* Exit *pSymClass = duplicated and linked to list pName->hFound
* pSymClass->s.viable = FALSE
*
* Returns SCN_found if pSymClass duplicated
* SCN_error if unable to allocate memory for duplication
*/
LOCAL SCN_t
DupSymCl (
psearch_t pName
)
{
HDEP hSymCl;
psymclass_t pSymCl;
ushort size;
size = (ushort) (sizeof (symclass_t) + (pSymClass->CurIndex + 1) * sizeof (symbase_t));
if ((hSymCl = MHMemAllocate (size)) == 0) {
pExState->err_num = ERR_NOMEMORY;
return (SCN_error);
}
pSymCl = MHMemLock (hSymCl);
_fmemmove (pSymCl, pSymClass, size);
pSymCl->MaxIndex = (ushort)(pSymCl->CurIndex + 1);
pSymCl->hNext = pName->hFound;
pName->hFound = hSymCl;
pName->cFound++;
pSymClass->s.viable = FALSE;
MHMemUnLock (hSymCl);
return (SCN_found);
}
/** FindIntro - find introducing virtual method
*
* status = FindIntro (pName)
*
* Entry pName = structure describing search
* pSymClass = structure describing class search
*
* Exit pSymClass updated to reflect introducing virtual method
*
* Returns SCN_found if introducing virtual method found
* SCN_error if introducing virtual method not found
*/
LOCAL SCN_t
FindIntro (
psearch_t pName
)
{
ushort oldmask;
SCN_t retval;
oldmask = pName->clsmask;
// limit searches to introducing virtual methods
// the CLS_vfunc is set so that we pick up the vfuncptr information
pName->clsmask = CLS_virtintro | CLS_vfunc | CLS_method;
retval = SearchBases (pName);
pName->clsmask = oldmask;
return (retval);
}
/*** GenQualName - generate qualified method name
*
* handle = GenQualName (pName, pSymClass)
*
* Entry pSymCLass = pointer to struct describing search
*
* Exit qualified function name generated
*
* Returns 0 if name string not generated
* handle if name string generated
*/
LOCAL HDEP
GenQualName (
psearch_t pName,
psymclass_t pSymCl
)
{
HDEP hQual;
char *pQual;
uint buflen = 255;
uint len;
uint fSkip;
char *pField; // pointer to field list
HTYPE hBase; // handle to type record for base class
char *pc;
short i;
peval_t pL;
if ((hQual = MHMemAllocate (buflen + 1)) == 0) {
// unable to allocate memory
pExState->err_num = ERR_NOMEMORY;
return (0);
}
pQual = MHMemLock (hQual);
_fmemset (pQual, 0, 256);
// walk up list of search structures adding qualifiers
for (i = 0; i <= pSymCl->CurIndex; i++) {
if (CLASS_PROP (&pSymCl->symbase[i].Base).cnested == TRUE) {
NOTTESTED (FALSE);
}
if ((pSymCl->symbase[i].clsmask & CLS_virtintro) != 0) {
// if the search turned into a search for the introducing virtual
// function, break out of this loop so that the method name is
// correct
break;
}
pL = &pSymCl->symbase[i].Base;
}
// copy name of last class encountered
if ((hBase = THGetTypeFromIndex (EVAL_MOD (pL), EVAL_TYP (pL))) == 0) {
pExState->err_num = ERR_INTERNAL;
return (HDEP)(SCN_error);
}
pField = (char *)(&((TYPPTR)MHOmfLock ((HDEP)hBase))->leaf);
switch (((plfClass)pField)->leaf) {
case LF_CLASS:
case LF_STRUCTURE:
fSkip = offsetof (lfClass, data[0]);
RNumLeaf (pField + fSkip, &fSkip);
pc = pField + fSkip;
break;
case LF_UNION:
fSkip = offsetof (lfUnion, data[0]);
RNumLeaf (pField + fSkip, &fSkip);
pc = pField + fSkip;
break;
default:
DASSERT (FALSE);
MHOmfUnLock ((HDEP)hBase);
MHMemUnLock (hQual);
return (hQual);
}
len = *pc++;
if ((len + 2) <= buflen) {
_fmemcpy (pQual, pc, len);
pQual += len;
*pQual++ = ':';
*pQual++ = ':';
buflen -= len + 2;
}
_fmemcpy (pQual, pName->sstr.lpName, pName->sstr.cb);
MHOmfUnLock ((HDEP)hBase);
MHMemUnLock (hQual);
return (hQual);
}
/*** pvThisFromST - generate expression for null path to qualified name
*
* status = pvThisFromST (bnOp)
*
* Entry bnOp = node to add init expression to
*
* Exit qualified path expression generated
*
* Returns TRUE if expression generated
* FALSE if no memory
*/
bool_t
pvThisFromST (
bnode_t bnOp
)
{
uint len;
pnode_t Parent;
peval_t pvOp;
int diff;
if (ST == NULL) {
return (FALSE);
}
// we need to generate an expression tree attached to the operator node
// which will compute the null this pointer adjustment from ST. This
// routine is used for pClass->Class::member
len = sizeof (node_t) + sizeof (adjust_t);
if ((diff = pTree->size - pTree->node_next - len) < 0) {
if (!GrowETree ((uint) (-diff))) {
pExState->err_num = ERR_NOMEMORY;
return (FALSE);
}
if (bnCxt != 0) {
// the context was pointing into the expression tree.
// since the expression tree could have been reallocated,
// we must recompute the context pointer
pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
}
}
pvOp = &pnodeOfbnode(bnOp)->v[0];
EVAL_IS_MEMBER (pvOp) = TRUE;
MEMBER_THISEXPR (pvOp) = pTree->node_next;
Parent = NULL;
// now add the node that causes pvThis to be initialized with the
// value of ST.
AddETInit (Parent, EVAL_TYP (ST));
return (TRUE);
}
/*** GenQualExpr - generate expression for path to qualified name
*
* status = GenQualExpr (pName)
*
* Entry pName = pointer to struct describing search
* pSymClass = pointer to class path structure
*
* Exit qualified path expression generated
*
* Returns SCN_found is expression generated
* SCN_error if no memory
*/
LOCAL SCN_t
GenQualExpr (
psearch_t pName
)
{
short i;
peval_t pvOp;
uint len;
pnode_t Parent;
int diff;
peval_t pvB;
CV_typ_t btype;
OFFSET off;
uint pvOff = 0;
// we need to generate an expression tree attached to the operator node
// which will compute the this pointer adjustment. The number
// of nodes is potentially the number of base classes + an
// initializer.
// M00OPTIMIZE - if the final base is a direct or indirect virtual base
// M00OPTIMIZE - of the inital class, then the entire expression can be
// M00OPTIMIZE - reduced to one node + the initializer
len = (pSymClass->CurIndex + 2) * (sizeof (node_t) + sizeof (adjust_t));
pvOp = &(pnodeOfbnode(pName->bnOp)->v[0]);
if ((diff = pTree->size - pTree->node_next - len) < 0) {
if (((char *)(pName->pv) >= (char *)pTree) &&
((char *)(pName->pv) < ((char *)pTree) + pTree->size)) {
pvOff = ((char *)pName->pv) - ((char *)pTree);
}
if (!GrowETree ((uint) (-diff))) {
pExState->err_num = ERR_NOMEMORY;
return (SCN_error);
}
if (bnCxt != 0) {
// the context was pointing into the expression tree.
// since the expression tree could have been reallocated,
// we must recompute the context pointer
pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
}
if (pvOff != 0) {
pName->pv = (peval_t)(((char *)pTree) + pvOff);
}
pvOp = &(pnodeOfbnode(pName->bnOp)->v[0]);
}
// walk the path backwards generating the expression required to do
// the adjustment. The backwards walk is because evaluation is depth
// first.
MEMBER_THISEXPR (pvOp) = pTree->node_next;
Parent = NULL;
for (i = pSymClass->CurIndex; i > 0; i--) {
pvB = &pSymClass->symbase[i].Base;
btype = EVAL_TYP (pvB);
off = pSymClass->symbase[i].thisadjust;
if (pSymClass->symbase[i].virtual == TRUE) {
Parent = AddETExpr (Parent, pSymClass->symbase[i].vbptr,
pSymClass->symbase[i].vbpoff, off, btype);
}
else {
Parent = AddETConst (Parent, off, btype);
}
}
// add the first real adjustment if necessary. What is really happening
// here is that the the expression was of the form x.CLASS::member and
// we need an adjustment from the object to the start of the base class
pvB = &pSymClass->evalP;
btype = EVAL_TYP (pvB);
if ((EVAL_STATE (pvB) == EV_type) && EVAL_IS_CLASS (pvB)) {
Parent = AddETConst (Parent, pSymClass->offset, btype);
}
// now add the node that causes pvThis to be initialized with the
// value of ST.
pvB = &pSymClass->symbase[i].Base;
btype = EVAL_TYP (pvB);
Parent = AddETInit (Parent, btype);
return (SCN_found);
}
/** GetArgType - get type of argument to function
*
* fSuccess = GetArgType (pvF, argn, ptype);
*
* Entry pvF = pointer to function description
* argn = argument index (0-based)
* ptype = pointer to location to store type
*
* Exit *ptype = type of argument
* *ptype = 0 if vararg
*
* Returns FARG_error if error
* FARG_none if no arguments
* FARG_vararg if varargs allowed
* FARG_exact if exact list
*/
farg_t
GetArgType (
peval_t pvF,
short argn,
CV_typ_t *type
)
{
HTYPE hList; // handle of the type list
plfArgList pList = NULL;
register farg_t retval;
if (FCN_PCOUNT (pvF) == 0) {
// there are no formals. We need to check for varargs
*type = 0;
if (FCN_VARARGS (pvF) == TRUE) {
return (FARG_vararg);
}
else {
return (FARG_none);
}
}
// set hList to the handle of the type list
if ((hList = THGetTypeFromIndex (EVAL_MOD (pvF), FCN_PINDEX (pvF))) == HNULL) {
DASSERT (FALSE);
return (FARG_error);
}
if (argn >= FCN_PCOUNT (pvF) - 1) {
// this argument can possibly be a vararg.
if (FCN_VARARGS (pvF) == TRUE) {
*type = 0;
retval = FARG_vararg;
}
else if (argn > FCN_PCOUNT (pvF)) {
// varargs are not allowed and the maximum arg count is exceeded
retval = FARG_error;
}
else {
// varargs are not allowed and this is the last argument
pList = (plfArgList)(&((TYPPTR)MHOmfLock ((HDEP)hList))->leaf);
*type = pList->arg[argn];
retval = FARG_exact;
}
}
else {
// this is before the last argument so it cannot be a vararg
// load type list and store type of argument
pList = (plfArgList)(&((TYPPTR)MHOmfLock ((HDEP)hList))->leaf);
*type = pList->arg[argn];
retval = FARG_exact;
}
if (pList != NULL) {
MHOmfUnLock ((HDEP)hList);
}
return (retval);
}
/** VBSearched - check to see if virtual base hase already been searched
*
* flag = VBSearched (type)
*
* Entry type = type index of virtual base
*
* Exit none
*
* Returns TRUE if virtual base has already been searched
* FALSE if virtual base has not been searched
*/
LOCAL bool_t
VBSearched (
CV_typ_t type
)
{
ushort i;
for (i = 0; i < pVBSearch->CurIndex; i++) {
if (pVBSearch->dom[i] == type) {
return (TRUE);
}
}
return (FALSE);
}
/** GrowTMList - grow TML
*
* fSuccess = GrowTMList (void)
*
* Entry pTMLbp = pointer to TML
* pTMList = pointer to TM list
*
* Exit TML grown
* pTMList = pointer to locked table
*
* Returns TRUE if table grown
* FALSE if out of memory
*/
LOCAL bool_t
GrowTMList(
void
)
{
register bool_t retval = FALSE;
MHMemUnLock (pTMLbp->hTMList);
if ((pTMLbp->hTMList = MHMemReAlloc (pTMLbp->hTMList,
(pTMLbp->cTMListMax + TMLISTCNT) * sizeof (HTM))) != 0) {
pTMLbp->cTMListMax += TMLISTCNT;
retval = TRUE;
}
// lock list to maintain lock/unlock synchronization
pTMList = MHMemLock (pTMLbp->hTMList);
return (retval);
}
/** IncrSymBase - increment symbase_t index and grow if necessary
*
* status = IncrSymbase ();
*
* Entry none
*
* Exit *pSymClass->CurIndex incremented
* pSymBase grown if necessary
*
* Returns SCN_found if pSymClass->CurIndex incremented
* SCN_error if unable to allocate memory for duplication
*/
LOCAL SCN_t
IncrSymBase (
void
)
{
uint size;
if (++pSymClass->CurIndex >= pSymClass->MaxIndex) {
size = sizeof (psymclass_t) + (pSymClass->CurIndex + 5) * sizeof (symbase_t);
MHMemUnLock (hSymClass);
if ((hSymClass = MHMemReAlloc (hSymClass, size)) == 0) {
pExState->err_num = ERR_NOMEMORY;
pSymClass = MHMemLock (hSymClass);
pSymClass->CurIndex--;
return (SCN_error);
}
pSymClass = MHMemLock (hSymClass);
pSymClass->MaxIndex += 5;
}
return (SCN_found);
}
/** IsDominated - check to see of feature is dominated
*
* fStatus = IsDominated (pSymBest, pSymTest)
*
* Entry pName = structure describing search
* pSymClass = structure describing most recent class search
*
* Exit pName updated to reflect search
* pSymClass updated to unambiguous feature
*
* Returns DOM_replace if pSymBest is dominated by pSymTest
* DOM_keep if pSymBest is exactly equivalent to pSymTest
* DOM_ambiguous if pSymBest is equal to pSymTest
* DOM_keep if pSymTest is duplicate virtual base
*/
LOCAL DOM_t
IsDominated (
psymclass_t pSymBest,
psymclass_t pSymTest
)
{
short i;
short j;
if (pSymBest->s.isdupvbase == TRUE) {
return (DOM_replace);
}
if (pSymTest->s.isdupvbase == TRUE) {
return (DOM_keep);
}
// check all of the base classes for a dominated virtual base
for (i = 0; i <= pSymBest->CurIndex; i++) {
if (pSymBest->symbase[i].virtual == TRUE) {
for (j = pVBDom->CurIndex; j >= 0; j--) {
if (pVBDom->dom[j] == EVAL_TYP (&pSymBest->symbase[i].Base)) {
return (DOM_replace);
}
}
}
}
for (i = 0; i <= pSymTest->CurIndex; i++) {
if (pSymTest->symbase[i].virtual == TRUE) {
for (j = pVBDom->CurIndex; j >= 0; j--) {
if (pVBDom->dom[j] == EVAL_TYP (&pSymTest->symbase[i].Base)) {
return (DOM_keep);
}
}
}
}
// we have two paths to potentially two different features. We now check
// to see if the features are identical. This is done by checking for
// static data members that have identical addresses and types
if (!EVAL_IS_STMEMBER (&pSymBest->evalP) ||
!EVAL_IS_STMEMBER (&pSymTest->evalP) ||
(EVAL_TYP (&pSymBest->evalP) != EVAL_TYP (&pSymTest->evalP)) ||
(EVAL_SYM_SEG (&pSymBest->evalP) != EVAL_SYM_SEG (&pSymTest->evalP)) ||
(EVAL_SYM_OFF (&pSymBest->evalP) != EVAL_SYM_OFF (&pSymTest->evalP))) {
return (DOM_ambiguous);
}
return (DOM_keep);
}
/** IsIntroVirt - is this the introducing virtual method
*
* fSuccess = IsIntroVirt (count, mlist, pvtabindex)
*
* Entry count = number of methods in list
* mlist = type index of method list
* pvtabind = pointer to virtual function table index
*
* Exit *pvtabind = virtual fuction table index
*
* Returns TRUE if the introducing virtual method is found
* FALSE otherwise
*/
LOCAL bool_t
IsIntroVirt (
ushort count,
CV_typ_t mlist,
ushort *vtabind)
{
HTYPE hMethod;
pmlMethod pMethod;
plfMFunc pMFunc;
uint skip;
CV_fldattr_t attr;
CV_typ_t type;
bool_t Mmatch = 0;
peval_t pvF;
HMOD hMod;
bool_t retval;
pvF = &pSymClass->evalP;
hMod = EVAL_MOD (pvF);
// we now walk the list of methods looking for a method with the same
// return type and argument list type
if ((hMethod = THGetTypeFromIndex (hMod, mlist)) == (HTYPE) NULL) {
DASSERT (FALSE);
return (FALSE);
}
// set the number of methods overloaded on this name and the index into
// the method list
skip = 0;
while (count-- > 0) {
// lock the omf record, extract information for the current entry in
// the method list and increment to field for next method
pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1 + skip);
attr = pMethod->attr;
type = pMethod->index;
skip += sizeof (mlMethod);
if (pMethod->attr.mprop == CV_MTintro) {
*vtabind = (short)RNumLeaf (((char *)pMethod) + skip, &skip);
}
else {
*vtabind = 0;
}
MHOmfUnLock (hMethod);
if (attr.mprop == CV_MTintro) {
if ((hMethod = THGetTypeFromIndex (hMod, type)) == (HTYPE) NULL) {
DASSERT (FALSE);
return (FALSE);
}
pMFunc = (plfMFunc)((&((TYPPTR)MHOmfLock (hMethod))->leaf));
retval = (pMFunc->rvtype == FCN_RETURN (pvF)) &&
(pMFunc->arglist == FCN_PINDEX (pvF));
MHOmfUnLock (hMethod);
if (retval == TRUE) {
return (TRUE);
}
}
}
return (FALSE);
}
LOCAL CV_typ_t
SkipModifiers(
HMOD mod,
CV_typ_t type
)
{
HTYPE hType;
plfModifier pType;
if (!CV_IS_PRIMITIVE (type)) {
hType = THGetTypeFromIndex (mod, type);
pType = (plfModifier)((&((TYPPTR)MHOmfLock (hType))->leaf));
while (pType->leaf == LF_MODIFIER) {
type = pType->type;
if (CV_IS_PRIMITIVE (type)) {
break;
}
MHOmfUnLock (hType);
hType = THGetTypeFromIndex (mod, type);
pType = (plfModifier)((&((TYPPTR)MHOmfLock (hType))->leaf));
}
}
MHOmfUnLock (hType);
return type;
}
/** MatchArgs - match a method against argument list
*
* flag = MatchArgs (pv, pName, fattr, vtabind, fForce)
*
* Entry pv = pointer to function descriptor
* pName = pointer to search structure
* attr = attribute if method
* vtabind = offset into vtable if virtual method
* fForce = TRUE if match on first (only) method is forced
* This is the case if bp method, no args and single
* method.
* BindingBP = TRUE if call is via ParseBP API entry
* if BindingBP is true, then only exact matches are allowed
* bArgList = based pointer to argument list
*
* Exit ST = resolved address of method
*
* Returns TRUE if a match was found or ambiguous references are allowed
* FALSE if no match or ambiguity not allowed
*/
LOCAL void
MatchArgs (
peval_t pvM,
psearch_t pName,
CV_fldattr_t attr,
UOFFSET vtabind,
bool_t fForce
)
{
pnode_t pnT;
pargd_t pa;
bool_t update;
argcounters current;
short argc;
CV_typ_t Ftype;
bool_t argmatch;
eval_t evalArg;
peval_t pvArg = &evalArg;
HTYPE hType;
plfModifier pType;
// walk down the formal list specified by pvM and the actual list
// specified by bArgList. Initialize the conversion counters to
// zero and set the index to varargs parameter to zero
argc = 0;
current.exact = 0;
current.implicit = 0;
current.varargs = 0;
argmatch = FALSE;
update = FALSE;
pnT = pnodeOfbnode(bArgList);
(pName->overloadCount)++;
if (fForce == TRUE) {
argmatch = TRUE;
update = TRUE;
}
else if (!N_EVAL_IS_FCN(pvM)) {
argmatch = TRUE;
current.exact = 0;
}
else while (TRUE) {
if (NODE_OP (pnT) == OP_endofargs) {
if ((argc == FCN_PCOUNT (pvM)) ||
((argc >= (FCN_PCOUNT (pvM) - 1)) && (FCN_VARARGS (pvM) == TRUE))) {
argmatch = TRUE;
}
break;
}
if ((argc > FCN_PCOUNT (pvM)) && (FCN_VARARGS (pvM) == FALSE)) {
// this function cannot possibly be a match because the
// number of actuals is greater than the number of formals
// and the method does not allow varargs.
break;
}
switch (GetArgType (pvM, argc, &Ftype)) {
case FARG_error:
DASSERT (FALSE);
return;
case FARG_none:
// special case foo(void)
// sps 2/20/92
if ((argc == 0) && (pa->actual == T_VOID)) {
argmatch = TRUE;
goto argmatchloop;
}
return;
case FARG_vararg:
// varargs are allowed unless we are binding breakpoints
if (BindingBP == TRUE) {
return;
}
break;
case FARG_exact:
if ((argc + 1) > FCN_PCOUNT (pvM)) {
// we must exactly match the argument count and we
// have more arguments
return;
}
break;
}
argc++;
// pa points to the argument descriptor array in the OP_arg node
pa = (pargd_t)&(pnT->v[0]);
if (Ftype == 0) {
// all arguments from this point on are vararg
current.varargs = argc;
pa->current = OM_vararg;
}
#if 1
else {
CV_typ_t Atype = pa->actual;
eval_t vA, vF;
peval_t pvA = &vA;
peval_t pvF = &vF;
if (pa->flags.istype) {
// If we have a type want identical type indices
// (This helps with class dumps)
if (Atype == Ftype) {
current.exact++;
pa->current = OM_exact;
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
continue;
}
else {
pExState->err_num = ERR_NONE;
break;
}
}
Ftype = SkipModifiers(EVAL_MOD(pvM), Ftype);
Atype = SkipModifiers(EVAL_MOD(pvM), Atype);
*pvF = *pvM;
if (!SetNodeType(pvF, Ftype)) {
// error (not valid type)
break;
}
// Update Ftype (SetNodeType must have resolved potential fwd refs)
Ftype = EVAL_TYP (pvF);
// if we are calling a 32 bit func we must promote all const
// int2's to int4's
if (EVAL_SYM_IS32(pvM) &&
(EVAL_STATE((peval_t)(&(pnodeOfbnode(NODE_LCHILD (pnT)))->v[0])) == EV_constant) &&
((Atype == T_INT2) || (Atype == T_UINT2))
) {
Atype++;
}
*pvA = *pvM;
if (!SetNodeType(pvA, Atype)) {
// error (not valid type)
break;
}
if (EVAL_IS_PTR(pvA) && EVAL_IS_REF(pvA)) {
Atype = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvA));
}
if (Atype == Ftype) {
current.exact++;
pa->current = OM_exact;
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
continue;
}
if (EVAL_IS_PTR(pvF)) {
*pvA = *pvM;
if (!SetNodeType(pvA, Atype)) {
// error (not valid type)
break;
}
if (!EVAL_IS_REF(pvF)) {
if (!EVAL_IS_PTR(pvA)) {
// do not cast a non-pointer to pointer
break;
}
PTR_UTYPE(pvA) = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvA));
PTR_UTYPE(pvF) = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE(pvF));
if (EVAL_PTRTYPE(pvA) == EVAL_PTRTYPE(pvF) &&
PTR_UTYPE(pvA) == PTR_UTYPE(pvF) &&
!EVAL_IS_BASED(pvA) &&
!EVAL_IS_BASED(pvF)) {
// we don't match based pointers. if we want to
// do this we must examine additional information
// we allow mathcing a pointer with an array
// however all arrays are considered far
// since codeview information does not distinguish
// between far or near arrays. --gdp 10/16/92
current.exact++;
pa->current = OM_exact;
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
continue;
}
}
else {
//
// special handling of a reference
//
CV_typ_t Utype;
Utype = SkipModifiers(EVAL_MOD(pvM), PTR_UTYPE (pvF));
if (Utype == Atype) {
current.exact++;
pa->current = OM_exact;
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
continue;
}
else {
break;
}
}
}
// see if we can cast the type of the actual to the type of
// the formal if we are not binding breakpoints. If we are
// binding breakpoints, only exact matches are allowed
*pvArg = *pvM;
SetNodeType (pvArg, pa->actual);
if (EVAL_IS_BITF (pvArg)) {
SetNodeType (pvArg, BITF_UTYPE (pvArg));
}
if (CastNode (pvArg, Ftype, Ftype)) {
pa->current = OM_implicit;
current.implicit++;
}
else {
pExState->err_num = ERR_NONE;
break;
}
}
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
}
argmatchloop:
#endif
#if 0
else if (pa->actual == Ftype) {
current.exact++;
pa->current = OM_exact;
}
else {
/*
* we need to check to see if we have a modifier to the
* actual type
*
* Modifies we look for are:
*
* const foo
* volatile foo
*
* pointer to foo by reference (C++ call by reference)
*/
if (!CV_IS_PRIMITIVE (Ftype)) {
hType = THGetTypeFromIndex (EVAL_MOD (pvM), Ftype);
DASSERT(hType != (HTYPE) NULL);
pType = (plfModifier)((&((TYPPTR)MHOmfLock ((HDEP)hType))->leaf));
if (pType->leaf == LF_MODIFIER) {
if (((pType->attr.MOD_const == TRUE) == (int) pa->flags.isconst) ||
((pType->attr.MOD_volatile == TRUE) == (int) pa->flags.isvolatile) &&
(pType->type == Ftype)) {
current.exact++;
pa->current = OM_exact;
MHOmfUnLock((HDEP)hType);
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
continue;
}
} else {
if (pType->leaf == LF_POINTER) {
lfPointer * pType2 = (lfPointer *) pType;
if ((pType2->attr.ptrmode == CV_PTR_MODE_REF) &&
(pType2->utype == pa->actual)) {
current.exact++;
pa->current = OM_exact;
MHOmfUnLock((HDEP)hType);
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
continue;
}
}
}
MHOmfUnLock( (HDEP)hType );
}
if (pa->flags.istype == TRUE) {
// the formal argument is a type and exact match is required
break;
}
else {
// see if we can cast the type of the actual to the type of
// the formal if we are not binding breakpoints. If we are
// binding breakpoints, only exact matches are allowed
*pvArg = *pvM;
SetNodeType (pvArg, pa->actual);
if (EVAL_IS_BITF (pvArg)) {
SetNodeType (pvArg, BITF_UTYPE (pvArg));
}
if (CastNode (pvArg, Ftype, Ftype)) {
pa->current = OM_implicit;
current.implicit++;
}
else {
pExState->err_num = ERR_NONE;
break;
}
}
}
pnT = pnodeOfbnode(NODE_RCHILD (pnT));
}
#endif
if (argmatch == TRUE) {
// check current against best match
if (pName->best.match == 0) {
// we have a first time match
update = TRUE;
pName->possibles++;
}
else if (fForce == FALSE) {
// we have already matched on some function so we now
// check to see if the current is better than the best
if (current.varargs == 0) {
// there are no varargs in this method therefor it is
// better than any previous match with varargs
if (pName->best.varargs != 0) {
update = TRUE;
pName->best = current;
pName->possibles = 1;
}
else if (current.exact > pName->best.exact) {
// this function has more exact matches than the
// best one so far
update = TRUE;
pName->possibles = 1;
}
else if (EVAL_TYP (pvM) != pName->best.match &&
current.exact == pName->best.exact) {
// this function is a good as the best one.
// this means the call is ambiguous
pName->possibles++;
}
}
else {
if (pName->best.varargs != 0) {
// both the current and the best functions have
// varargs
if (current.varargs < pName->best.varargs) {
// this function uses fewer varargs which
// makes it a better one
update = TRUE;
pName->possibles = 1;
}
else if (current.varargs == pName->best.varargs) {
// this function uses the same number of varargs
// pick the one with more exact matches
if (current.exact > pName->best.exact) {
update = TRUE;
pName->possibles = 1;
}
else if (EVAL_TYP (pvM) != pName->best.match &&
current.exact == pName->best.exact) {
pName->possibles++;
}
}
}
}
}
if (update == TRUE) {
if (fForce == FALSE) {
// the current match is better
for (pnT = pnodeOfbnode(bArgList); NODE_OP (pnT) != OP_endofargs; pnT = pnodeOfbnode(NODE_RCHILD (pnT))) {
pa = (pargd_t)&(pnT->v[0]);
pa->best = pa->current;
}
{ //M00KLUDGE - hack for compiler DS != SS bug
argcounters *pcurrent = &current;
pName->best = *pcurrent;
}
}
pName->best.match = EVAL_TYP (pvM);
pName->best.attr = attr;
pName->best.vtabind = vtabind;
pName->best.hSym = pName->hSym;
}
}
}
/** MatchFunction - match a function against argument list
*
* flag = MatchFunction (pName)
*
* Entry pName = pointer to search status
* BindingBP = TRUE if call is via ParseBP API entry
* bArgList = based pointer to argument list
*
* Exit pv = resolved address of method
*
* Returns HR_... describing match result
*/
LOCAL HR_t __fastcall
MatchFunction (
psearch_t pName
)
{
HR_t retval;
CV_fldattr_t attr = {0};
CV_typ_t type;
ADDR addr;
bool_t dupfcn;
if (bArgList == 0) {
// if there is no argument list, assume we are assigning to a
// function pointer and take the first function found. Let the
// user beware.
return (HR_found);
}
// NOTENOTE -- jimsch -- don't search publics if something was found
// it is making all sorts of problems for me on MIPS
pName->scope &= ~SCP_global;
// save the function address and type. Then if a subsequent match has
// the same address and type (i.e., comdat code), we can ignore it.
addr = EVAL_SYM (ST);
type = EVAL_TYP (ST);
// pop the entry that SearchSym has added to the evaluation stack
// the best match will be pushed back on later
pName->scope |= SCP_nomatchfn;
PopStack ();
MatchArgs (pName->pv, pName, attr, 0, FALSE);
while ((retval = SearchSym (pName)) != HR_notfound) {
DASSERT (retval != HR_end);
dupfcn = FALSE;
if (retval == HR_found) {
if ((EVAL_TYP (ST) == type) &&
(_fmemcmp (&addr, &EVAL_SYM (ST), sizeof (addr)) == 0)) {
dupfcn = TRUE;
}
PopStack ();
if (dupfcn == FALSE) {
MatchArgs (pName->pv, pName, attr, 0, FALSE);
}
}
else {
return (retval);
}
}
pName->scope &= ~SCP_nomatchfn;
// clear the symbol not found error from the recursive symbol search
pExState->err_num = ERR_NONE;
if (pName->best.match == 0) {
pExState->err_num = ERR_ARGLIST;
return (HR_error);
}
else if (pName->possibles > 1) {
PushStack (pName->pv);
pExState->err_num = ERR_AMBIGUOUS;
EVAL_IS_AMBIGUOUS (ST) = TRUE;
return (HR_ambiguous);
}
else if (pName->overloadCount > 1 && pName->best.implicit > 0) {
//
// overloaded function that involves implicit casts
//
pExState->err_num = ERR_AMBIGUOUS;
return (HR_ambiguous);
}
else {
pName->hSym = pName->best.hSym;
if ((SymToNode (pName) == FALSE) || (PushStack (pName->pv) == FALSE)) {
return (HR_notfound);
}
else {
return (HR_found);
}
}
}
/** MatchMethod - match a method against argument list
*
* flag = MatchMethod (pName, pSymCl)
*
* Entry pName = pointer to search descriptor
* pSymCl = pointer tp symbol class structure
* select = selection masj
* BindingBP = TRUE if call is via ParseBP API entry
* if BindingBP is true, then only exact matches allowed
* bArgList = based pointer to argument list
*
* Exit pName->pv = resolved address of method
*
* Returns MTH_found if a match was found or ambiguous references are allowed
* MTH_error if error or ambiguity not allowed
*
*/
LOCAL MTH_t
MatchMethod (
psearch_t pName,
psymclass_t pSymCl
)
{
HTYPE hMethod;
pmlMethod pMethod;
uint skip;
eval_t evalM;
peval_t pvM = &evalM;
CV_fldattr_t attr;
CV_typ_t type;
ushort vtabind;
bool_t Mmatch = 0;
HDEP hQual;
peval_t pvF;
ushort count = pSymCl->possibles;
peval_t pvB;
HMOD hMod;
bool_t fForce = FALSE;
pvB = &pSymClass->symbase[pSymClass->CurIndex].Base;
hMod = EVAL_MOD (pvB);
pName->possibles = 0;
// we now walk the list of methods looking for an argument match
// For now, we require an exact match except that we assume any
// primitive type can be cast to any other primitive type. A cast from
// pointer to derived to pointer to base is an implicit conversion
if ((hMethod = THGetTypeFromIndex (hMod, pSymCl->mlist)) == (HTYPE)NULL) {
DASSERT (FALSE);
return (MTH_error);
}
// set the number of methods overloaded on this name and the index into
// the method list
skip = 0;
// if ((BindingBP == TRUE) && (bArgList == 0))
if (bArgList == 0)
{
if (count == 1) {
fForce = TRUE;
}
else {
// there is not an argument list. We allow breakpoints if a single
// method by that name exists. Otherwise, we require an argument
// list
pExState->err_num = ERR_NOARGLIST;
return (MTH_error);
}
}
while (count-- > 0) {
// lock the omf record, extract information for the current entry in
// the method list and increment to field for next method
pMethod = (pmlMethod)((&((TYPPTR)MHOmfLock (hMethod))->leaf) + 1);
pMethod = (pmlMethod)((uchar *)pMethod + skip);
attr = pMethod->attr;
type = pMethod->index;
skip += sizeof (mlMethod);
if (pMethod->attr.mprop == CV_MTintro) {
vtabind = (short)RNumLeaf (((char *)pMethod) + skip, &skip);
}
else {
vtabind = 0;
}
MHOmfUnLock (hMethod);
// now compare the actual and formal argument lists for the function
// pvM will be initialized to be a function node whose type index is
// type.
CLEAR_EVAL (pvM);
EVAL_MOD (pvM) = hMod;
if (SetNodeType (pvM, type) == FALSE) {
// the type record for the method was not found
DASSERT (FALSE);
return (MTH_error);
}
MatchArgs (pvM, pName, attr, vtabind, fForce);
}
// since the name was found at this level, it hides all other methods
// by the same name above it in the inheritance tree. Therefore we must
// either have a match or an error because there is no match or two or
// methods match after conversions are considered
if (pName->best.match == 0) {
pExState->err_num = ERR_ARGLIST;
return (MTH_error);
}
else if (pName->possibles > 1) {
pExState->err_num = ERR_AMBIGUOUS;
EVAL_IS_AMBIGUOUS (pName->pv) = TRUE;
return (MTH_error);
}
else if (pName->overloadCount > 1 && pName->best.implicit > 0) {
// we have an overloaded method
// in this case the EE requires exact matches only
pExState->err_num = ERR_AMBIGUOUS;
EVAL_IS_AMBIGUOUS (pName->pv) = TRUE;
return (MTH_error);
}
else {
// we have found a non-ambiguous match
pvF = &pSymCl->evalP;
EVAL_MOD (pvF) = hMod;
if (SetNodeType (pvF, pName->best.match) == FALSE) {
return (MTH_error);
}
else {
pSymCl->access.access = pName->best.attr.access;
FCN_ATTR (pvF) = pName->best.attr;
FCN_VTABIND (pvF) = pName->best.vtabind;
FCN_VFPTYPE (pvF) = pSymCl->vfpType;
if (NODE_OP (pnodeOfbnode(pName->bnOp)) == OP_bscope) {
// binary scoping switches off virtual function evaluation
FCN_PROPERTY (pvF) = CV_MTvanilla;
}
if ((FCN_PROPERTY (pvF) == CV_MTvirtual) ||
(FCN_PROPERTY (pvF) == CV_MTintro)) {
// do nothing. address will have to be found at evaluation
}
else {
if (((hQual = GenQualName (pName, pSymClass)) == 0) ||
(SearchQualName (pName, pSymCl, hQual, TRUE) == FALSE)) {
if (hQual != 0) {
MHMemFree (hQual);
}
return (MTH_error);
}
MHMemFree (hQual);
}
return (MTH_found);
}
}
}
/** MoveSymCl - move symbol class structure
*
* MoveSymCl (hSymCl);
*
* Entry hSymCl = handle of symbol class structure
*
* Exit *pSymClass = symbol class structure
*
* Returns none
*/
LOCAL void
MoveSymCl (
HDEP hSymCl
)
{
psymclass_t pSymCl;
ushort max;
pSymCl = MHMemLock (hSymCl);
DASSERT (pSymClass->MaxIndex >= pSymCl->CurIndex);
max = pSymClass->MaxIndex;
_fmemmove (pSymClass, pSymCl,
sizeof (symclass_t) + (pSymCl->CurIndex + 1) * sizeof (symbase_t));
pSymClass->MaxIndex = max;
MHMemUnLock (hSymCl);
MHMemFree (hSymCl);
}
/** PurgeAmbCl - purge ambiguous class structure list
*
* PurgeAmbCl (pName)
*
* Entry pName = pointer to symbol search structure
*
* Exit pname->hAmb list freed
*
* Returns none
*/
LOCAL void
PurgeAmbCl (
psearch_t pName
)
{
psymclass_t pAmbCl;
HDEP hNext;
while (pName->hAmbCl != 0) {
pAmbCl = MHMemLock (pName->hAmbCl);
hNext = pAmbCl->hNext;
MHMemUnLock (pName->hAmbCl);
pName->hAmbCl = hNext;
}
}
/*** SetBase - set base value in pSymClass->symbase array
*
* status = SetBase (pName, type, vbptr, vbpoff, thisadjust, attr, virtual)
*
* Entry pName = pointer to struct describing search
* type = type index of class
* vbptr = type index of virtual base pointer
* vbpoff = offset of virtual base pointer from address point
* thisadjust = offset of base from previous class
* thisadjust = virtual base index if virtual base
* attr = field attribute mask
* virtual = TRUE if virtual base
*
* Exit new base class added to pSymClass
*
* Returns enum describing search state
*/
LOCAL SCN_t
SetBase (
psearch_t pName,
CV_typ_t type,
CV_typ_t vbptr,
OFFSET vbpoff,
OFFSET thisadjust,
CV_fldattr_t attr,
bool_t virtual
)
{
peval_t pvB;
// save offset of base from address point for this pointer adjustment
pSymClass->symbase[pSymClass->CurIndex].thisadjust = thisadjust;
pSymClass->symbase[pSymClass->CurIndex].vbptr = vbptr;
pSymClass->symbase[pSymClass->CurIndex].vbpoff = vbpoff;
pSymClass->symbase[pSymClass->CurIndex].attrBC = attr;
pSymClass->symbase[pSymClass->CurIndex].virtual = virtual;
pSymClass->symbase[pSymClass->CurIndex].clsmask = pName->clsmask;
pvB = &pSymClass->symbase[pSymClass->CurIndex].Base;
EVAL_MOD (pvB) = pName->hMod;
if (SetNodeType (pvB, type) == FALSE) {
pExState->err_num = ERR_BADOMF;
return (SCN_error);
}
return (SCN_found);
}
/*** SearchQualName - Search for a qualified method name
*
* flag = SearchQualName (pName, pSymCl, hQual, fProc)
*
* Entry pName = pointer to struct describing search
* pSymCl = pointer to structure describing path to symbol
* hQual = handle to symbol name
* fProc = TRUE if proc symbol to be searched for
* fProc = FALSE if data to be searched for
*
* Exit pName updated to reflect search
*
* Return enum describing search
*/
LOCAL bool_t
SearchQualName (
psearch_t pName,
psymclass_t pSymCl,
HDEP hQual,
bool_t fProc
)
{
HDEP hTemp;
psearch_t pTemp;
uchar *pQual;
ushort retval;
if ((hTemp = MHMemAllocate (sizeof (search_t))) == 0) {
pExState->err_num = ERR_NOMEMORY;
return (FALSE);
}
pTemp = MHMemLock (hTemp);
*pTemp = *pName;
pTemp->CXTT = *pCxt;
// set pointer to symbol name
pQual = (uchar *)MHMemLock (hQual);
pTemp->sstr.lpName = pQual;
pTemp->sstr.cb = (uchar)_fstrlen ((char *)pQual);
pTemp->state = SYM_init;
if (fProc == TRUE) {
pTemp->scope = SCP_module | SCP_global;
pTemp->sstr.searchmask |= SSTR_proc;
}
else {
pTemp->scope = SCP_module | SCP_global | SCP_lexical;
// data members may not be overloaded, hence there is
// no need for the type to qualify the name. Furthermore
// there are cases where the symbol type doesn't match
// the member type exactly (e.g. variable length arrays,
// symbol has actual length and member has zero length)
// hence this matching is suppressed for data items [rm]
// pTemp->sstr.searchmask |= SSTR_data;
}
pTemp->initializer = INIT_qual;
pTemp->typeOut = EVAL_TYP (&pSymCl->evalP);
retval = SearchSym (pTemp);
MHMemUnLock (hQual);
if (retval != HR_found) {
#ifdef NEVER /* CAVIAR #1081 */
if ((retval != HR_end) && (pTemp->FcnBP != 0)) {
// if (pTemp->FcnBP != 0) {
// there is another symbol with the same name but a different
// type. Since this is set only when we are binding breakpoints,
// let's go ahead and try it
pTemp->state = SYM_init;
pTemp->scope = SCP_module | SCP_global;
pTemp->sstr.searchmask |= SSTR_proc;
pTemp->typeOut = pTemp->FcnBP;
retval = SearchSym (pTemp);
}
#endif
if (retval != HR_found) {
// the only way we can get here is if the method or data
// is declared in the class but is not defined or
// is a noninstianted inline method.
// therefore, we return a special error code
if (ST == NULL) {
// this is a hack to get around the case where the expression
// bp {,foo.c, foo.exe}X::f
// and the first function in the module foo is a method.
// SearchSym ended up calling the class search routines
// because the context is implicitly a class so class is
// searched even though it shouldn't be. Any fix for this
// causes problems and we are too close to release to find
// a valid fix. The major result of this fix is that
// some breakpoints will not get reset on entry.
return (FALSE);
}
PushStack (ST);
// if this is a missing static DATA member function then
// best.match won't have anything in it at all... we'll need
// to pick up what we want from typeOut which will have been
// set by a previous non-qualified name search... [rm]
if (pName->best.match == T_NOTYPE) {
SetNodeType (ST, pName->typeOut);
}
else {
SetNodeType (ST, pName->best.match);
}
if (EVAL_IS_FCN(ST)) {
FCN_NOTPRESENT (ST) = TRUE;
}
else {
// indicate missing static data member
EVAL_HSYM (ST) = 0;
pExState->state.fNotPresent = TRUE;
}
// if (fProc) {
// SetNodeType (ST, pName->best.match);
// FCN_NOTPRESENT (ST) = TRUE;
// }
}
}
// pop off the stack entry that a successful search found. Move the
// static data member flag first so that it will not be lost.
EVAL_IS_STMEMBER (ST) = EVAL_IS_STMEMBER (&pSymCl->evalP);
EVAL_ACCESS (ST) = (uchar)(pSymCl->access.access);
pSymCl->evalP = *ST;
MHMemUnLock (hTemp);
MHMemFree (hTemp);
return (PopStack ());
}
/** SymAmbToList - add ambiguous symbol to list
*
* status = SymAmbToList (pName)
*
* Entry pName = pointer to list describing search
*
* Exit ambiguous symbol added to list pointed to by pTMList
* pTMLbp
* pName reset to continue breakpoint search
*
* Returns HR_... describing state
*/
LOCAL HR_t
SymAmbToList (
psearch_t pName
)
{
HDEP hSearch;
psearch_t pSearch;
HR_t retval;
HDEP hevalT;
PopStack ();
if (pExState->ambiguous == 0) {
// this is the first breakpoint symbol found.
// indicate the only node in the tree that is
// allowed ambiguity and initialize list of
// symbols for later back patching into duplicated
// expression trees. We save the initial search packet
// so that the first symbol will be set into the breakpoint
// list.
pNameFirst = pName;
pExState->ambiguous = pName->bn;
if ((hSearch = MHMemAllocate (sizeof (search_t))) == 0) {
pExState->err_num = ERR_NOMEMORY;
return (HR_error);
}
if ((hevalT = MHMemAllocate (sizeof (eval_t))) == 0) {
MHMemFree (hSearch);
pExState->err_num = ERR_NOMEMORY;
return (HR_error);
}
pSearch = MHMemLock (hSearch);
*pSearch = *pName;
pSearch->pv = (peval_t)MHMemLock (hevalT);
SHGoToParent (&pName->CXTT, &pSearch->CXTT);
// clear the newly allocated pv
_fmemset ( pSearch->pv, 0, sizeof (eval_t) );
retval = SearchSym (pSearch);
PushStack (pName->pv);
MHMemUnLock (hSearch);
MHMemFree (hSearch);
MHMemUnLock (hevalT);
MHMemFree (hevalT);
if (retval == HR_end) {
retval = HR_found;
}
return (retval);
}
else if (pExState->ambiguous != pName->bn) {
// there has already been a ambiguous symbol that is
// not at this node in the tree
pExState->err_num = ERR_BPAMBIGUOUS;
return (HR_error);
}
else {
if (CheckDupAmb (pName) == FALSE) {
// the function is not already in the ambiguity list
if (AmbToList (pName) == FALSE) {
return (HR_error);
}
}
// reset search to allow more symbols
pName->possibles = 0;
return (SearchSym (pName));
}
}
/** CheckDupAmb - check for duplicate ambiguity entry
*
* fSuccess = CheckDupAmb (pName)
*
* Entry pName = pointer to list describing search
*
* Exit none
*
* Returns TRUE if duplicate symbol found
* FALSE if duplicate symbol not found
*/
LOCAL bool_t
CheckDupAmb (
psearch_t pName
)
{
psearch_t pN;
ushort i;
bool_t fdup = FALSE;
if ((EVAL_TYP (pNameFirst->pv) == EVAL_TYP (pName->pv)) &&
(_fmemcmp ((void *)&EVAL_SYM (pNameFirst->pv), (void *)&EVAL_SYM (pName->pv),
sizeof (ADDR)) == 0)) {
return (TRUE);
}
for (i = 1; i < iBPatch; i++) {
pN = (psearch_t) MHMemLock (pTMList[i]);
if (pN->typeOut == EVAL_TYP (pName->pv) &&
(_fmemcmp ((void *)&pN->addr, (void *)&EVAL_SYM (pName->pv), sizeof (ADDR)) == 0)) {
fdup = TRUE;
}
MHMemUnLock (pTMList[i]);
if (fdup == TRUE) {
break;
}
}
return (fdup);
}
/** SymToNode - store symbol information in evaluation node
*
* fSuccess = SymToNode (hName)
*
* Entry pName = pointer to search state
*
* Exit type information and address data stored in value
* if the symbol is a typedef record, then the evaluation
* state will be set to EV_type. Otherwise, it will be set
* to EV_lvalue.
*
* Returns TRUE if variable was accessible
* FALSE if error
*/
LOCAL bool_t
SymToNode (
psearch_t pName
)
{
CV_typ_t typ;
ushort evalstate;
HSYM hSym;
peval_t pv = pName->pv;
PCXT pCXT = &pName->CXTT;
SYMPTR pSym;
ushort cmpThis = 1;
MEMINFO mi;
if ((hSym = pName->hSym) == NULL) {
// this symbol is found as a class member which means it does
// not have a symbol.
DASSERT (pName->typeOut != T_NOTYPE);
return (SetNodeType (pv, pName->typeOut));
}
EVAL_STATE (pv) = EV_lvalue;
EVAL_MOD (pv) = SHHMODFrompCXT (pCXT);
CLEAR_EVAL_FLAGS (pv);
EVAL_SYM_EMI (pv) = pCXT->addr.emi;
switch((pSym = MHOmfLock ((HDEP)hSym))->rectyp) {
case S_REGISTER:
EVAL_IS_REG (pv) = TRUE;
EVAL_REG (pv) = ((REGPTR)pSym)->reg;
typ = ((REGPTR)pSym)->typind;
cmpThis = strncmp ( (char *) &((REGPTR)pSym)->name[0],
(char *) &OpName[0], ((REGPTR)pSym)->name[0] + 1);
break;
case S_CONSTANT:
if (!DebLoadConst (pv, (CONSTPTR)pSym, hSym)) {
MHOmfUnLock ((HDEP)hSym);
return (FALSE);
}
EVAL_STATE (pv) = EV_constant;
typ = EVAL_TYP (pv);
break;
case S_UDT:
typ = ((UDTPTR)pSym)->typind;
EVAL_STATE (pv) = EV_type;
break;
case S_BLOCK16:
EVAL_SYM_SEG (pv) = ((BLOCKPTR16)pSym)->seg;
EVAL_SYM_OFF (pv) = ((BLOCKPTR16)pSym)->off;
typ = T_NOTYPE;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
NOTTESTED (FALSE); // not tested
break;
case S_LPROC16:
case S_GPROC16:
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
if ((typ = ((PROCPTR16)pSym)->typind) == T_NOTYPE) {
// this is a hack to allow breakpoints on untyped symbols
typ = T_PFUCHAR;
EVAL_SYM_OFF (pv) = ((PROCPTR16)pSym)->off;
EVAL_SYM_SEG (pv) = ((PROCPTR16)pSym)->seg;
EVAL_PTR (pv) = EVAL_SYM (pv);
EVAL_STATE (pv) = EV_rvalue;
}
else {
EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT);
EVAL_SYM_SEG (pv) = ((PROCPTR16)pSym)->seg;
EVAL_SYM_OFF (pv) = ((PROCPTR16)pSym)->off;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
}
break;
case S_LABEL16:
EVAL_IS_LABEL (pv) = TRUE;
EVAL_SYM_OFF (pv) = ((LABELPTR16)pSym)->off;
EVAL_SYM_SEG (pv) = ((LABELPTR16)pSym)->seg;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
EVAL_PTR (pv) = EVAL_SYM (pv);
EVAL_STATE (pv) = EV_rvalue;
typ = T_PFUCHAR;
break;
case S_BPREL16:
EVAL_IS_BPREL (pv) = TRUE;
EVAL_SYM_OFF (pv) = ((BPRELPTR16)pSym)->off;
EVAL_SYM_SEG (pv) = 0;
ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
typ = ((BPRELPTR16)pSym)->typind;
pExState->state.bprel = TRUE;
cmpThis = strncmp ( (char *) &((BPRELPTR16)pSym)->name[0],
(char *) &OpName[0], ((BPRELPTR16)pSym)->name[0] + 1);
break;
case S_LDATA16:
pExState->state.fLData = TRUE;
EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off;
EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg;
typ = ((DATAPTR16)pSym)->typind;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
break;
case S_GDATA16:
pExState->state.fGData = TRUE;
EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off;
EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg;
typ = ((DATAPTR16)pSym)->typind;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
break;
case S_PUB16:
EVAL_SYM_OFF (pv) = ((DATAPTR16)pSym)->off;
EVAL_SYM_SEG (pv) = ((DATAPTR16)pSym)->seg;
EVAL_STATE (pv) = EV_lvalue;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
if ((typ = ((DATAPTR16)pSym)->typind) == T_NOTYPE) {
// this is a hack to allow breakpoints on untyped symbols
MEMINFO mi;
mi.addr = EVAL_SYM(pv);
SYGetMemInfo(&mi);
if ((mi.dwState & MEM_COMMIT)
&& (mi.dwProtect & (PAGE_EXECUTE |
PAGE_EXECUTE_READ |
PAGE_EXECUTE_READWRITE |
PAGE_EXECUTE_WRITECOPY))
) {
typ = T_PFUCHAR;
EVAL_STATE (pv) = EV_rvalue;
} else {
typ = T_UINT2;
EVAL_STATE (pv) = EV_lvalue;
}
}
EVAL_PTR (pv) = EVAL_SYM (pv);
break;
case S_BLOCK32:
EVAL_SYM_SEG (pv) = ((BLOCKPTR32)pSym)->seg;
EVAL_SYM_OFF (pv) = ((BLOCKPTR32)pSym)->off;
typ = T_NOTYPE;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
break;
case S_LPROC32:
case S_GPROC32:
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
if ((typ = ((PROCPTR32)pSym)->typind) == T_NOTYPE) {
// this is a hack to allow breakpoints on untyped symbols
typ = T_32PUCHAR;
EVAL_SYM_OFF (pv) = ((PROCPTR32)pSym)->off;
EVAL_SYM_SEG (pv) = ((PROCPTR32)pSym)->seg;
EVAL_PTR (pv) = EVAL_SYM (pv);
EVAL_STATE (pv) = EV_rvalue;
}
else {
EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT);
EVAL_SYM_SEG (pv) = ((PROCPTR32)pSym)->seg;
EVAL_SYM_OFF (pv) = ((PROCPTR32)pSym)->off;
}
break;
case S_LPROCMIPS:
case S_GPROCMIPS:
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
if ((typ = ((PROCPTRMIPS)pSym)->typind) == T_NOTYPE) {
// this is a hack to allow breakpoints on untyped symbols
typ = T_32PUCHAR;
EVAL_SYM_OFF (pv) = ((PROCPTRMIPS)pSym)->off;
EVAL_SYM_SEG (pv) = ((PROCPTRMIPS)pSym)->seg;
EVAL_PTR (pv) = EVAL_SYM (pv);
EVAL_STATE (pv) = EV_rvalue;
} else {
EVAL_SYM (pv) = *SHpADDRFrompCXT (pCXT);
EVAL_SYM_SEG (pv) = ((PROCPTRMIPS)pSym)->seg;
EVAL_SYM_OFF (pv) = ((PROCPTRMIPS)pSym)->off;
}
break;
case S_REGREL32:
EVAL_IS_REGREL (pv) = TRUE;
EVAL_SYM_OFF (pv) = ((LPREGREL32)pSym)->off;
EVAL_SYM_SEG (pv) = 0;
EVAL_REGREL (pv) = ((LPREGREL32)pSym)->reg;
typ = ((LPREGREL32)pSym)->typind;
ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
pExState->state.regrel = TRUE;
cmpThis = strncmp ( (char *) &((LPREGREL32)pSym)->name[0],
(char *) &OpName[0], ((LPREGREL32)pSym)->name[0] + 1);
break;
case S_LABEL32:
EVAL_IS_LABEL (pv) = TRUE;
EVAL_SYM_OFF (pv) = ((LABELPTR32)pSym)->off;
EVAL_SYM_SEG (pv) = ((LABELPTR32)pSym)->seg;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
EVAL_PTR (pv) = EVAL_SYM (pv);
EVAL_STATE (pv) = EV_rvalue;
typ = T_32PUCHAR;
break;
case S_BPREL32:
EVAL_IS_BPREL (pv) = TRUE;
EVAL_SYM_OFF (pv) = ((BPRELPTR32)pSym)->off;
EVAL_SYM_SEG (pv) = 0;
typ = ((BPRELPTR32)pSym)->typind;
ADDR_IS_LI (EVAL_SYM (pv)) = FALSE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
pExState->state.bprel = TRUE;
pExState->state.regrel = TRUE;
cmpThis = strncmp ( (char *) &((BPRELPTR32)pSym)->name[0],
(char *) &OpName[0], ((BPRELPTR32)pSym)->name[0] + 1);
break;
case S_LTHREAD32:
// NOTENOTE - jimsch -- TLS -- global vs local difference?
case S_GTHREAD32:
EVAL_IS_TLSREL( pv ) = TRUE;
EVAL_SYM_OFF( pv ) = ((DATAPTR32) pSym)->off;
EVAL_SYM_SEG( pv ) = ((DATAPTR32) pSym)->seg;
typ = ((DATAPTR32) pSym)->typind;
ADDR_IS_LI( EVAL_SYM( pv )) = TRUE;
ADDR_IS_FLAT( EVAL_SYM( pv )) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
pExState->state.tlsrel = TRUE;
break;
case S_LDATA32:
pExState->state.fLData = TRUE;
EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off;
EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg;
typ = ((DATAPTR32)pSym)->typind;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
break;
case S_GDATA32:
pExState->state.fGData = TRUE;
EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off;
EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg;
typ = ((DATAPTR32)pSym)->typind;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
if (FNtsdEvalType) {
FNtsdEvalType = FALSE;
EVAL_STATE (pv) = EV_rvalue;
EVAL_PTR (pv) = EVAL_SYM (pv);
typ = T_32PULONG;
}
break;
case S_PUB32:
EVAL_SYM_OFF (pv) = ((DATAPTR32)pSym)->off;
EVAL_SYM_SEG (pv) = ((DATAPTR32)pSym)->seg;
ADDR_IS_LI (EVAL_SYM (pv)) = TRUE;
ADDR_IS_FLAT (EVAL_SYM (pv)) = TRUE;
ADDR_IS_OFF32( EVAL_SYM ( pv ) ) = TRUE;
EVAL_PTR (pv) = EVAL_SYM (pv);
EVAL_STATE (pv) = EV_lvalue;
if (((typ = ((DATAPTR32)pSym)->typind) == T_NOTYPE) || FNtsdEvalType) {
if (FNtsdEvalType) {
FNtsdEvalType = FALSE;
evalstate = EV_rvalue;
typ = T_32PULONG;
} else {
typ = T_UINT4;
evalstate = EV_lvalue;
}
//
// this is a hack to allow breakpoints on untyped symbols
//
mi.addr = EVAL_SYM(pv);
SYGetMemInfo(&mi);
if ((mi.dwState & MEM_COMMIT)
&& (mi.dwProtect & (PAGE_EXECUTE |
PAGE_EXECUTE_READ |
PAGE_EXECUTE_READWRITE |
PAGE_EXECUTE_WRITECOPY))
) {
typ = T_32PUCHAR;
EVAL_STATE (pv) = EV_rvalue;
} else {
//
// this gives windbg the "look & feel" of ntsd/kd
// if the user does a "dd foo" and there are only
// coff publics then the answer will be the same
// as ntsd/kd
//
EVAL_STATE (pv) = evalstate;
}
}
break;
default:
// these OMF records are no longer supported
MHOmfUnLock ((HDEP)hSym);
pExState->err_num = ERR_BADOMF;
return (FALSE);
}
MHOmfUnLock ((HDEP)hSym);
if (SetNodeType (pv, typ) == FALSE) {
return (FALSE);
}
else if (ClassImp != T_NOTYPE) {
if (EVAL_IS_PTR (pv) &&
memcmp (pName->sstr.lpName, &OpName[0] + 1, pName->sstr.cb) == 0) {
PTR_THISADJUST (pv) = ClassThisAdjust;
}
else if (cmpThis == 0) {
PTR_THISADJUST (pv) = ClassThisAdjust;
}
}
return (TRUE);
}
#if defined (M68K)
#define VALID68851 0x40
#define VALID68882 0x80
#define VALID68000 0x01
#define VALID68010 0x02 | VALID68000
#define VALID68020 0x04 | VALID68010
#define VALID68030 0x08 | VALID68020 | VALID68851
#define VALID68040 0x10 | VALID68030
struct hreg {
char name[7];
ushort index;
char valid;
ushort type;
} _based (_segname("_CODE")) hreg_list[] = {
{"\x002""D0", CV_R68_D0, VALID68000, T_ULONG},
{"\x002""D1", CV_R68_D1, VALID68000, T_ULONG},
{"\x002""D2", CV_R68_D2, VALID68000, T_ULONG},
{"\x002""D3", CV_R68_D3, VALID68000, T_ULONG},
{"\x002""D4", CV_R68_D4, VALID68000, T_ULONG},
{"\x002""D5", CV_R68_D5, VALID68000, T_ULONG},
{"\x002""D6", CV_R68_D6, VALID68000, T_ULONG},
{"\x002""D7", CV_R68_D7, VALID68000, T_ULONG},
{"\x002""A0", CV_R68_A0, VALID68000, T_ULONG},
{"\x002""A1", CV_R68_A1, VALID68000, T_ULONG},
{"\x002""A2", CV_R68_A2, VALID68000, T_ULONG},
{"\x002""A3", CV_R68_A3, VALID68000, T_ULONG},
{"\x002""A4", CV_R68_A4, VALID68000, T_ULONG},
{"\x002""A5", CV_R68_A5, VALID68000, T_ULONG},
{"\x002""A6", CV_R68_A6, VALID68000, T_ULONG},
{"\x002""A7", CV_R68_A7, VALID68000, T_ULONG},
{"\x003""CCR", CV_R68_CCR, VALID68000, T_USHORT},
{"\x002""SR", CV_R68_SR, VALID68000, T_USHORT},
{"\x003""USP", CV_R68_USP, VALID68000, T_ULONG},
{"\x003""MSP", CV_R68_MSP, VALID68000, T_ULONG},
{"\x002""PC", CV_R68_PC, VALID68000, T_ULONG},
{"\x003""SFC", CV_R68_SFC, VALID68010, T_USHORT},
{"\x003""DFC", CV_R68_DFC, VALID68010, T_USHORT},
{"\x003""VBR", CV_R68_VBR, VALID68010, T_USHORT},
{"\x004""CACR", CV_R68_CACR, VALID68020, T_ULONG},
{"\x004""CAAR", CV_R68_CAAR, VALID68020, T_ULONG},
{"\x003""ISP", CV_R68_ISP, VALID68020, T_ULONG},
{"\x003""PSR", CV_R68_PSR, VALID68851, T_USHORT},
{"\x004""PCSR", CV_R68_PCSR, VALID68851, T_USHORT},
{"\x003""VAL", CV_R68_VAL, VALID68851, T_USHORT},
{"\x003""CRP", CV_R68_CRP, VALID68851, T_UQUAD},
{"\x003""SRP", CV_R68_SRP, VALID68851, T_UQUAD},
{"\x003""DRP", CV_R68_DRP, VALID68851, T_UQUAD},
{"\x002""TC", CV_R68_TC, VALID68851, T_ULONG},
{"\x002""AC", CV_R68_AC, VALID68851, T_USHORT},
{"\x003""SCC", CV_R68_SCC, VALID68851, T_USHORT},
{"\x003""CAL", CV_R68_CAL, VALID68851, T_USHORT},
{"\x004""BAD0", CV_R68_BAD0, VALID68851, T_USHORT},
{"\x004""BAD1", CV_R68_BAD1, VALID68851, T_USHORT},
{"\x004""BAD2", CV_R68_BAD2, VALID68851, T_USHORT},
{"\x004""BAD3", CV_R68_BAD3, VALID68851, T_USHORT},
{"\x004""BAD4", CV_R68_BAD4, VALID68851, T_USHORT},
{"\x004""BAD5", CV_R68_BAD5, VALID68851, T_USHORT},
{"\x004""BAD6", CV_R68_BAD6, VALID68851, T_USHORT},
{"\x004""BAD7", CV_R68_BAD7, VALID68851, T_USHORT},
{"\x004""BAC0", CV_R68_BAC0, VALID68851, T_USHORT},
{"\x004""BAC1", CV_R68_BAC1, VALID68851, T_USHORT},
{"\x004""BAC2", CV_R68_BAC2, VALID68851, T_USHORT},
{"\x004""BAC3", CV_R68_BAC3, VALID68851, T_USHORT},
{"\x004""BAC4", CV_R68_BAC4, VALID68851, T_USHORT},
{"\x004""BAC5", CV_R68_BAC5, VALID68851, T_USHORT},
{"\x004""BAC6", CV_R68_BAC6, VALID68851, T_USHORT},
{"\x004""BAC7", CV_R68_BAC7, VALID68851, T_USHORT},
{"\x003""TT0", CV_R68_TT0, VALID68030, T_ULONG},
{"\x003""TT1", CV_R68_TT1, VALID68030, T_ULONG},
{"\x004""FPCR", CV_R68_FPCR, VALID68882, T_ULONG},
{"\x004""FPSR", CV_R68_FPSR, VALID68882, T_ULONG},
{"\x005""FPIAR", CV_R68_FPIAR, VALID68882, T_ULONG},
{"\x003""FP0", CV_R68_FP0, VALID68882, T_REAL80},
{"\x003""FP1", CV_R68_FP1, VALID68882, T_REAL80},
{"\x003""FP2", CV_R68_FP2, VALID68882, T_REAL80},
{"\x003""FP3", CV_R68_FP3, VALID68882, T_REAL80},
{"\x003""FP4", CV_R68_FP4, VALID68882, T_REAL80},
{"\x003""FP5", CV_R68_FP5, VALID68882, T_REAL80},
{"\x003""FP6", CV_R68_FP6, VALID68882, T_REAL80},
{"\x003""FP7", CV_R68_FP7, VALID68882, T_REAL80},
};
#endif // M68K
struct hreg {
char name[9];
int index;
ushort type;
#ifdef WIN32
} hreg_list[] = {
#else
} _based (_segname("_CODE")) hreg_list[] = {
#endif
{"\x002""$p", CV_REG_PSEUDO1, T_ULONG},
{"\x003""$p1", CV_REG_PSEUDO1, T_ULONG},
{"\x003""$p2", CV_REG_PSEUDO2, T_ULONG},
{"\x003""$p3", CV_REG_PSEUDO3, T_ULONG},
{"\x003""$p4", CV_REG_PSEUDO4, T_ULONG},
{"\x002""$u", CV_REG_PSEUDO5, T_ULONG},
{"\x003""$u1", CV_REG_PSEUDO5, T_ULONG},
{"\x003""$u2", CV_REG_PSEUDO6, T_ULONG},
{"\x003""$u3", CV_REG_PSEUDO7, T_ULONG},
{"\x003""$u4", CV_REG_PSEUDO8, T_ULONG},
{"\x004""$exp", CV_REG_PSEUDO9, T_ULONG},
#ifdef TARGET_i386
{"\x002""AX", CV_REG_AX, T_USHORT},
{"\x002""BX", CV_REG_BX, T_USHORT},
{"\x002""CX", CV_REG_CX, T_USHORT},
{"\x002""DX", CV_REG_DX, T_USHORT},
{"\x002""SP", CV_REG_SP, T_USHORT},
{"\x002""BP", CV_REG_BP, T_USHORT},
{"\x002""SI", CV_REG_SI, T_USHORT},
{"\x002""DI", CV_REG_DI, T_USHORT},
{"\x002""DS", CV_REG_DS, T_USHORT},
{"\x002""ES", CV_REG_ES, T_USHORT},
{"\x002""SS", CV_REG_SS, T_USHORT},
{"\x002""CS", CV_REG_CS, T_USHORT},
{"\x002""IP", CV_REG_IP, T_USHORT},
{"\x002""FL", CV_REG_FLAGS, T_USHORT},
{"\x003""EFL", CV_REG_EFLAGS, T_ULONG},
{"\x003""EAX", CV_REG_EAX, T_ULONG},
{"\x003""EBX", CV_REG_EBX, T_ULONG},
{"\x003""ECX", CV_REG_ECX, T_ULONG},
{"\x003""EDX", CV_REG_EDX, T_ULONG},
{"\x003""ESP", CV_REG_ESP, T_ULONG},
{"\x003""EBP", CV_REG_EBP, T_ULONG},
{"\x003""ESI", CV_REG_ESI, T_ULONG},
{"\x003""EDI", CV_REG_EDI, T_ULONG},
{"\x003""EIP", CV_REG_EIP, T_ULONG},
{"\x002""FS", CV_REG_FS, T_USHORT},
{"\x002""GS", CV_REG_GS, T_USHORT},
{"\x002""AH", CV_REG_AH, T_UCHAR},
{"\x002""BH", CV_REG_BH, T_UCHAR},
{"\x002""CH", CV_REG_CH, T_UCHAR},
{"\x002""DH", CV_REG_DH, T_UCHAR},
{"\x002""AL", CV_REG_AL, T_UCHAR},
{"\x002""BL", CV_REG_BL, T_UCHAR},
{"\x002""CL", CV_REG_CL, T_UCHAR},
{"\x002""DL", CV_REG_DL, T_UCHAR},
{"\x002""st", CV_REG_ST0, T_REAL80},
{"\x003""st0", CV_REG_ST0, T_REAL80},
{"\x003""st1", CV_REG_ST1, T_REAL80},
{"\x003""st2", CV_REG_ST2, T_REAL80},
{"\x003""st3", CV_REG_ST3, T_REAL80},
{"\x003""st4", CV_REG_ST4, T_REAL80},
{"\x003""st5", CV_REG_ST5, T_REAL80},
{"\x003""st6", CV_REG_ST6, T_REAL80},
{"\x003""st7", CV_REG_ST7, T_REAL80},
{"\x003""cr0", CV_REG_CR0, T_ULONG},
{"\x003""cr1", CV_REG_CR1, T_ULONG},
{"\x003""cr2", CV_REG_CR2, T_ULONG},
{"\x003""cr3", CV_REG_CR3, T_ULONG},
{"\x003""cr4", CV_REG_CR4, T_ULONG},
{"\x003""dr0", CV_REG_DR0, T_ULONG},
{"\x003""dr1", CV_REG_DR1, T_ULONG},
{"\x003""dr2", CV_REG_DR2, T_ULONG},
{"\x003""dr3", CV_REG_DR3, T_ULONG},
{"\x003""dr4", CV_REG_DR4, T_ULONG},
{"\x003""dr5", CV_REG_DR5, T_ULONG},
{"\x003""dr6", CV_REG_DR6, T_ULONG},
{"\x003""dr7", CV_REG_DR7, T_ULONG},
#endif // TARGET_i386
#ifdef TARGET_PPC
{"\004""GPR0", CV_PPC_GPR0,T_ULONG},
{"\004""GPR1", CV_PPC_GPR1, T_ULONG},
{"\004""GPR2", CV_PPC_GPR2, T_ULONG},
{"\004""GPR3", CV_PPC_GPR3, T_ULONG},
{"\004""GPR4", CV_PPC_GPR4, T_ULONG},
{"\004""GPR5", CV_PPC_GPR5, T_ULONG},
{"\004""GPR6", CV_PPC_GPR6, T_ULONG},
{"\004""GPR7", CV_PPC_GPR7, T_ULONG},
{"\004""GPR8", CV_PPC_GPR8, T_ULONG},
{"\004""GPR9", CV_PPC_GPR9, T_ULONG},
{"\005""GPR10", CV_PPC_GPR10, T_ULONG},
{"\005""GPR11", CV_PPC_GPR11, T_ULONG},
{"\005""GPR12", CV_PPC_GPR12, T_ULONG},
{"\005""GPR13", CV_PPC_GPR13, T_ULONG},
{"\005""GPR14", CV_PPC_GPR14, T_ULONG},
{"\005""GPR15", CV_PPC_GPR15, T_ULONG},
{"\005""GPR16", CV_PPC_GPR16, T_ULONG},
{"\005""GPR17", CV_PPC_GPR17, T_ULONG},
{"\005""GPR18", CV_PPC_GPR18, T_ULONG},
{"\005""GPR19", CV_PPC_GPR19, T_ULONG},
{"\005""GPR20", CV_PPC_GPR20, T_ULONG},
{"\005""GPR21", CV_PPC_GPR21, T_ULONG},
{"\005""GPR22", CV_PPC_GPR22, T_ULONG},
{"\005""GPR23", CV_PPC_GPR23, T_ULONG},
{"\005""GPR24", CV_PPC_GPR24, T_ULONG},
{"\005""GPR25", CV_PPC_GPR25, T_ULONG},
{"\005""GPR30", CV_PPC_GPR30, T_ULONG},
{"\005""GPR26", CV_PPC_GPR26, T_ULONG},
{"\005""GPR27", CV_PPC_GPR27, T_ULONG},
{"\005""GPR28", CV_PPC_GPR28, T_ULONG},
{"\005""GPR29", CV_PPC_GPR29, T_ULONG},
{"\005""GPR31", CV_PPC_GPR31, T_ULONG},
// floating point registers follow
{"\004""FPR0", CV_PPC_FPR0, T_REAL64 },
{"\004""FPR1", CV_PPC_FPR1, T_REAL64 },
{"\004""FPR2", CV_PPC_FPR2, T_REAL64 },
{"\004""FPR3", CV_PPC_FPR3, T_REAL64 },
{"\004""FPR4", CV_PPC_FPR4, T_REAL64 },
{"\004""FPR5", CV_PPC_FPR5, T_REAL64 },
{"\004""FPR6", CV_PPC_FPR6, T_REAL64 },
{"\004""FPR7", CV_PPC_FPR7, T_REAL64 },
{"\004""FPR8", CV_PPC_FPR8, T_REAL64 },
{"\004""FPR9", CV_PPC_FPR9, T_REAL64 },
{"\005""FPR10", CV_PPC_FPR10, T_REAL64 },
{"\005""FPR11", CV_PPC_FPR11, T_REAL64 },
{"\005""FPR12", CV_PPC_FPR12, T_REAL64 },
{"\005""FPR13", CV_PPC_FPR13, T_REAL64 },
{"\005""FPR14", CV_PPC_FPR14, T_REAL64 },
{"\005""FPR15", CV_PPC_FPR15, T_REAL64 },
{"\005""FPR16", CV_PPC_FPR16, T_REAL64 },
{"\005""FPR17", CV_PPC_FPR17, T_REAL64 },
{"\005""FPR18", CV_PPC_FPR18, T_REAL64 },
{"\005""FPR19", CV_PPC_FPR19, T_REAL64 },
{"\005""FPR20", CV_PPC_FPR20, T_REAL64 },
{"\005""FPR21", CV_PPC_FPR21, T_REAL64 },
{"\005""FPR22", CV_PPC_FPR22, T_REAL64 },
{"\005""FPR23", CV_PPC_FPR23, T_REAL64 },
{"\005""FPR24", CV_PPC_FPR24, T_REAL64 },
{"\005""FPR25", CV_PPC_FPR25, T_REAL64 },
{"\005""FPR26", CV_PPC_FPR26, T_REAL64 },
{"\005""FPR27", CV_PPC_FPR27, T_REAL64 },
{"\005""FPR28", CV_PPC_FPR28, T_REAL64 },
{"\005""FPR29", CV_PPC_FPR29, T_REAL64 },
{"\005""FPR30", CV_PPC_FPR30, T_REAL64 },
{"\005""FPR31", CV_PPC_FPR31, T_REAL64 },
{"\005""FPSCR", CV_PPC_FPSCR, T_ULONG },
{"\002""LR", CV_PPC_LR, T_ULONG },
{"\002""CR", CV_PPC_CR, T_ULONG },
{"\003""CTR", CV_PPC_CTR, T_ULONG },
{"\003""CIA", CV_PPC_PC, T_ULONG },
{"\003""XER", CV_PPC_XER, T_ULONG },
{"\003""MSR", CV_PPC_MSR, T_ULONG }
#endif //TARGET_PPC
#ifdef TARGET_MIPS
{"\004""ZERO", CV_M4_IntZERO, T_ULONG},
{"\002""AT", CV_M4_IntAT, T_ULONG},
{"\002""V0", CV_M4_IntV0, T_ULONG},
{"\002""V1", CV_M4_IntV1, T_ULONG},
{"\002""A0", CV_M4_IntA0, T_ULONG},
{"\002""A1", CV_M4_IntA1, T_ULONG},
{"\002""A2", CV_M4_IntA2, T_ULONG},
{"\002""A3", CV_M4_IntA3, T_ULONG},
{"\002""T0", CV_M4_IntT0, T_ULONG},
{"\002""T1", CV_M4_IntT1, T_ULONG},
{"\002""T2", CV_M4_IntT2, T_ULONG},
{"\002""T3", CV_M4_IntT3, T_ULONG},
{"\002""T4", CV_M4_IntT4, T_ULONG},
{"\002""T5", CV_M4_IntT5, T_ULONG},
{"\002""T6", CV_M4_IntT6, T_ULONG},
{"\002""T7", CV_M4_IntT7, T_ULONG},
{"\002""T8", CV_M4_IntT8, T_ULONG},
{"\002""T9", CV_M4_IntT9, T_ULONG},
{"\002""S0", CV_M4_IntS0, T_ULONG},
{"\002""S1", CV_M4_IntS1, T_ULONG},
{"\002""S2", CV_M4_IntS2, T_ULONG},
{"\002""S3", CV_M4_IntS3, T_ULONG},
{"\002""S4", CV_M4_IntS4, T_ULONG},
{"\002""S5", CV_M4_IntS5, T_ULONG},
{"\002""S6", CV_M4_IntS6, T_ULONG},
{"\002""S7", CV_M4_IntS7, T_ULONG},
{"\002""S8", CV_M4_IntS8, T_ULONG},
{"\002""K0", CV_M4_IntKT0, T_ULONG},
{"\002""K1", CV_M4_IntKT1, T_ULONG},
{"\002""GP", CV_M4_IntGP, T_ULONG},
{"\002""SP", CV_M4_IntSP, T_ULONG},
{"\002""RA", CV_M4_IntRA, T_ULONG},
{"\003""FIR", CV_M4_Fir, T_ULONG},
{"\003""PSR", CV_M4_Psr, T_ULONG},
{"\003""FSR", CV_M4_FltFsr, T_ULONG},
{"\002""HI", CV_M4_IntHI, T_ULONG},
{"\002""LO", CV_M4_IntLO, T_ULONG},
{"\003""FR0", CV_M4_FltF0, T_REAL32},
{"\003""FR1", CV_M4_FltF1, T_REAL32},
{"\003""FR2", CV_M4_FltF2, T_REAL32},
{"\003""FR3", CV_M4_FltF3, T_REAL32},
{"\003""FR4", CV_M4_FltF4, T_REAL32},
{"\003""FR5", CV_M4_FltF5, T_REAL32},
{"\003""FR6", CV_M4_FltF6, T_REAL32},
{"\003""FR7", CV_M4_FltF7, T_REAL32},
{"\003""FR8", CV_M4_FltF8, T_REAL32},
{"\003""FR9", CV_M4_FltF9, T_REAL32},
{"\004""FR10", CV_M4_FltF10, T_REAL32},
{"\004""FR11", CV_M4_FltF11, T_REAL32},
{"\004""FR12", CV_M4_FltF12, T_REAL32},
{"\004""FR13", CV_M4_FltF13, T_REAL32},
{"\004""FR14", CV_M4_FltF14, T_REAL32},
{"\004""FR15", CV_M4_FltF15, T_REAL32},
{"\004""FR16", CV_M4_FltF16, T_REAL32},
{"\004""FR17", CV_M4_FltF17, T_REAL32},
{"\004""FR18", CV_M4_FltF18, T_REAL32},
{"\004""FR19", CV_M4_FltF19, T_REAL32},
{"\004""FR20", CV_M4_FltF20, T_REAL32},
{"\004""FR21", CV_M4_FltF21, T_REAL32},
{"\004""FR22", CV_M4_FltF22, T_REAL32},
{"\004""FR23", CV_M4_FltF23, T_REAL32},
{"\004""FR24", CV_M4_FltF24, T_REAL32},
{"\004""FR25", CV_M4_FltF25, T_REAL32},
{"\004""FR26", CV_M4_FltF26, T_REAL32},
{"\004""FR27", CV_M4_FltF27, T_REAL32},
{"\004""FR28", CV_M4_FltF28, T_REAL32},
{"\004""FR29", CV_M4_FltF29, T_REAL32},
{"\004""FR30", CV_M4_FltF30, T_REAL32},
{"\004""FR31", CV_M4_FltF31, T_REAL32},
{"\003""FP0", CV_M4_FltF0 << 8 | CV_M4_FltF1, T_REAL64},
{"\003""FP2", CV_M4_FltF2 << 8 | CV_M4_FltF3, T_REAL64},
{"\003""FP4", CV_M4_FltF4 << 8 | CV_M4_FltF5, T_REAL64},
{"\003""FP6", CV_M4_FltF6 << 8 | CV_M4_FltF7, T_REAL64},
{"\003""FP8", CV_M4_FltF8 << 8 | CV_M4_FltF9, T_REAL64},
{"\004""FP10", CV_M4_FltF10 << 8 | CV_M4_FltF11, T_REAL64},
{"\004""FP12", CV_M4_FltF12 << 8 | CV_M4_FltF13, T_REAL64},
{"\004""FP14", CV_M4_FltF14 << 8 | CV_M4_FltF15, T_REAL64},
{"\004""FP16", CV_M4_FltF16 << 8 | CV_M4_FltF17, T_REAL64},
{"\004""FP18", CV_M4_FltF18 << 8 | CV_M4_FltF19, T_REAL64},
{"\004""FP20", CV_M4_FltF20 << 8 | CV_M4_FltF21, T_REAL64},
{"\004""FP22", CV_M4_FltF22 << 8 | CV_M4_FltF23, T_REAL64},
{"\004""FP24", CV_M4_FltF24 << 8 | CV_M4_FltF25, T_REAL64},
{"\004""FP26", CV_M4_FltF26 << 8 | CV_M4_FltF27, T_REAL64},
{"\004""FP28", CV_M4_FltF28 << 8 | CV_M4_FltF29, T_REAL64},
{"\004""FP30", CV_M4_FltF30 << 8 | CV_M4_FltF31, T_REAL64},
#endif // TARGET_MIPS
#ifdef TARGET_ALPHA
{"\002""V0", CV_ALPHA_IntV0, T_UQUAD },
{"\002""T0", CV_ALPHA_IntT0, T_UQUAD },
{"\002""T1", CV_ALPHA_IntT1, T_UQUAD },
{"\002""T2", CV_ALPHA_IntT2, T_UQUAD },
{"\002""T3", CV_ALPHA_IntT3, T_UQUAD },
{"\002""T4", CV_ALPHA_IntT4, T_UQUAD },
{"\002""T5", CV_ALPHA_IntT5, T_UQUAD },
{"\002""T6", CV_ALPHA_IntT6, T_UQUAD },
{"\002""T7", CV_ALPHA_IntT7, T_UQUAD },
{"\002""S0", CV_ALPHA_IntS0, T_UQUAD },
{"\002""S1", CV_ALPHA_IntS1, T_UQUAD },
{"\002""S2", CV_ALPHA_IntS2, T_UQUAD },
{"\002""S3", CV_ALPHA_IntS3, T_UQUAD },
{"\002""S4", CV_ALPHA_IntS4, T_UQUAD },
{"\002""S5", CV_ALPHA_IntS5, T_UQUAD },
{"\002""FP", CV_ALPHA_IntFP, T_UQUAD },
{"\002""A0", CV_ALPHA_IntA0, T_UQUAD },
{"\002""A1", CV_ALPHA_IntA1, T_UQUAD },
{"\002""A2", CV_ALPHA_IntA2, T_UQUAD },
{"\002""A3", CV_ALPHA_IntA3, T_UQUAD },
{"\002""A4", CV_ALPHA_IntA4, T_UQUAD },
{"\002""A5", CV_ALPHA_IntA5, T_UQUAD },
{"\002""T8", CV_ALPHA_IntT8, T_UQUAD },
{"\002""T9", CV_ALPHA_IntT9, T_UQUAD },
{"\003""T10", CV_ALPHA_IntT10, T_UQUAD },
{"\003""T11", CV_ALPHA_IntT11, T_UQUAD },
{"\002""RA", CV_ALPHA_IntRA, T_UQUAD },
{"\003""T12", CV_ALPHA_IntT12, T_UQUAD },
{"\002""AT", CV_ALPHA_IntAT, T_UQUAD },
{"\002""GP", CV_ALPHA_IntGP, T_UQUAD },
{"\002""SP", CV_ALPHA_IntSP, T_UQUAD },
{"\004""ZERO", CV_ALPHA_IntZERO, T_UQUAD },
{"\002""F0", CV_ALPHA_FltF0, T_REAL64 },
{"\002""F1", CV_ALPHA_FltF1, T_REAL64 },
{"\002""F2", CV_ALPHA_FltF2, T_REAL64 },
{"\002""F3", CV_ALPHA_FltF3, T_REAL64 },
{"\002""F4", CV_ALPHA_FltF4, T_REAL64 },
{"\002""F5", CV_ALPHA_FltF5, T_REAL64 },
{"\002""F6", CV_ALPHA_FltF6, T_REAL64 },
{"\002""F7", CV_ALPHA_FltF7, T_REAL64 },
{"\002""F8", CV_ALPHA_FltF8, T_REAL64 },
{"\002""F9", CV_ALPHA_FltF9, T_REAL64 },
{"\003""F10", CV_ALPHA_FltF10, T_REAL64 },
{"\003""F11", CV_ALPHA_FltF11, T_REAL64 },
{"\003""F12", CV_ALPHA_FltF12, T_REAL64 },
{"\003""F13", CV_ALPHA_FltF13, T_REAL64 },
{"\003""F14", CV_ALPHA_FltF14, T_REAL64 },
{"\003""F15", CV_ALPHA_FltF15, T_REAL64 },
{"\003""F16", CV_ALPHA_FltF16, T_REAL64 },
{"\003""F17", CV_ALPHA_FltF17, T_REAL64 },
{"\003""F18", CV_ALPHA_FltF18, T_REAL64 },
{"\003""F19", CV_ALPHA_FltF19, T_REAL64 },
{"\003""F20", CV_ALPHA_FltF20, T_REAL64 },
{"\003""F21", CV_ALPHA_FltF21, T_REAL64 },
{"\003""F22", CV_ALPHA_FltF22, T_REAL64 },
{"\003""F23", CV_ALPHA_FltF23, T_REAL64 },
{"\003""F24", CV_ALPHA_FltF24, T_REAL64 },
{"\003""F25", CV_ALPHA_FltF25, T_REAL64 },
{"\003""F26", CV_ALPHA_FltF26, T_REAL64 },
{"\003""F27", CV_ALPHA_FltF27, T_REAL64 },
{"\003""F28", CV_ALPHA_FltF28, T_REAL64 },
{"\003""F29", CV_ALPHA_FltF29, T_REAL64 },
{"\003""F30", CV_ALPHA_FltF30, T_REAL64 },
{"\003""F31", CV_ALPHA_FltF31, T_REAL64 },
{"\003""FIR", CV_ALPHA_Fir, T_UQUAD },
{"\004""FPCR", CV_ALPHA_Fpcr, T_UQUAD },
{"\003""PSR", CV_ALPHA_Psr, T_ULONG }
#endif // TARGET_ALPHA
};
#define REGCNT (sizeof (hreg_list)/sizeof (struct hreg))
LOCAL bool_t
ParseRegister (
psearch_t pName
)
{
int i;
peval_t pv;
if (*pName->sstr.lpName == '@') {
pName->sstr.lpName++;
pName->sstr.cb--;
}
for (i = 0; i < REGCNT; i++) {
if (fnCmp ((LPSSTR) pName, NULL, hreg_list[i].name, FALSE) == 0)
break;
}
if (i >= REGCNT) {
return (HR_notfound);
}
pv = pName->pv;
EVAL_REG (pv) = hreg_list[i].index;
SetNodeType (pv, hreg_list[i].type);
EVAL_IS_REG (pv) = TRUE;
EVAL_STATE (pv) = EV_lvalue;
PushStack (pv);
return (HR_found);
}
#if defined (M68K)
/** TypeFromHreg - get the CV type of a register
*
* type = TypeFromHreg (hReg)
*
* Entry hReg = register index
*
* Returns the CV type of the register
* (T_NOTYPE if register not found)
*/
ushort
TypeFromHreg (
ushort hreg
)
{
int i;
for (i = 0; i < REGCNT; i++) {
if (hreg == hreg_list[i].index) {
return(hreg_list[i].type);
}
}
return(T_NOTYPE);
}
#endif
LOCAL bool_t
LineNumber (
psearch_t pName
)
{
uchar *pb = pName->sstr.lpName + 1;
uint i;
char c;
ulong val = 0;
//FLS fls;
HSF hsf;
ADDR addr;
SHOFF cbLine;
peval_t pv;
// convert line number
for (i = pName->sstr.cb - 1; i > 0; i--) {
c = *pb;
if (!isdigit (c)) {
// Must have reached the end
pExState->err_num = ERR_LINENUMBER;
return (HR_error);
}
val *= 10;
val += (c - '0');
if (val > 0xffff) {
// Must have overflowed
pExState->err_num = ERR_LINENUMBER;
return (HR_error);
}
pb++;
}
// Make sure we have the right address.
if (!ADDR_IS_LI( *SHpADDRFrompCXT( pCxt ) )) {
SHUnFixupAddr( SHpADDRFrompCXT( pCxt ) );
}
if ( (hsf = SLHsfFromPcxt ( pCxt ) ) &&
SLFLineToAddr ( hsf, (ushort) val, &addr, &cbLine, NULL ) ) {
pv = pName->pv;
if (ADDR_IS_FLAT( *SHpADDRFrompCXT( pCxt )) ) {
SetNodeType (pv, T_32PUCHAR);
} else if (ADDR_IS_OFF32( *SHpADDRFrompCXT( pCxt )) ) {
SetNodeType (pv, T_32PFUCHAR);
} else {
SetNodeType (pv, T_PFUCHAR);
}
EVAL_IS_LABEL (pv) = TRUE;
EVAL_STATE (pv) = EV_rvalue;
EVAL_SYM (pv) = addr;
EVAL_PTR (pv) = addr;
PushStack (pv);
return (HR_found);
}
else {
pExState->err_num = ERR_NOCODE;
return (HR_error);
}
pExState->err_num = ERR_BADCONTEXT;
return (HR_error);
}
/** InsertThis - rewrite bind tree to add this->
*
* fSuccess = InsertThis (pName);
*
* Entry pName = pointer to search structure
*
* Exit tree rewritten such that the node pn becomes OP_pointsto
* with the left node being OP_this and the right node being
* the original symbol
*
* Returns TRUE if tree rewritten
* FALSE if error
*/
LOCAL bool_t __fastcall
InsertThis (
psearch_t pName
)
{
ushort len = 2 * (sizeof (node_t) + sizeof (eval_t));
ushort Left;
ushort Right;
pnode_t pn;
bnode_t bn = pName->bn;
Left = pTree->node_next;
Right = Left + sizeof (node_t) + sizeof (eval_t);
if ((ushort)(pTree->size - Left) < len) {
if (!GrowETree (len)) {
NOTTESTED (FALSE);
pExState->err_num = ERR_NOMEMORY;
return (FALSE);
}
if (bnCxt != 0) {
// the context was pointing into the expression tree.
// since the expression tree could have been reallocated,
// we must recompute the context pointer
pCxt = SHpCXTFrompCXF ((PCXF)&(pnodeOfbnode(bnCxt))->v[0]);
}
}
// copy symbol to right node
_fmemcpy (pnodeOfbnode((bnode_t)Right), pnodeOfbnode(bn), sizeof (node_t) + sizeof (eval_t));
// insert OP_this node as left node
pn = pnodeOfbnode((bnode_t)Left);
_fmemset (pn, 0, sizeof (node_t) + sizeof (eval_t));
NODE_OP (pn) = OP_this;
// change original node to OP_pointsto
pn = pnodeOfbnode(bn);
_fmemset (pn, 0, sizeof (node_t) + sizeof (eval_t));
NODE_OP (pn) = OP_pointsto;
NODE_LCHILD (pn) = (bnode_t)Left;
NODE_RCHILD (pn) = (bnode_t)Right;
pTree->node_next += len;
return (TRUE);
}
/*
* load a constant symbol into a node.
*/
LOCAL bool_t
DebLoadConst (
peval_t pv,
CONSTPTR pSym,
HSYM hSym
)
{
uint skip = 0;
CV_typ_t type;
HTYPE hType;
plfEnum pEnum;
type = pSym->typind;
if (!CV_IS_PRIMITIVE (type)) {
// we also allow constants that are enumeration values, so check
// that the non-primitive type is an enumeration and set the type
// to the underlying type of the enum
MHOmfUnLock ((HDEP)hSym);
hType = THGetTypeFromIndex (EVAL_MOD (pv), type);
if (hType == 0) {
DASSERT (FALSE);
pSym = MHOmfLock ((HDEP)hSym);
pExState->err_num = ERR_BADOMF;
return (FALSE);
}
pEnum = (plfEnum)(&((TYPPTR)(MHOmfLock ((HDEP)hType)))->leaf);
if ((pEnum->leaf != LF_ENUM) || !CV_IS_PRIMITIVE (pEnum->utype)) {
DASSERT (FALSE);
MHOmfUnLock ((HDEP)hType);
pSym = MHOmfLock ((HDEP)hSym);
pExState->err_num = ERR_BADOMF;
return (FALSE);
}
MHOmfUnLock ((HDEP)hType);
pSym = MHOmfLock ((HDEP)hSym);
SetNodeType (pv, type);
// SetNodeType will resolve forward ref Enums - but we need to get the
// utype from the pv when this happens - sps
type = ENUM_UTYPE (pv);
}
else {
SetNodeType (pv, type);
}
EVAL_STATE (pv) = EV_rvalue;
if ((CV_MODE (type) != CV_TM_DIRECT) || ((CV_TYPE (type) != CV_SIGNED) &&
(CV_TYPE (type) != CV_UNSIGNED) && (CV_TYPE (type) != CV_INT))) {
DASSERT (FALSE);
pExState->err_num = ERR_BADOMF;
return (FALSE);
}
EVAL_ULONG (pv) = RNumLeaf (&pSym->value, &skip);
return (TRUE);
}