⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cstmt2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Convert C statements to expression trees.
*
****************************************************************************/


#include "cvars.h"

typedef struct block_entry {
    struct block_entry  *prev_block;
    struct block_entry  *prev_loop;
    int         block_type;
    int         top_label;
    int         break_label;
    int         continue_label;
    int         try_index;      /* TRY: current index */
    int         parent_index;   /* TRY: parent index */
    TREEPTR     inc_var;        /* variable used in FOR statement */
    SYM_HANDLE  sym_list;       /* symbols defined in this block */
} BLOCKDEFN, *BLOCKPTR;

// values for return_type
enum return_with {
    RETURN_WITH_NONE    = 0,
    RETURN_WITH_NO_EXPR = 1,
    RETURN_WITH_EXPR    = 2,
};

struct return_info {
    enum return_with    with;
    bool                with_expr;
};

extern int          NodeCount;
TREEPTR             CurFuncNode;
int                 LabelIndex;
SYM_LISTS           *SymListHeads;

static TREEPTR      LastStmt;
static BLOCKPTR     BlockStack;
static BLOCKPTR     LoopStack;
static SWITCHPTR    SwitchStack;

void ChkStmtExpr( void );
static void EndOfStmt( void );
static void LeftBrace( void );
static void BreakStmt( void );
static void LeaveStmt( void );
static void ContinueStmt( void );
static void DropBreakLabel( void );
static void DropContinueLabel( void );
static void DefaultStmt( void );
static void ElseStmt( void );
static void GotoStmt( void );
static void ForStmt( void );
static void EndForStmt( void );
static void StmtExpr( void );
static void ChkUseful( void );
static void CaseStmt( void );
static void TryStmt( void );
static int EndTry( void );
static void UnWindTry( int try_scope );
static void NewLoop( void );
static void startNewBlock( void );
static void PopBlock( void );
static void SwitchStmt( void );
static void EndSwitch( void );
static void JumpCond( TREEPTR expr, LABEL_INDEX label, int jump_opcode,
                      int jump_opposite );

void StmtInit( void ){
    FirstStmt = NULL;
    LastStmt = NULL;
    SymListHeads = NULL;
}

void ChkStringLeaf( TREEPTR leaf )
{
    if( leaf->op.opr == OPR_PUSHSTRING ) {
        leaf->op.string_handle->ref_count++;
    }
}

SYM_HANDLE GetBlockSymList( void )
{
    return( BlockStack->sym_list );
}

void InitStmt( void )
{
    BlockStack  = NULL;
    LoopStack   = NULL;
    SwitchStack = NULL;
}

void SwitchPurge()
{
    SWITCHPTR   sw;
    CASEPTR     c_entry, c_tmp;

    while( (sw = SwitchStack) ) {
        SwitchStack = sw->prev_switch;
        c_entry = sw->case_list;
        while( c_entry != NULL ) {
            c_tmp = c_entry->next_case;
            CMemFree( c_entry );
            c_entry = c_tmp;
        }
        CMemFree( sw );
    }
}

void AddStmt( TREEPTR stmt )
{
    WalkExprTree( stmt, ChkStringLeaf, NoOp, NoOp, DoConstFold );
    stmt = ExprNode( 0, OPR_STMT, stmt );
    stmt->op.source_fno = SrcFno;
    stmt->srclinenum = SrcLineNum;
    stmt->op.unroll_count = UnrollCount;
    if( FirstStmt == NULL )  FirstStmt = stmt;
    if( LastStmt != NULL ) {
        LastStmt->left = stmt;
    }
    LastStmt = stmt;
}

void AddSymList( SYM_HANDLE sym_handle )
{
    SYM_LISTS   *symlist;

    symlist = (SYM_LISTS *)CMemAlloc( sizeof(SYM_LISTS) );
    symlist->next = SymListHeads;
    symlist->sym_head = sym_handle;
    SymListHeads = symlist;
}

void GenFunctionNode( SYM_HANDLE sym_handle )
{
    TREEPTR     tree;
    SYMPTR      sym;

    tree = LeafNode( OPR_FUNCTION );
    sym = SymGetPtr( sym_handle );
    tree->op.func.sym_handle = sym_handle;
    tree->op.func.flags = FUNC_NONE;
    if( ( Toggles & TOGGLE_INLINE ) | ( sym->attrib & FLAG_INLINE ) ){
        if( !sym->naked ){
            if( strcmp( sym->name, "main" ) != 0 ) {
                tree->op.func.flags |= FUNC_OK_TO_INLINE;
            }
        }
    }
    tree->op.flags = OpFlags( sym->attrib );
    tree->expr_type = sym->sym_type->object;    // function return type
    AddStmt( tree );
    // Evil, evil globals! But we need this for later lookups in cgen2.c
    sym->u.func.start_of_func = LastStmt;
    CurFuncNode = tree;
    NodeCount = 0;
}

int NextLabel()
{
    return( ++LabelIndex );
}

static void DropLabel( LABEL_INDEX label )
{
    TREEPTR     tree;

    CompFlags.label_dropped = 1;
    DeadCode = 0;
    tree = LeafNode( OPR_LABEL );
    tree->op.label_index = label;
    AddStmt( tree );
}

static TREEPTR BracketExpr()
{
    TREEPTR     tree;

    MustRecog( T_LEFT_PAREN );
    tree = Expr();
    FoldExprTree( tree );
    MustRecog( T_RIGHT_PAREN );
    return( tree );
}


static void Jump( LABEL_INDEX label )
{
    TREEPTR     tree;

    if( ! DeadCode ) {
        tree = LeafNode( OPR_JUMP );
        tree->op.label_index = label;
        AddStmt( tree );
        DeadCode = 1;
    }
}


static int JumpFalse( TREEPTR expr, LABEL_INDEX label )
{
    int         jump_generated;

    jump_generated = 0;
    if( expr->op.opr == OPR_PUSHINT ) {
        if( ! expr->op.long_value ) {
            Jump( label );
            jump_generated = 1;
        }
        FreeExprNode( expr );
    } else {
        JumpCond( expr, label, OPR_JUMPFALSE, OPR_JUMPTRUE );
        jump_generated = 1;
    }
    return( jump_generated );
}


static void JumpTrue( TREEPTR expr, LABEL_INDEX label )
{
    if( expr->op.opr == OPR_PUSHINT ) {
        if( expr->op.long_value ) {
            Jump( label );
        }
        FreeExprNode( expr );
    } else {
        JumpCond( expr, label, OPR_JUMPTRUE, OPR_JUMPFALSE );
    }
}


static void JumpCond( TREEPTR expr,
                     LABEL_INDEX label,
                     int jump_opcode,
                     int jump_opposite )
{
    TREEPTR     tree;

    tree = BoolExpr( expr );
    if( tree->op.opr == OPR_NOT ) {
        tree->op.opr = jump_opposite;
    } else {
        tree = ExprNode( 0, jump_opcode, tree );
    }
    tree->op.label_index = label;
    AddStmt( tree );
}


void LookAhead( void )
{
    SavedId = CStrSave( Buffer );        /* save current id */
    SavedHash = HashValue;              /* and its hash value */
    SavedTokenLine = TokenLine;         /* save linenum and fno 09-jul-95 */
    SavedTokenFno  = TokenFno;
    NextToken();                        /* get next token */
    LAToken = CurToken;                 /* save it in look ahead */
    CurToken = T_SAVED_ID;              /* go back to saved id */
}


static int GrabLabels()
{
    LABELPTR    label;

    label = NULL;
    for(;;) {
        if( CurToken == T_SAVED_ID ) {          /* 09-jul-95 */
            SrcLineNum = SavedTokenLine;
            SrcFno     = SavedTokenFno;
        } else {
            SrcLineNum = TokenLine;
            SrcFno     = TokenFno;
            if( CurToken != T_ID ) break;
            LookAhead();
        }
        if( LAToken != T_COLON ) break; /* quit if look ahead not : */
        label = LkLabel( SavedId );
        if( label->defined != 0 ) {
            CErr2p( ERR_LABEL_ALREADY_DEFINED, label->name );
        } else {
            DropLabel( label->ref_list );
            label->defined = 1;         /* indicate label defined now */
        }
        CMemFree( SavedId );            /* free the saved id */
        SavedId = NULL;
        NextToken();                    /* get next token */
    }
    if( label != NULL ) {                       /* label was found */
        if( CurToken == T_RIGHT_BRACE ) {
            CErr1( ERR_STMT_REQUIRED_AFTER_LABEL );
        }
        return( 1 );                    // indicate label found
    }
    return( 0 );
}


static void ReturnStmt( SYM_HANDLE func_result, struct return_info *info )
{
    TREEPTR     tree;
    BLOCKPTR    block;
    enum  return_with with;

    NextToken();
    if( CurToken != T_SEMI_COLON ) {
        tree = RValue( Expr() );
        ChkRetType( tree );
        tree = ExprNode( 0, OPR_RETURN, tree );
        tree->expr_type = CurFunc->sym_type->object;
        tree->op.sym_handle = func_result;
        AddStmt( tree );
        with = RETURN_WITH_EXPR;
        info->with_expr = TRUE;
    } else {
        with = RETURN_WITH_NO_EXPR;
    }
    if( info->with == RETURN_WITH_NONE ) {
        info->with = with;
    }
    if( info->with != with ) {
        CErr1( ERR_INCONSISTENT_USE_OF_RETURN );
    }
    block = BlockStack;                                 /* 16-apr-94 */
    while( block != NULL ) {
        if( block->block_type == T__TRY ) break;
        block = block->prev_block;
    }
    if( block != NULL ) {
        UnWindTry( -1 );
    }
}

static void SetFuncReturnNode( TREEPTR tree )
{
    TYPEPTR     typ;

    typ = CurFunc->sym_type->object;
    tree->expr_type = typ;
    while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
    if( typ->decl_type == TYPE_STRUCT || typ->decl_type == TYPE_UNION ) {
        tree->right = LeafNode( OPR_NOP );      // place holder
        tree->right->expr_type = NULL;
    }
}

static void ChkRetValue()
{
    TYPEPTR     typ;

    typ = CurFunc->sym_type;
    typ = typ->object;
    while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
    if( typ->decl_type != TYPE_VOID ) {
        CWarn( WARN_MISSING_RETURN_VALUE,
                ERR_MISSING_RETURN_VALUE, CurFunc->name );
    }
}

void GetLocalVarDecls()
{
    SYM_HANDLE  symlist;
    SYM_HANDLE  symhandle;
    SYM_ENTRY   sym;

    DeclList( &symlist );
    if( symlist != 0 ) {
        symhandle = CurFunc->u.func.locals;
        // symhandle will be non-zero if MakeNewSym was called while
        // parsing the declaration list.
        if( symhandle != 0 ) {          // if some temporaries were created
            for(;;) {                   // - find end of list
                SymGet( &sym, symhandle );
                if( sym.handle == 0 ) break;
                symhandle = sym.handle;
            }
            sym.handle = symlist;
            SymReplace( &sym, symhandle );
        } else {
            CurFunc->u.func.locals = symlist;
        }
    }
}

static void DeadMsg( void ){
/***************************/
    CWarn1( WARN_DEAD_CODE, ERR_DEAD_CODE );
    DeadCode = 2;   /* so we don't get more messages */
}

void Statement( void )
{
    LABEL_INDEX        end_of_func_label;
    SYM_HANDLE         func_result;
    TREEPTR            tree;
    char               return_at_outer_level;
    char               skip_to_next_token;
    struct return_info return_info;
    SYM_ENTRY sym;

#ifndef NDEBUG
    if( DebugFlag >= 1 ) {
        printf( "***** line %d, func=%s\n", TokenLine, CurFunc->name );
        PrintStats();
    }
#endif
    ++FuncCount;
    return_info.with = RETURN_WITH_NONE; /* indicate no return statements */
    return_info.with_expr = FALSE;
    CompFlags.label_dropped = 0;
    CompFlags.addr_of_auto_taken = 0;           /* 23-oct-91 */
    end_of_func_label = 0;

⌨️ 快捷键说明

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