347 lines
9.1 KiB
C
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);
|
||
|
}
|
||
|
}
|