cstmt.c

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

C
1,481
字号
    TREEPTR     tree;

/*
    <storage> <type> function( <parms> )
    {   <- this is SymLevel == 1
    (weird code is for SymLevel > 1 )
*/
    // DeclList might generate some quads to do some initializers
    // if that happens, we want them output after the OPR_NEWBLOCK node
    StartNewBlock();
    NextToken();
    ++SymLevel;
    tree = LeafNode( OPR_NEWBLOCK );
    AddStmt( tree );
    BlockStack->sym_list = 0;
    BlockStack->gen_endblock = TRUE;
    DeclList( &BlockStack->sym_list );
    tree->op.sym_handle = BlockStack->sym_list;
}


static void JumpBreak( BLOCKPTR block )
{
    if( !DeadCode ) {                           /* 05-apr-92 */
        if( block->break_label == 0 ) {
            block->break_label = NextLabel();
        }
        Jump( block->break_label );
    }
}


static void BreakStmt( void )
{
    BLOCKPTR    block;
    int         try_scope;

    NextToken();
    try_scope = -2;
    block = BlockStack;
    if( block != NULL ) {
        while( block != LoopStack ) {
            if( block->block_type == T_SWITCH )
                break;
            if( (block->block_type == T__TRY) || (block->block_type == T___TRY) ) {
                try_scope = block->parent_index;
            }
            block = block->prev_block;
        }
    }
    if( block != NULL ) {
        if( try_scope != -2 ) {
            UnWindTry( try_scope );
        }
        JumpBreak( block );
    } else {
        CErr1( ERR_MISPLACED_BREAK );
    }
    MustRecog( T_SEMI_COLON );
}


#ifdef __SEH__
static void LeaveStmt( void )
{
    BLOCKPTR    block;

    NextToken();
    block = BlockStack;
    while( block != NULL ) {
        if( (block->block_type == T__TRY) || (block->block_type == T___TRY) )
            break;
        block = block->prev_block;
    }
    if( block != NULL ) {
        JumpBreak( block );
    } else {
        CErr1( ERR_MISPLACED_LEAVE );
    }
    MustRecog( T_SEMI_COLON );
}
#endif


static void ContinueStmt( void )
{
    BLOCKPTR    block;
    int         try_scope;

    NextToken();
    if( LoopStack != NULL ) {
        if( ! DeadCode ) {                              /* 05-apr-92 */
            try_scope = -2;
            block = BlockStack;
            while( block != LoopStack ) {
                if( ( block->block_type == T__TRY )
                  || ( block->block_type == T___TRY ) ) {
                    try_scope = block->parent_index;
                }
                block = block->prev_block;
            }
            if( try_scope != -2 ) {
                UnWindTry( try_scope );
            }
            if( LoopStack->continue_label == 0 ) {
                LoopStack->continue_label = NextLabel();
            }
            Jump( LoopStack->continue_label );
        }
    } else {
        CErr1( ERR_MISPLACED_CONTINUE );
    }
    MustRecog( T_SEMI_COLON );
}


static void DefaultStmt( void )
{
    NextToken();
    MustRecog( T_COLON );
    if( SwitchStack ) {
        if( SwitchStack->default_label == 0 ) {
            SwitchStack->default_label = NextLabel();
            DropLabel( SwitchStack->default_label );
        } else {
            CErr1( ERR_ONLY_1_DEFAULT );
        }
        if( CurToken == T_RIGHT_BRACE ) {
            CErr1( ERR_STMT_REQUIRED_AFTER_DEFAULT );
        }
    } else {
        CErr1( ERR_MISPLACED_DEFAULT );
    }
}


static void ElseStmt( void )
{
    LABEL_INDEX if_label;

    SrcLineNum = TokenLine;             /* 18-jan-89 */
    SrcFno     = TokenFno;
    NextToken();
    BlockStack->block_type = T_ELSE;
    if_label = BlockStack->break_label;
    if( DeadCode ) {                            /* 05-apr-92 */
        BlockStack->break_label = 0;
    } else {
        BlockStack->break_label = NextLabel();
        Jump( BlockStack->break_label );
    }
    DropLabel( if_label );
}


static void GotoStmt( void )
{
    LABELPTR    label;

    NextToken();
    if( CurToken != T_ID ) {
        CErr1( ERR_EXPECTING_LABEL );
    } else {
        label = LkLabel( Buffer );
        label->referenced = 1;                          /* 05-apr-91 */
        Jump( label->ref_list );
    }
    NextToken();
    MustRecog( T_SEMI_COLON );
}


static void PushBlock( void )
{
    StartNewBlock();
    ++SymLevel;
    BlockStack->sym_list = 0;
}


static void NewLoop( void )
{
    StartNewBlock();
    LoopStack = BlockStack;
    LoopStack->top_label = NextLabel();
    DropLabel( LoopStack->top_label );
    ++LoopDepth;
}


static void ForStmt( void )
{
    bool    parsed_semi_colon = FALSE;

    NextToken();
    MustRecog( T_LEFT_PAREN );
    if( CompFlags.c99_extensions ) {
        PushBlock();    // 'for' opens new scope
    }
    if( CurToken != T_SEMI_COLON ) {
        if( CompFlags.c99_extensions ) {
            TREEPTR     tree;

            tree = LeafNode( OPR_NEWBLOCK );
            AddStmt( tree );
            BlockStack->gen_endblock = TRUE;
            if( !LoopDecl( &BlockStack->sym_list ) ) {
                ChkStmtExpr();      // no declarator, try init_expr
            } else {
                parsed_semi_colon = TRUE;   // LoopDecl ate it up
            }
            tree->op.sym_handle = BlockStack->sym_list;
        } else {
            ChkStmtExpr();          // init_expr
        }
    }
    if( !parsed_semi_colon ) {
        MustRecog( T_SEMI_COLON );
    }
    NewLoop();
    BlockStack->block_type = T_FOR;
    if( CurToken != T_SEMI_COLON ) {
        BlockStack->break_label = NextLabel();
        if( !JumpFalse( Expr(), BlockStack->break_label ) ) {
            BlockStack->break_label = 0;        /* 09-sep-92 */
        }
    }
    MustRecog( T_SEMI_COLON );
    BlockStack->inc_var = NULL;
    if( CurToken != T_RIGHT_PAREN ) {
        BlockStack->inc_var = Expr();                   // save this
        if( CompFlags.meaningless_stmt == 1 ) {
            ChkUseful();
        }
    }
    MustRecog( T_RIGHT_PAREN );
}


static void EndForStmt( void )
{
    DropContinueLabel();
    if( BlockStack->inc_var ) {
        AddStmt( BlockStack->inc_var );
    }
    Jump( BlockStack->top_label );
}


static void StmtExpr( void )
{
    ChkStmtExpr();
    switch( CurToken ) {
    case T_IF:
    case T_WHILE:
    case T_DO:
    case T_FOR:
    case T_SWITCH:
    case T_CASE:
    case T_DEFAULT:
    case T_BREAK:
    case T_CONTINUE:
    case T_RETURN:
    case T_GOTO:
    case T_LEFT_BRACE:
    case T_RIGHT_BRACE:
        Expecting( Tokens[ T_SEMI_COLON ] );
        break;
    default:
        Expecting( Tokens[ T_SEMI_COLON ] );
    case T_SEMI_COLON:
        NextToken();
        break;
    }
}


static void AddCaseLabel( unsigned long value )
{
    CASEPTR         ce, prev_ce, new_ce;
    unsigned long   old_value, converted_value;
    TREEPTR         tree;
    char            buffer[12];

    prev_ce = NULL;
#if 0
    leaf.u.ulong_konst = value;
    leaf.data_type = SwitchStack->case_type;
    SetLeafType( &leaf, 1 );
//      converted_value = value & SwitchStack->case_mask;
    converted_value = leaf.u.ulong_konst;
#else
    converted_value = value;
#endif
    old_value = converted_value + 1;  /* make old_value different */
    for( ce = SwitchStack->case_list; ce; ce = ce->next_case ) {
        old_value = ce->value;
        if( old_value >= converted_value ) break;
        prev_ce = ce;
    }
    if( converted_value == old_value ) {   /* duplicate case value found */
        sprintf( buffer, SwitchStack->case_format, value );
        CErr2p( ERR_DUPLICATE_CASE_VALUE, buffer );
    } else {
        new_ce = (CASEPTR)CMemAlloc( sizeof( CASEDEFN ) );
        new_ce->value = converted_value;
        new_ce->label = NextLabel();
        if( prev_ce == NULL ) {
            new_ce->next_case = SwitchStack->case_list;
            SwitchStack->case_list = new_ce;
        } else {
            prev_ce->next_case = new_ce;
            new_ce->next_case = ce;
        }
        SwitchStack->number_of_cases++;
        if( converted_value < SwitchStack->low_value ) {
            SwitchStack->low_value = converted_value;
        }
        if( converted_value > SwitchStack->high_value ) {
            SwitchStack->high_value = converted_value;
        }
        tree = LeafNode( OPR_CASE );
        tree->op.label_index = new_ce->label;
        AddStmt( tree );
    }
}


static void CaseStmt( void )
{
    const_val   val;

    NextToken();
    if( SwitchStack ) {
        if( ConstExprAndType( &val ) ) {
            if( ( val.type == TYPE_ULONG64 ) && !U64IsU32( val.value ) ) {
                CErr1( ERR_CONSTANT_TOO_BIG );
            } else if( ( val.type == TYPE_LONG64 ) && !I64IsI32( val.value ) ) {
                CErr1( ERR_CONSTANT_TOO_BIG );
            }
            AddCaseLabel( U32FetchTrunc( val.value) );
        }
        MustRecog( T_COLON );
        if( CurToken == T_RIGHT_BRACE ) {
            CErr1( ERR_STMT_REQUIRED_AFTER_CASE );
        }
    } else {
        CErr1( ERR_MISPLACED_CASE );
        ConstExprAndType( &val );        /* grab constant expression */
        MustRecog( T_COLON );
    }
}


#ifdef __SEH__
static void MarkTryVolatile( SYM_HANDLE sym_handle )
{
    SYM_ENTRY   sym;

    for( ;; ) {
        if( sym_handle == 0 ) break;
        SymGet( &sym, sym_handle );
        sym.flags |= SYM_TRY_VOLATILE; //force into memory
        SymReplace( &sym, sym_handle );
        sym_handle = sym.handle;
    }
}


static void TryStmt( void )
{
    TREEPTR     tree;

    MarkTryVolatile( CurFunc->u.func.parms );
    MarkTryVolatile( CurFunc->u.func.locals );
    CurFuncNode->op.func.flags |=  FUNC_USES_SEH;
    CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE;
    CurToken = T__TRY;
    StartNewBlock();
    NextToken();
    BlockStack->parent_index = TryScope;
    ++TryCount;
    BlockStack->try_index = TryCount;
    TryScope = TryCount;
    tree = LeafNode( OPR_TRY );
    tree->op.try_index = 0;
    tree->op.parent_scope = TryCount;
    AddStmt( tree );
}


static SYM_HANDLE DummyTrySymbol( void )
{
    SYM_ENTRY   sym;
    SYM_HANDLE  sym_handle;

    sym_handle = MakeNewSym( &sym, 'T', GetType( TYPE_VOID ), SC_STATIC );
    SymReplace( &sym, sym_handle );
    return( sym_handle );
}


static int EndTry( void )
{
    int         parent_scope;
    TREEPTR     expr;
    TREEPTR     func;
    TREEPTR     tree;
    TYPEPTR     typ;
    int         expr_type;

    DropBreakLabel();           /* _leave jumps to this label */
    parent_scope = BlockStack->parent_index;
    tree = LeafNode( OPR_TRY );
    tree->op.try_index = BlockStack->try_index;
    tree->op.parent_scope = parent_scope;
    AddStmt( tree );
    if( (CurToken == T__EXCEPT) || (CurToken == T___EXCEPT) ) {
        NextToken();
        BlockStack->block_type = T__EXCEPT;
        BlockStack->break_label = NextLabel();
        Jump( BlockStack->break_label );
        DeadCode = 0;
        tree = LeafNode( OPR_EXCEPT );
        tree->op.try_sym_handle = DummyTrySymbol();
        tree->op.parent_scope = parent_scope;
        AddStmt( tree );
        CompFlags.exception_filter_expr = 1;
        expr = RValue( BracketExpr() );
        CompFlags.exception_filter_expr = 0;
        CompFlags.exception_handler = 1;
        typ = TypeOf( expr );
        expr_type = DataTypeOf( typ );
        if( expr_type != TYPE_VOID ) {
            if( expr_type > TYPE_ULONG ) {
                CErr1( ERR_EXPR_MUST_BE_INTEGRAL );
            }
        }
        func = VarLeaf( SymGetPtr( SymExcept ), SymExcept );
        func->op.opr = OPR_FUNCNAME;
        expr = ExprNode( NULL, OPR_PARM, expr );
        expr->expr_type = typ;
        expr->op.result_type = typ;
        tree = ExprNode( func, OPR_CALL, expr );
        tree->expr_type = GetType( TYPE_VOID );
        AddStmt( tree );
        return( 1 );
    } else if( (CurToken == T__FINALLY) || (CurToken == T___FINALLY) ) {
        CompFlags.in_finally_block = 1;
        NextToken();
        BlockStack->block_type = T__FINALLY;
        DeadCode = 0;
        tree = LeafNode( OPR_FINALLY );
        tree->op.try_sym_handle = DummyTrySymbol();
        tree->op.parent_scope = parent_scope;
        AddStmt( tree );
        return( 1 );
    }
    return( 0 );
}
#endif


static void PopBlock( void )
{
    BLOCKPTR    block;
    TREEPTR     tree;

    if( BlockStack->gen_endblock ) {
        tree = LeafNode( OPR_ENDBLOCK );
        tree->op.sym_handle = BlockStack->sym_list;
        AddStmt( tree );
    }
    if( BlockStack->sym_list != 0 ) {
        AddSymList( BlockStack->sym_list );
    }
    block = BlockStack;
    LoopStack = block->prev_loop;
    BlockStack = block->prev_block;
    CMemFree( block );
}


static void SwitchStmt( void )
{
    SWITCHPTR   sw;
    TREEPTR     tree;
    TYPEPTR     typ;
    int         switch_type;

    StartNewBlock();
    NextToken();
    sw = (SWITCHPTR)CMemAlloc( sizeof( SWITCHDEFN ) );
    sw->prev_switch = SwitchStack;

⌨️ 快捷键说明

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