ptree.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,173 行 · 第 1/5 页

C
2,173
字号
/********************************************************************/
{
    CPP_FLOAT *fp_rep;

    fp_rep = makeFPRep( buff, len );
    return PTreeFloatingConstant( fp_rep, id );
}

PTREE PTreeFloatingConstant( CPP_FLOAT *rep, type_id id )
/*******************************************************/
{
    PTREE new_tree;

    new_tree = allocConstant( PT_FLOATING_CONSTANT, id );
    new_tree->u.floating_constant = rep;
    new_tree = PTreeCheckFloatRepresentation( new_tree );
    return new_tree;
}

PTREE PTreeId( char *id )
/***********************/
{
    PTREE new_tree;

    new_tree = PTreeAlloc();
    new_tree->op = PT_ID;
    new_tree->cgop = CO_NAME_NORMAL;
    new_tree->u.id.name = id;
    new_tree->u.id.scope = NULL;
    return new_tree;
}

PTREE PTreeIc(                  // CREATE PT_IC NODE
    unsigned opcode,            // - IC opcode
    CGVALUE value )             // - IC value
{
    PTREE node;                 // - new node

    node = PTreeAlloc();
    node->op = PT_IC;
    node->u.ic.opcode = opcode;
    node->u.ic.value = value;
    node->flags |= PTF_LV_CHECKED;
    return node;
}

PTREE PTreeIdSym( SYMBOL sym )
/****************************/
{
    return PTreeId( sym->name->name );
}

PTREE PTreeThis( void )
/*********************/
{
    PTREE node;                 // - new node

    node = PTreeId( CppSpecialName( SPECIAL_THIS ) );
    node->cgop = CO_NAME_THIS;
    return node;
}

PTREE PTreeCDtorExtra( void )
/***************************/
{
    PTREE node;                 // - new node

    node = PTreeId( CppSpecialName( SPECIAL_CDTOR_EXTRA ) );
    node->cgop = CO_NAME_CDTOR_EXTRA;
    return node;
}


boolean PTreePropogateError(    // CHECK AND PROPOGATE ERRORS FROM SUB-TREES
    PTREE curr )                // - current node
{
    unsigned op;                // - current expr op
    PTREE left;                 // - left subtree
    PTREE right;                // - right subtree

    DbgAssert( curr != NULL );
    op = curr->op;
    if( ptreePTSFlags[ op ] & PTS_OPERATOR ) {
        left = curr->u.subtree[0];
        if( left != NULL && left->op == PT_ERROR ) {
            PTreeErrorNode( curr );
            return TRUE;
        }
    }
    if( ptreePTSFlags[ op ] & PTS_BINARY ) {
        right = curr->u.subtree[1];
        if( right != NULL && right->op == PT_ERROR ) {
            PTreeErrorNode( curr );
            return TRUE;
        }
    }
    return FALSE;
}


PTREE PTreeTraversePostfix(     // TRAVERSE A PTREE IN (LEFT,RIGHT,SELF) ORDER
    PTREE tree,                 // - tree to be traversed
    PTREE (*visit_rtn)          // - visiting routine
        ( PTREE curr ) )        // - - addr( current node )
{
    PTREE parent;
    PTREE temp;
    PTREE left;
    PTREE right;

    /*
        The states represent locations in the traditional recursive version
        of a postfix traversal function.

        postfix( tree )
        {
                                        PTREE_LEFT
            postfix( tree->left )
                                        PTREE_RIGHT
            postfix( tree->right )
                                        PTREE_PROCESS
            process( tree )
                                        PTREE_UNWIND
        }

        note: this routine is heavily used so it has been optimized
        to use gotos since the current codegen can't optimize an
        assignment of a constant to a variable and an immediate
        switch statement to a simple goto.  The switch() style has
        been preserved for less heavily used traversal routines.
    */
    if( tree == NULL || tree->op == PT_ERROR ) {
        return tree;
    }
    parent = NULL;
    PTREE_LEFT:
        if( tree->flags & PTF_DUP_VISITED ) {
            goto PTREE_UNWIND;
        } else if( ptreePTSFlags[ tree->op ] & PTS_OPERATOR ) {
            left = tree->u.subtree[0];
            if( left != NULL ) {
                /* has a left subtree; store current parent */
                temp = tree;
                tree = left;
                temp->u.subtree[0] = parent;
                temp->flags |= PTF_TRAVERSE_LEFT;
                parent = temp;

                /* descend to left child node */
                goto PTREE_LEFT;
            }
            /* descend to right child node */
            goto PTREE_RIGHT;
        } else {
            /* no subtrees; process this node */
            goto PTREE_PROCESS;
        }
    PTREE_RIGHT:
        if( ptreePTSFlags[ tree->op ] & PTS_BINARY ) {
            right = tree->u.subtree[1];
            if( right != NULL ) {
                /* has a right subtree; store current parent */
                temp = tree;
                tree = right;
                temp->u.subtree[1] = parent;
                temp->flags &= ~PTF_TRAVERSE_LEFT;
                parent = temp;

                /* descend to right child node */
                goto PTREE_LEFT;
            } else {
                /* no right subtree; process this node */
                goto PTREE_PROCESS;
            }
        } else {
            /* no right subtree; process this node */
            goto PTREE_PROCESS;
        }
    PTREE_PROCESS:
        /* process node; may replace parent's pointer to this node */
        tree = (*visit_rtn)( tree );
        goto PTREE_UNWIND;
    PTREE_UNWIND:
        if( parent == NULL ) {
            return tree;
        }
        if( parent->flags & PTF_TRAVERSE_LEFT ) {
            parent->flags &= ~PTF_TRAVERSE_LEFT;
            /* set child pointer of parent to current subtree */
            temp = parent;
            parent = temp->u.subtree[0];
            temp->u.subtree[0] = tree;
            tree = temp;

            /* processed a left child; try for right hand child of parent */
            goto PTREE_RIGHT;
        } else {
            /* set child pointer of parent to current subtree */
            temp = parent;
            parent = temp->u.subtree[1];
            temp->u.subtree[1] = tree;
            tree = temp;

            /* processed a right child; process parent */
            goto PTREE_PROCESS;
        }
}

// The following is a cut-paste version of PTreeTraversePostfix, with
// traversals to the left of commas eliminated
//
PTREE PTreeTraverseInitRef(     // TRAVERSE A PTREE FOR REFERENCE INIT.
    PTREE tree,                 // - tree to be traversed
    PTREE (*visit_rtn)          // - visiting routine
        ( PTREE curr ) )        // - - addr( current node )
{
    PTREE parent;
    PTREE temp;
    PTREE left;
    PTREE right;
    PTREE_STATE state;

    /*
        The states represent locations in the traditional recursive version
        of a postfix traversal function.

        postfix( tree )
        {
                                        PTREE_LEFT
            postfix( tree->left )
                                        PTREE_RIGHT
            postfix( tree->right )
                                        PTREE_PROCESS
            process( tree )
                                        PTREE_UNWIND
        }
    */
    if( tree == NULL || tree->op == PT_ERROR ) {
        return tree;
    }
    state = PTREE_LEFT;
    parent = NULL;
    for(;;) {
        switch( state ) {
        case PTREE_LEFT:
            if( ptreePTSFlags[ tree->op ] & PTS_OPERATOR ) {
                left = tree->u.subtree[0];
                if( left != NULL
                 && !( tree->op == PT_BINARY && tree->cgop == CO_COMMA ) ) {
                    /* has a left subtree; store current parent */
                    temp = tree;
                    tree = left;
                    temp->u.subtree[0] = parent;
                    temp->flags |= PTF_TRAVERSE_LEFT;
                    parent = temp;

                    /* descend to left child node */
                    state = PTREE_LEFT;
                } else {
                    /* descend to right child node */
                    state = PTREE_RIGHT;
                }
            } else {
                /* no subtrees; process this node */
                state = PTREE_PROCESS;
            }
            continue;
        case PTREE_RIGHT:
            if( ptreePTSFlags[ tree->op ] & PTS_BINARY ) {
                right = tree->u.subtree[1];
                if( right != NULL ) {
                    /* has a right subtree; store current parent */
                    temp = tree;
                    tree = right;
                    temp->u.subtree[1] = parent;
                    temp->flags &= ~PTF_TRAVERSE_LEFT;
                    parent = temp;

                    /* descend to right child node */
                    state = PTREE_LEFT;
                } else {
                    /* no right subtree; process this node */
                    state = PTREE_PROCESS;
                }
            } else {
                /* no right subtree; process this node */
                state = PTREE_PROCESS;
            }
            continue;
        case PTREE_PROCESS:
            /* process node; may replace parent's pointer to this node */
            tree = (*visit_rtn)( tree );
            state = PTREE_UNWIND;
            /* fall through */
        case PTREE_UNWIND:
            if( parent == NULL ) {
                break;
            }
            if( parent->flags & PTF_TRAVERSE_LEFT ) {
                parent->flags &= ~PTF_TRAVERSE_LEFT;
                /* set child pointer of parent to current subtree */
                temp = parent;
                parent = temp->u.subtree[0];
                temp->u.subtree[0] = tree;
                tree = temp;

                /* processed a left child; try for right hand child of parent */
                state = PTREE_RIGHT;
            } else {
                /* set child pointer of parent to current subtree */
                temp = parent;
                parent = temp->u.subtree[1];
                temp->u.subtree[1] = tree;
                tree = temp;

                /* processed a right child; process parent */
                state = PTREE_PROCESS;
            }
            continue;
        }
        break;
    }
    return tree;
}


PTREE PTreeTraversePrefix(      // TRAVERSE A PTREE IN (SELF,LEFT,RIGHT) ORDER
    PTREE tree,                 // - tree to be traversed
    PTREE (*visit_rtn)          // - visiting routine
        ( PTREE curr ) )        // - - addr( current node )
{
    PTREE parent;
    PTREE temp;
    PTREE_STATE state;

    /*
        The states represent locations in the traditional recursive version
        of a prefix traversal function.

        prefix( tree )
        {
                                        PTREE_PROCESS
            process( tree )
                                        PTREE_LEFT
            postfix( tree->left )
                                        PTREE_RIGHT
            postfix( tree->right )
                                        PTREE_UNWIND
        }
    */
    if( tree == NULL || tree->op == PT_ERROR ) {
        return tree;
    }
    state = PTREE_PROCESS;
    parent = NULL;
    for(;;) {
        switch( state ) {
        case PTREE_PROCESS:
            /* process node */
            tree = (*visit_rtn)( tree );
            state = PTREE_LEFT;
            /* fall through */
        case PTREE_LEFT:
            if( ptreePTSFlags[ tree->op ] & PTS_OPERATOR ) {
                if( tree->u.subtree[0] != NULL ) {
                    /* has a left subtree; store current parent */
                    temp = tree;
                    tree = temp->u.subtree[0];
                    temp->u.subtree[0] = parent;
                    temp->flags |= PTF_TRAVERSE_LEFT;
                    parent = temp;

                    /* descend to left child node */
                    state = PTREE_PROCESS;
                } else {
                    /* descend to right child node */
                    state = PTREE_RIGHT;
                }
            } else {
                /* no subtrees; unwind up to parent */
                state = PTREE_UNWIND;
            }
            continue;
        case PTREE_RIGHT:
            if( ( ptreePTSFlags[ tree->op ] & PTS_BINARY )
              &&( tree->u.subtree[1] != NULL ) ) {
                /* has a right subtree; store current parent */
                temp = tree;
                tree = temp->u.subtree[1];
                temp->u.subtree[1] = parent;
                temp->flags &= ~PTF_TRAVERSE_LEFT;
                parent = temp;

                /* descend to right child node */
                state = PTREE_PROCESS;
            } else {
                /* no right subtree; unwind up to parent */
                state = PTREE_UNWIND;
            }
            continue;
        case PTREE_UNWIND:
            if( parent == NULL ) {
                break;
            }
            if( parent->flags & PTF_TRAVERSE_LEFT ) {
                parent->flags &= ~PTF_TRAVERSE_LEFT;
                /* set child pointer of parent to new node */
                temp = parent;
                parent = temp->u.subtree[0];
                temp->u.subtree[0] = tree;
                tree = temp;

                /* processed a left child; try for right hand child of parent */
                state = PTREE_RIGHT;
            } else {
                /* set child pointer of parent to new node */
                temp = parent;
                parent = temp->u.subtree[1];
                temp->u.subtree[1] = tree;
                tree = temp;

                /* processed a right child; unwind to parent */
                state = PTREE_UNWIND;
            }
            continue;
        }
        break;
    }
    return tree;
}

static TOKEN_LOCN *extract_locn;

static PTREE set_error_location( PTREE node )
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?