349 lines
9.3 KiB
C
349 lines
9.3 KiB
C
/*** debwalk.c - walk bound expression tree and perform operations
|
|
|
|
*/
|
|
|
|
#include "debexpr.h"
|
|
|
|
bool_t PushCXT (peval_t);
|
|
bool_t GetCXTL (pnode_t);
|
|
bool_t GetCXTFunction (pnode_t, pnode_t);
|
|
|
|
/** DoGetCXTL - Gets a list of symbols and contexts for expression
|
|
|
|
* status = DoGetCXTL (phTM, phCXTL)
|
|
|
|
* Entry phTM = pointer to handle to expression state structure
|
|
* phCXTL = pointer to handle for CXT list buffer
|
|
|
|
* Exit *phCXTL = handle for CXT list buffer
|
|
|
|
* Returns EENOERROR if no error
|
|
* status code if error
|
|
*/
|
|
|
|
ulong
|
|
DoGetCXTL (
|
|
PHTM phTM,
|
|
PHCXTL phCXTL
|
|
)
|
|
{
|
|
ulong retval = EECATASTROPHIC;
|
|
|
|
// lock the expression state structure and copy the context package
|
|
|
|
DASSERT (*phTM != 0);
|
|
if (*phTM != 0) {
|
|
pExState = (pexstate_t) MemLock (*phTM);
|
|
if ((pExState->state.parse_ok == TRUE) &&
|
|
(pExState->state.bind_ok == TRUE)) {
|
|
if ((hCxtl = MemAllocate (sizeof (CXTL) + 5 * sizeof (HCS))) == 0) {
|
|
pExState->err_num = ERR_NOMEMORY;
|
|
MemUnLock (*phTM);
|
|
*phCXTL = hCxtl;
|
|
return (EEGENERAL);
|
|
} else {
|
|
pCxtl = (PCXTL) MemLock (hCxtl);
|
|
mCxtl = 5;
|
|
pCxtl->CXT = pExState->cxt;
|
|
pCxtl->cHCS = 0;
|
|
|
|
}
|
|
pTree = (pstree_t) MemLock (pExState->hETree);
|
|
if (GetCXTL ((pnode_t)((bnode_t)pTree->start_node))) {
|
|
retval = EENOERROR;
|
|
} else {
|
|
retval = EEGENERAL;
|
|
}
|
|
*phCXTL = hCxtl;
|
|
MemUnLock (hCxtl);
|
|
MemUnLock (pExState->hETree);
|
|
}
|
|
MemUnLock (*phTM);
|
|
}
|
|
return (retval);
|
|
}
|
|
|
|
|
|
|
|
/** GetCXTL - get CXT list from bound expression tree
|
|
|
|
* fSuccess = GetCXTL (pn)
|
|
|
|
* Entry pn = pointer to node
|
|
* hCxtl = handle of CXT list
|
|
* pCxtl = pointer to CXT list
|
|
* mCxtl = maximum number of context list entries
|
|
|
|
* Exit *phCXTL = handle for CXT list
|
|
|
|
* Returns TRUE if no error
|
|
* FALSEif error
|
|
*/
|
|
|
|
|
|
bool_t
|
|
GetCXTL (
|
|
pnode_t pn
|
|
)
|
|
{
|
|
PCXT oldCxt;
|
|
bool_t retval;
|
|
peval_t pv;
|
|
CXT Cxt;
|
|
|
|
// Recurse down the tree.
|
|
|
|
pv = &pn->v[0];
|
|
switch (NODE_OP (pn)) {
|
|
case OP_typestr:
|
|
return (TRUE);
|
|
|
|
case OP_const:
|
|
#pragma message ("Remove following code when 'langapi' for v3 exists")
|
|
//Cxt = *pCxt;
|
|
//memset (SHpADDRFrompCXT (pCxt), 0, sizeof (ADDR));
|
|
retval = PushCXT (pv);
|
|
//*pCxt = Cxt;
|
|
return (retval);
|
|
|
|
case OP_ident:
|
|
case OP_this:
|
|
case OP_hsym:
|
|
case OP_retval:
|
|
return (PushCXT (pv));
|
|
|
|
case OP_cast:
|
|
return (GetCXTL ((pnode_t)NODE_RCHILD (pn)));
|
|
|
|
case OP_function:
|
|
return (GetCXTFunction ((pnode_t)NODE_LCHILD (pn), (pnode_t)NODE_RCHILD (pn)));
|
|
|
|
case OP_context:
|
|
// Set the new context for evaluation of the remainder of this
|
|
// part of the tree
|
|
|
|
oldCxt = pCxt;
|
|
pCxt = SHpCXTFrompCXF ((PCXF)&pn->v[0]);
|
|
retval = GetCXTL ((pnode_t)NODE_LCHILD (pn));
|
|
pCxt = oldCxt;
|
|
return (retval);
|
|
|
|
// All other operators come through here. Recurse down the tree
|
|
|
|
default:
|
|
if (!GetCXTL ((pnode_t)NODE_LCHILD (pn)))
|
|
return (FALSE);
|
|
|
|
if ((pn->pnRight != 0) && (!GetCXTL ((pnode_t)NODE_RCHILD (pn))))
|
|
return (FALSE);
|
|
|
|
return (TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
/** GetExpr - get expression from bound expression tree
|
|
|
|
* status = GetExpr (radix, phStr, pEnd);
|
|
|
|
* Entry radix = numeric radix for formatting
|
|
* phStr = pointer to handle for formatted string
|
|
* pEnd = pointer to int to receive index of char that ended parse
|
|
|
|
* Exit *phStr = handle for allocated expression
|
|
* *pEnd = index of character that terminated parse
|
|
|
|
* Returns EENOERROR if no error
|
|
* error number if
|
|
*/
|
|
|
|
EESTATUS
|
|
GetExpr (
|
|
uint radix,
|
|
PEEHSTR phStr,
|
|
ulong *pEnd
|
|
)
|
|
{
|
|
EESTATUS retval = EENOMEMORY;
|
|
char *pStr;
|
|
char *pExprStr;
|
|
HDEP hExprStr;
|
|
int len;
|
|
ulong strIndex;
|
|
UINT nLen;
|
|
|
|
Unreferenced( radix );
|
|
|
|
//M00KLUDGE - this routine will eventuall have to walk the bound tree
|
|
// and format the expression because of ambiguous expressions
|
|
|
|
// use the saved original string if there is one
|
|
// (in case the expression has been modified)
|
|
|
|
if (pExState->hExStrSav) {
|
|
hExprStr = pExState->hExStrSav;
|
|
len = pExState->ExLenSav;
|
|
strIndex = pExState->strIndexSav;
|
|
} else {
|
|
hExprStr = pExState->hExStr;
|
|
len = pExState->ExLen;
|
|
strIndex = pExState->strIndex;
|
|
}
|
|
|
|
pExprStr = (char *) MemLock (hExprStr);
|
|
|
|
nLen = len+1;
|
|
if (((*phStr = MemAllocate (nLen)) != 0)) {
|
|
// the expression has been bound and memory allocated
|
|
char tempBuf[TYPESTRMAX];
|
|
UINT nb;
|
|
UINT nIndex = 0;
|
|
BOOL fHSYM;
|
|
char *psz;
|
|
ulong nAdj = 0;
|
|
|
|
pStr = (char *) MemLock (*phStr);
|
|
for (psz = pExprStr; (psz < pExprStr + len) && *psz; psz = _tcsinc (psz)) {
|
|
fHSYM = FALSE;
|
|
if (*psz == HSYM_MARKER) {
|
|
HSYM hSym = GetHSYMFromHSYMCode(psz + 1);
|
|
psz += HSYM_CODE_LEN; // skip embedded HSYM code
|
|
fHSYM = TRUE;
|
|
DASSERT (hSym);
|
|
if (GetNameFromHSYM(tempBuf, hSym) == FALSE) {
|
|
pExState->err_num = ERR_INTERNAL;
|
|
MemUnLock(*phStr);
|
|
MemUnLock(hExprStr);
|
|
return EEGENERAL;
|
|
}
|
|
nb = _tcslen(tempBuf);
|
|
// compute adjustment for strIndex:
|
|
// if an HSYM is to the left of strIndex,
|
|
// strIndex needs to be adjusted
|
|
if (psz <= pExprStr + strIndex)
|
|
nAdj += (nb - sizeof (char) - HSYM_CODE_LEN);
|
|
} else {
|
|
nb = 1;
|
|
}
|
|
|
|
// check if there is space in the buffer and
|
|
// copy nb characters to the destination string
|
|
|
|
if (nIndex + nb > nLen-1) {
|
|
// there is not enough space, grow buffer
|
|
MemUnLock(*phStr);
|
|
nLen += NAMESTRMAX;
|
|
if ((*phStr = MemReAlloc(*phStr, nLen)) == 0){
|
|
MemUnLock(hExprStr);
|
|
return EENOMEMORY;
|
|
}
|
|
pStr = (char *) MemLock (*phStr);
|
|
}
|
|
if (fHSYM) {
|
|
// copy name from tembBuf
|
|
memcpy(pStr+nIndex, tempBuf, nb);
|
|
nIndex += nb;
|
|
} else {
|
|
// copy a single character from pExprStr
|
|
_tccpy (pStr + nIndex, psz);
|
|
nIndex += _tclen (psz);
|
|
}
|
|
}
|
|
pStr[nIndex++] = 0;
|
|
MemUnLock (*phStr);
|
|
|
|
// Reallocate the buffer in case it is too large
|
|
DASSERT (nIndex <= nLen);
|
|
if (nIndex < nLen &&
|
|
(*phStr = MemReAlloc(*phStr, nIndex)) == 0){
|
|
MemUnLock(hExprStr);
|
|
return EENOMEMORY;
|
|
}
|
|
retval = EENOERROR;
|
|
*pEnd = strIndex + nAdj;
|
|
}
|
|
MemUnLock (hExprStr);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/** PushCXT - Push CXT list entry
|
|
|
|
* fSuccess = PushCXT (pv)
|
|
|
|
* Entry pv = pointer to evaluation
|
|
* hCxtl = handle of CXT list
|
|
* pCxtl = pointer to CXT list
|
|
* mCxtl = maximum number of context list entries
|
|
|
|
* Exit CXT entry pushed
|
|
|
|
* Returns TRUE if no error
|
|
* FALSE if error
|
|
*/
|
|
|
|
bool_t
|
|
PushCXT (
|
|
peval_t pv
|
|
)
|
|
{
|
|
HCXTL nhCxtl;
|
|
PCXTL npCxtl;
|
|
uint lenIn;
|
|
uint lenOut;
|
|
|
|
DASSERT (pCxtl->cHCS <= mCxtl);
|
|
if (mCxtl < pCxtl->cHCS) {
|
|
// this is a catatrosphic error
|
|
return (FALSE);
|
|
}
|
|
if (mCxtl == pCxtl->cHCS) {
|
|
// grow CXT list
|
|
|
|
lenIn = sizeof (CXTL) + mCxtl * sizeof (HCS);
|
|
lenOut = sizeof (CXTL) + (mCxtl + 5) * sizeof (HCS);
|
|
if ((nhCxtl = MemAllocate (lenOut)) == 0) {
|
|
return (FALSE);
|
|
}
|
|
npCxtl = (PCXTL) MemLock (nhCxtl);
|
|
memcpy (npCxtl, pCxtl, lenIn);
|
|
mCxtl += 5;
|
|
MemUnLock (hCxtl);
|
|
MHMemFree (hCxtl);
|
|
hCxtl = nhCxtl;
|
|
pCxtl = npCxtl;
|
|
}
|
|
|
|
// in case of a constant we will return only the context information.
|
|
// anything more than that doesn't make sense and since we
|
|
// need to get context only information in the case of bp {..}.line
|
|
// we needed to make this change.
|
|
|
|
pCxtl->rgHCS[pCxtl->cHCS].hSym = pv->hSym;
|
|
// Change for Dolphin bp functionality:
|
|
// if pv->CXTT is non-zero, prefer it over *pCxt:
|
|
// pv->CXTT is more specific, as it contains the exact
|
|
// context where a symbol was found by SearchSym, while
|
|
// pCxt just contains a context from which the symbol is
|
|
// visible
|
|
pCxtl->rgHCS[pCxtl->cHCS].CXT = (pv->CXTT.hMod) ? pv->CXTT : *pCxt;
|
|
pCxtl->cHCS++;
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
bool_t
|
|
GetCXTFunction (
|
|
pnode_t pnLeft,
|
|
pnode_t pnRight
|
|
)
|
|
{
|
|
Unreferenced( pnLeft );
|
|
Unreferenced( pnRight );
|
|
|
|
return (FALSE);
|
|
}
|