Windows2000/private/windbg64/debugger/ee/debtree.c
2020-09-30 17:12:32 +02:00

347 lines
9.1 KiB
C

/*** DEBTREE.C - Routines for building expression tree
* Routines to take tokens lexed from expression string
* and add to expression tree (tree building routines).
*/
#include "debexpr.h"
ulong AddLeaf (ptoken_t);
ulong AddNode (ptoken_t);
/*** PushToken - Push a token onto expression stack
* fSuccess = PushToken (ptok)
* Entry ptok = pointer to token_t structure to add
* Returns TRUE if token pushed ont expression stack
* FALSE if error
*/
ulong
PushToken (
ptoken_t ptok
)
{
ulong retVal;
if (OP_IS_IDENT (ptok->opTok)) {
// if the node is an identifier, constant or end of function arguments
// just add it to the tree
retVal = AddLeaf (ptok);
} else {
retVal = AddNode (ptok);
}
return (retVal);
}
/*** AddLeaf - Add a leaf node to the expression tree
* fSuccess = AddLeaf (ptok)
* Entry ptok = pointer to token to add to tree
* pExState->hStree = handle of syntax tree buffer
* Returns TRUE if successful
* FALSE if not and sets DebErr
* Notes The start_node index in the stree_t structure is not changed
* by AddLeaf. If there is only a single node, (OP_ident or
* OP_const), then start_node points to the correct node that
* was set by the routine that initialized the tree buffer.
* AddNode will set the correct node if there is a
* more complex parse tree.
*/
ulong
AddLeaf (
ptoken_t ptok
)
{
pnode_t pn;
peval_t pv;
bnode_t *ia;
uint len;
// check for space
// check for stack space too... [Dolphin 10293]
if (pTree->stack_next >= NSTACK_MAX) {
pExState->err_num = ERR_TOOCOMPLEX;
return (EEGENERAL);
}
len = sizeof (node_t) + sizeof (eval_t);
if ((uint)(pTree->stack_base - pTree->node_next) < len) {
// syntax tree is full, grow it
if (!GrowTree (NODE_DEFAULT)) {
// grow failed, clean up and return error
pExState->err_num = ERR_TOOCOMPLEX;
return (EEGENERAL);
}
}
pn = (pnode_t)((bnode_t)(pTree->node_next));
// Initialize the Node.
memset ((char *)pn, 0, len);
NODE_OP (pn) = ptok->opTok;
pv = &pn->v[0];
EVAL_ITOK (pv) = ptok->iTokStart;
EVAL_CBTOK (pv) = ptok->cbTok;
// If the node is a constant, retrieve its value from the token.
if (NODE_OP (pn) == OP_const) {
EVAL_TYP (pv) = ptok->typ;
EVAL_VAL (pv) = VAL_VAL (ptok);
}
ia = (bnode_t *)((char *)pTree + pTree->stack_base);
ia[pTree->stack_next++] = (bnode_t)(pTree->node_next);
pTree->node_next += len;
return (0);
}
/** AddNode - Add an operator node to the expression tree
* fSuccess = AddNode (ptok)
* Entry ptok = pointer to token to add
* Returns TRUE if node was added to tree
* FALSE if error
* Notes AddNode will set the start_node index in the stree_t structure
* to point to the node just added. If the statement is
* correctly parsed, start_node will contain the index of the
* last operator and there will be only one node on the stack
*/
ulong
AddNode (
ptoken_t ptok
)
{
pnode_t pn;
ulong retval = 0;
ulong iStack;
bnode_t *ia;
uint len;
// check for space
iStack = pTree->stack_next;
// check for stack space too... [Dolphin 10293]
if (iStack >= NSTACK_MAX) {
pExState->err_num = ERR_TOOCOMPLEX;
return (EEGENERAL);
}
switch (ptok->opTok) {
case OP_cast:
case OP_function:
case OP_sizeof:
case OP_dot:
case OP_pointsto:
case OP_bscope:
case OP_uscope:
case OP_pmember:
case OP_dotmember:
// these operators use the eval_t portion of the node to store
// casting information. In the case of the OP_dot, etc., the
// casting information is the implicit cast of the left member
// to a base class if one is required.
len = sizeof (node_t) + sizeof (eval_t);
break;
case OP_arg:
len = sizeof (node_t) + sizeof (argd_t);
break;
case OP_context:
case OP_execontext:
len = sizeof (node_t) + sizeof (CXF);
break;
// these are weird asm ops - that could also be idents
// if no operand - assume ident
// sps - 9/9/92
case OP_dw:
case OP_by:
case OP_wo:
if (iStack < 1) {
ptok->opTok = OP_ident;
return (AddLeaf (ptok));
}
default:
len = sizeof (node_t);
break;
}
len = (len + 1) & ~1;
if ((uint)(pTree->stack_base - pTree->node_next) < len) {
// syntax tree is full, grow it
if (!GrowTree (NODE_DEFAULT)) {
// grow failed, clean up and return error
pExState->err_num = ERR_TOOCOMPLEX;
return (EEGENERAL);
}
}
pn = (pnode_t)((bnode_t)(pTree->node_next));
// Initialize the Node.
memset (pn, 0, len);
NODE_OP (pn) = ptok->opTok;
if (ptok->opTok == OP_context || ptok->opTok == OP_execontext) {
EVAL_ITOK (&pn->v[0]) = ptok->iTokStart;
EVAL_CBTOK (&pn->v[0]) = ptok->cbTok;
}
// Set up the left and right children (left only if unary).
ia = (bnode_t *)((char *)pTree + pTree->stack_base);
if (OP_IS_BINARY (ptok->opTok)) {
if (iStack < 2) {
pExState->err_num = ERR_NOOPERAND;
retval = EEGENERAL;
}
else {
pn->pnRight = ia[--iStack];
pn->pnLeft = ia[--iStack];
}
} else {
if (iStack < 1) {
pExState->err_num = ERR_NOOPERAND;
retval = EEGENERAL;
}
else {
pn->pnLeft = ia[--iStack];
pn->pnRight = NULL;
}
}
// set this node into the start_node
if (retval == 0) {
ia[iStack++] = (bnode_t)(pTree->node_next);
pTree->start_node = pTree->node_next;
pTree->node_next += len;
pTree->stack_next = iStack;
}
return (retval);
}
/*** GrowTree - Grow space for the expression tree
* error = GrowTree (incr)
* Entry incr = amount to increase tree size
* pExState = address of expression state structure
* pExState->hSTree locked
* Exit pExState->hSTree locked
* pTree = address of locked syntax tree
* Returns TRUE if successful
* FALSE if unsuccessful
*/
bool_t FASTCALL
GrowTree (
uint incr
)
{
register HDEP NewTree;
register uint len;
len = pTree->size + incr;
MHMemUnLock (pExState->hSTree);
if ((NewTree = MHMemReAlloc (pExState->hSTree, len)) == 0) {
pTree = (pstree_t) MHMemLock (pExState->hSTree);
return (FALSE);
} else {
// reallocation succeeded, move data within buffer and update header
pExState->hSTree = NewTree;
pTree = (pstree_t) MHMemLock (pExState->hSTree);
pTree->size = len;
// move parse stack down by allocated amount if the stack is in use
// by the parser. Stack in use is indicated by non-zero stack_base.
// If we are in the bind phase, stack_base is zero,
if (pTree->stack_base != 0) {
memcpy ((char *)pTree + pTree->stack_base + NODE_DEFAULT,
(char *)pTree + pTree->stack_base,
NSTACK_MAX * sizeof (bnode_t));
pTree->stack_base += NODE_DEFAULT;
}
return (TRUE);
}
}
/*** GrowETree - Grow space for the expression tree
* error = GrowETree (incr)
* Entry incr = amount to increase tree size
* pExState = address of expression state structure
* pExState->hETree locked
* Exit pExState->hETree locked
* pTree = address of locked syntax tree
* Returns TRUE if successful
* FALSE if unsuccessful
*/
bool_t FASTCALL
GrowETree (
uint incr
)
{
register HDEP NewTree;
register uint len;
len = pTree->size + incr;
MHMemUnLock (pExState->hETree);
if ((NewTree = MHMemReAlloc (pExState->hETree, len)) == 0) {
pTree = (pstree_t) MHMemLock (pExState->hETree);
return (FALSE);
} else {
// reallocation succeeded, move data within buffer and update header
pExState->hETree = NewTree;
pTree = (pstree_t) MHMemLock (pExState->hETree);
pTree->size = len;
// move parse stack down by allocated amount if the stack is in use
// by the parser. Stack in use is indicated by non-zero stack_base.
// If we are in the bind phase, stack_base is zero,
if (pTree->stack_base != 0) {
memcpy ((char *)pTree + pTree->stack_base + NODE_DEFAULT,
(char *)pTree + pTree->stack_base,
NSTACK_MAX * sizeof (bnode_t));
pTree->stack_base += NODE_DEFAULT;
}
return (TRUE);
}
}