cstmt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,481 行 · 第 1/3 页
C
1,481 行
sw->low_value = ~0l;
sw->high_value = 0;
sw->case_format = "%ld"; /* assume signed cases */
SwitchStack = sw;
switch_type = TYPE_INT; /* assume int */
tree = RValue( BracketExpr() );
typ = TypeOf( tree );
if( typ->decl_type == TYPE_ENUM ) typ = typ->object;
if( typ->decl_type == TYPE_UFIELD ) {
if( typ->u.f.field_width == (TARGET_INT * 8) ) {
sw->case_format = "%lu";
switch_type = TYPE_UINT;
}
}
switch( typ->decl_type ) {
case TYPE_USHORT:
case TYPE_UINT:
sw->case_format = "%lu";
switch_type = TYPE_UINT;
case TYPE_CHAR:
case TYPE_UCHAR:
case TYPE_SHORT:
case TYPE_INT:
case TYPE_FIELD:
case TYPE_UFIELD:
break;
case TYPE_ULONG:
sw->case_format = "%lu";
switch_type = TYPE_ULONG;
break;
case TYPE_LONG:
switch_type = TYPE_LONG;
break;
default:
CErr1( ERR_INVALID_TYPE_FOR_SWITCH );
}
tree = ExprNode( 0, OPR_SWITCH, tree );
tree->op.switch_info = sw;
AddStmt( tree );
}
static void EndSwitch( void )
{
SWITCHPTR sw;
// CASEPTR ce;
sw = SwitchStack;
SwitchStack = sw->prev_switch;
if( sw->default_label == 0 ) {
if( BlockStack->break_label == 0 ) {
sw->default_label = NextLabel();
DropLabel( sw->default_label );
} else {
sw->default_label = BlockStack->break_label;
}
}
// if( sw->case_list == NULL ) {
// CWarn1( WARN_EMPTY_SWITCH, ERR_EMPTY_SWITCH );
// }
#if 0
for( ; ce = sw->case_list; ) {
sw->case_list = ce->next_case;
CMemFree( ce );
}
CMemFree( sw );
#endif
}
static void EndOfStmt( void )
{
do {
switch( BlockStack->block_type ) {
case T_LEFT_BRACE:
EndBlock();
break;
case T_IF:
if( CurToken == T_ELSE ) {
ElseStmt();
return;
}
DropBreakLabel();
break;
case T_ELSE:
DropBreakLabel();
break;
case T_WHILE:
DropContinueLabel();
Jump( BlockStack->top_label );
--LoopDepth;
DropBreakLabel();
break;
case T_FOR:
EndForStmt();
--LoopDepth;
DropBreakLabel();
if( CompFlags.c99_extensions ) {
EndBlock(); /* Terminate the scope introduced by 'for' */
PopBlock();
}
break;
case T_DO:
DropContinueLabel();
MustRecog( T_WHILE );
SrcLineNum = TokenLine; /* 20-dec-88 */
SrcFno = TokenFno;
JumpTrue( BracketExpr(), BlockStack->top_label );
MustRecog( T_SEMI_COLON );
SrcLineNum = TokenLine;
SrcFno = TokenFno;
--LoopDepth;
DropBreakLabel();
break;
case T_SWITCH:
EndSwitch();
DropBreakLabel();
break;
#ifdef __SEH__
case T__TRY:
case T___TRY:
if( EndTry() )
return;
break;
case T__EXCEPT:
case T___EXCEPT:
DropBreakLabel();
TryScope = BlockStack->parent_index;
CompFlags.exception_handler = 0;
break;
case T__FINALLY:
case T___FINALLY:
AddStmt( LeafNode( OPR_END_FINALLY ) );
CompFlags.in_finally_block = 0;
TryScope = BlockStack->parent_index;
break;
#endif
}
PopBlock();
if( BlockStack == NULL ) break;
} while( BlockStack->block_type != T_LEFT_BRACE );
}
static bool IsDeclarator( TOKEN token )
{
SYM_HANDLE sym_handle;
SYM_ENTRY sym;
/* If token class is storage class or qualifier, it's a declaration */
if( TokenClass[ token ] == TC_STG_CLASS
|| TokenClass[ token ] == TC_QUALIFIER
|| TokenClass[ token ] == TC_DECLSPEC ) {
return( TRUE );
}
/* If token is one of the following, it's a declaration */
switch( token ) {
case T_VOID:
case T_CHAR:
case T_SHORT:
case T_INT:
case T_LONG:
case T_FLOAT:
case T_DOUBLE:
case T_SIGNED:
case T_UNSIGNED:
case T__COMPLEX:
case T__IMAGINARY:
case T__BOOL:
case T___INT64:
case T_STRUCT:
case T_UNION:
case T_ENUM:
return( TRUE );
default:
break;
}
/* If token is an ID, it might be a typedef */
if( (CurToken == T_ID) || (CurToken == T_SAVED_ID) ) {
if( CurToken == T_ID ) {
sym_handle = SymLookTypedef( HashValue, Buffer, &sym );
} else { /* T_SAVED_ID */
sym_handle = SymLookTypedef( SavedHash, SavedId, &sym );
}
if( sym_handle != 0 && sym.stg_class == SC_TYPEDEF ) {
return( TRUE );
}
}
return( FALSE );
}
static void FixupC99MainReturn( SYM_HANDLE func_result, struct return_info *info )
{
TREEPTR tree;
TYPEPTR main_type;
/* In C99 mode, return statement need not be explicit for main()... */
main_type = CurFunc->sym_type->object;
SKIP_TYPEDEFS( main_type );
/* ... as long as return type is compatible with int */
if( main_type->decl_type == TYPE_INT ) {
tree = IntLeaf( 0 ); /* zero is the default return value */
tree = ExprNode( 0, OPR_RETURN, tree );
tree->expr_type = main_type;
tree->op.sym_handle = func_result;
AddStmt( tree );
info->with_expr = TRUE;
}
}
void Statement( void )
{
LABEL_INDEX end_of_func_label;
SYM_HANDLE func_result;
TREEPTR tree;
bool return_at_outer_level;
bool skip_to_next_token;
bool declaration_allowed;
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;
return_at_outer_level = FALSE; /* 28-feb-92 */
declaration_allowed = FALSE;
DeadCode = 0;
LoopDepth = 0;
LabelIndex = 0;
BlockStack = NULL;
LoopStack = NULL;
SwitchStack = NULL;
#ifdef __SEH__
TryCount = -1;
TryScope = -1;
#endif
StartNewBlock();
NextToken(); // skip over {
++SymLevel;
tree = LeafNode( OPR_LABELCOUNT );
AddStmt( tree );
if( GrabLabels() == 0 ) { /* 29-nov-94 */
GetLocalVarDecls();
}
func_result = MakeNewSym( &sym, 'R', CurFunc->sym_type->object, SC_AUTO );
sym.flags |= SYM_FUNC_RETURN_VAR; /* 25-oct-91 */
SymReplace( &sym, func_result );
for( ;; ) {
CompFlags.pending_dead_code = 0;
if( GrabLabels() == 0 && declaration_allowed && IsDeclarator( CurToken ) ) {
GetLocalVarDecls();
}
if( CompFlags.c99_extensions ) {
declaration_allowed = TRUE;
}
skip_to_next_token = FALSE;
switch( CurToken ) {
case T_IF:
StartNewBlock();
NextToken();
BlockStack->break_label = NextLabel();
JumpFalse( BracketExpr(), BlockStack->break_label );
/* 23-dec-88, only issue msg if ';' is on same line as 'if' */
if( CurToken == T_SEMI_COLON && SrcLineNum == TokenLine ) {
SetErrLoc( ErrFName, TokenLine ); /* 04-nov-91 */
NextToken(); /* look ahead for else keyword */
if( CurToken != T_ELSE ) { /* 02-apr-91 */
ChkUseful(); /* 08-dec-88 */
}
SetErrLoc( NULL, 0 ); /* 04-nov-91 */
break;
}
declaration_allowed = FALSE;
continue;
case T_WHILE:
NewLoop();
NextToken();
BlockStack->break_label = NextLabel();
if( !JumpFalse( BracketExpr(), BlockStack->break_label ) ) {
BlockStack->break_label = 0; /* 09-sep-92 */
}
if( CurToken == T_SEMI_COLON ) { /* 08-dec-88 */
if( ! CompFlags.useful_side_effect ) {
CWarn1( WARN_MEANINGLESS, ERR_MEANINGLESS );
}
}
declaration_allowed = FALSE;
continue;
case T_DO:
NewLoop();
NextToken();
if( CurToken == T_RIGHT_BRACE ) {
CErr1( ERR_STMT_REQUIRED_AFTER_DO );
break;
}
declaration_allowed = FALSE;
continue;
case T_FOR:
ForStmt();
declaration_allowed = FALSE;
continue;
case T_SWITCH:
SwitchStmt();
DeadCode = 1;
declaration_allowed = FALSE;
continue;
case T_CASE:
DeadCode = 0;
CaseStmt();
declaration_allowed = FALSE;
continue;
case T_DEFAULT:
DefaultStmt();
declaration_allowed = FALSE;
continue;
case T_BREAK:
BreakStmt();
DeadCode = 1;
if( BlockStack->block_type != T_LEFT_BRACE ) break;
continue;
case T_CONTINUE:
ContinueStmt();
DeadCode = 1;
if( BlockStack->block_type != T_LEFT_BRACE ) break;
continue;
#ifdef __SEH__
case T__LEAVE:
case T___LEAVE:
LeaveStmt();
DeadCode = 1;
if( BlockStack->block_type != T_LEFT_BRACE ) break;
continue;
#endif
case T_RETURN:
ReturnStmt( func_result, &return_info );
if( BlockStack->prev_block == NULL ) { /* 28-feb-92 */
return_at_outer_level = TRUE;
}
MustRecog( T_SEMI_COLON );
if( SymLevel != 1 || CurToken != T_RIGHT_BRACE ||
BlockStack->block_type != T_LEFT_BRACE ) {
if( end_of_func_label == 0 ) {
end_of_func_label = NextLabel();
}
Jump( end_of_func_label );
}
if( BlockStack->block_type != T_LEFT_BRACE ) break;
continue;
case T_GOTO:
GotoStmt();
if( BlockStack->block_type != T_LEFT_BRACE ) break;
continue;
case T_SEMI_COLON:
NextToken();
if( BlockStack->block_type != T_LEFT_BRACE ) {
if( CurToken == T_ELSE ) {
declaration_allowed = FALSE;
}
break;
}
continue;
case T_LEFT_BRACE:
LeftBrace();
continue;
case T_RIGHT_BRACE:
if( BlockStack->block_type != T_LEFT_BRACE ) {
CErr1( ERR_MISPLACED_RIGHT_BRACE );
}
if( BlockStack->prev_block == NULL ) {
skip_to_next_token = TRUE;
} else {
NextToken();
}
break;
case T_EXTERN:
case T_STATIC:
case T_AUTO:
case T_REGISTER:
case T_VOID:
case T_CHAR:
case T_SHORT:
case T_INT:
case T_LONG:
case T_FLOAT:
case T_DOUBLE:
case T_SIGNED:
case T_UNSIGNED:
if( CompFlags.c99_extensions )
CErr1( ERR_UNEXPECTED_DECLARATION );
else
CErr1( ERR_MISSING_RIGHT_BRACE );
break;
case T_EOF:
CErr1( ERR_MISSING_RIGHT_BRACE );
break;
#ifdef __SEH__
case T__TRY:
case T___TRY:
TryStmt();
continue;
#endif
case T___ASM:
AsmStmt();
continue;
default:
if( DeadCode == 1 ) {
DeadMsg();
}
StmtExpr();
if( BlockStack->block_type != T_LEFT_BRACE ) break;
continue;
}
EndOfStmt();
if( BlockStack == NULL ) break;
if( skip_to_next_token ) {
NextToken();
}
}
/* C99 has special semantics for return value of main() */
if( CompFlags.c99_extensions && !strcmp( CurFunc->name, "main" ) ) {
if( !return_at_outer_level ) {
FixupC99MainReturn( func_result, &return_info );
return_at_outer_level = TRUE;
}
}
if( !return_info.with_expr ) { /* no return values present */
if( !CurFunc->naked ) {
ChkRetValue();
}
} else if( ! return_at_outer_level ) { /* 28-feb-92 */
if( ! DeadCode && !CurFunc->naked ) {
CWarn( WARN_MISSING_RETURN_VALUE,
ERR_MISSING_RETURN_VALUE, CurFunc->name );
}
}
if( end_of_func_label != 0 ) {
DropLabel( end_of_func_label );
}
DeadCode = 0;
tree->op.label_count = LabelIndex;
tree = LeafNode( OPR_FUNCEND );
if( !return_info.with_expr ) {
tree->expr_type = NULL;
tree->op.sym_handle = 0;
} else {
tree->op.sym_handle = func_result;
SetFuncReturnNode( tree );
}
AddStmt( tree );
AddSymList( CurFunc->u.func.locals );
SrcLineNum = TokenLine;
SrcFno = TokenFno;
FreeLabels();
if( skip_to_next_token ) {
NextToken();
}
if( CompFlags.generate_prototypes ) {
if( DefFile == NULL ) {
OpenDefFile();
}
if( DefFile != NULL && CurFunc->stg_class == SC_NULL ) {
/* function exported */
DumpFuncDefn();
}
}
if( Toggles & TOGGLE_INLINE ) {
if( Inline_Threshold < NodeCount ) {
CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE;
}
}
if( VarParm( CurFunc ) ) {
CurFuncNode->op.func.flags &= ~FUNC_OK_TO_INLINE;
}
NodeCount = 0;
if( CompFlags.addr_of_auto_taken ) { /* 23-oct-91 */
CurFunc->flags &= ~ SYM_OK_TO_RECURSE;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?