static void ChkParms( void ) { PARMPTR parm; PARMPTR prev_parm; SYM_HANDLE sym_handle; SYM_HANDLE prev_sym_handle; TYPEPTR typ; CurFunc->u.func.locals = SYM_NULL; CurFunc->u.func.parms = SYM_NULL; typ = *(CurFunc->sym_type->u.fn.parms); SKIP_TYPEDEFS( typ ); if( typ->decl_type != TYPE_VOID ) { prev_sym_handle = SYM_NULL; prev_parm = NULL; for( parm = ParmList; parm != NULL; parm = parm->next_parm ) { if( parm->sym.name == NULL ) { parm->sym.name = ".J"; parm->sym.flags |= SYM_REFERENCED; } if( parm->sym.name[0] == '\0' ) { parm->sym.name = ".I"; InvDecl(); } if( parm->sym.sym_type == NULL ) { parm->sym.sym_type = TypeDefault(); } /* make sure name not already defined in this SymLevel */ sym_handle = SymAdd( parm->sym.info.hash, &parm->sym ); if( prev_parm == NULL ) { CurFunc->u.func.parms = sym_handle; } else { prev_parm->sym.handle = sym_handle; SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } prev_parm = parm; prev_sym_handle = sym_handle; parm->sym.flags |= SYM_DEFINED | SYM_ASSIGNED; parm->sym.attribs.is_parm = true; } if( prev_parm != NULL ) { #if _CPU == 370 { SYM_ENTRY var_parm; if( VarParm( CurFunc ) ) { typ = ArrayNode( GetType( TYPE_CHAR ) ); typ->u.array->dimension = 160; sym_handle = GetNewSym( &var_parm, 'V', typ, SC_AUTO ); SymReplace( &var_parm, sym_handle ); prev_parm->sym.handle = sym_handle; } } #endif SymReplace( &prev_parm->sym, prev_sym_handle ); CMemFree( prev_parm ); } } }
/* // does the specified symbol take variable args? hash calc'ed // */ bool VarFunc( SYMPTR sym ) { unsigned hash; size_t len; char *p; if( sym == NULL ) return( FALSE ); if( sym->flags & SYM_FUNCTION ) { p = sym->name; len = strlen( p ); hash = (len + VarFuncWeights[p[0] - 'a'] + VarFuncWeights[p[len - 1] -'a']) & 31; if( memcmp( p, VarParmFuncs[hash], len + 1 ) == 0 && ( CompFlags.extensions_enabled || ( ( 1 << hash ) & VAR_PARM_FUNCS_ANSI ) ) ) return( TRUE ); return( VarParm( sym ) ); } return( FALSE ); }
/* // does the specified symbol take variable args? hash calc'ed // */ int VarFunc( SYMPTR sym ) { int hash; int len; char *p; if( sym == NULL ) return( 0 ); if( sym->flags & SYM_FUNCTION ) { p = sym->name; len = strlen( p ); hash = (len + VarFuncWeights[ p[0] - 'a' ] + VarFuncWeights[ p[len-1] -'a' ]) & 31; if( strcmp( p, VarParmFuncs[ hash ] ) == 0 && ( CompFlags.extensions_enabled || ( ( 1 << hash ) & VAR_PARM_FUNCS_ANSI ) ) ) return( 1 ); return( VarParm( sym ) ); } return( 0 ); }
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 %u, func=%s\n", TokenLoc.line, 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 && SrcLoc.line == TokenLoc.line && SrcLoc.fno == TokenLoc.fno ) { SetErrLoc( &TokenLoc ); NextToken(); /* look ahead for else keyword */ if( CurToken != T_ELSE ) { /* 02-apr-91 */ ChkUseful(); /* 08-dec-88 */ } InitErrLoc(); 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( !DeadCode && !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 ); SrcLoc = TokenLoc; 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; } }
static void ParmDeclList( void ) /* process old style function definitions */ { TYPEPTR typ; PARMPTR parm; decl_state state; SYM_ENTRY sym; decl_info info; size_t len; while( CurToken != T_LEFT_BRACE ) { FullDeclSpecifier( &info ); if( info.stg == SC_NONE && info.typ == NULL ) { if( CurToken == T_ID ) { CErr2p( ERR_MISSING_DATA_TYPE, Buffer ); } } if( info.stg != SC_NONE && info.stg != SC_REGISTER ) { CErr1( ERR_INVALID_STG_CLASS_FOR_PARM ); info.stg = SC_NONE; } state = DECL_STATE_NONE; typ = info.typ; if( typ == NULL ) { state |= DECL_STATE_NOTYPE; typ = TypeDefault(); } if( info.stg == SC_NONE ) info.stg = SC_AUTO; for( ;; ) { if( CurToken == T_SEMI_COLON ) { Chk_Struct_Union_Enum( typ ); } else { sym.name = NULL; Declarator( &sym, info.mod, typ, state ); if( sym.name == NULL || sym.name[0] == '\0' ) { InvDecl(); } else { len = strlen( sym.name ) + 1; for( parm = ParmList; parm != NULL; parm = parm->next_parm ) { if( parm->sym.name != NULL ) { if( memcmp( parm->sym.name, sym.name, len ) == 0 ) { break; } } } if( parm == NULL ) { CErr2p( ERR_SYM_NOT_IN_PARM_LIST, sym.name ); } else if( parm->sym.sym_type != NULL ) { CErr2p( ERR_PARM_ALREADY_DECLARED, sym.name ); } else { ArgPromotion( &sym ); parm->sym.sym_type = sym.sym_type; parm->sym.attribs.stg_class = info.stg; } } CMemFree( sym.name ); } if( CurToken == T_SEMI_COLON ) { NextToken(); break; } if( CurToken == T_LEFT_BRACE ) { CErr1( ERR_MISSING_SEMICOLON ); break; } if( CurToken == T_EOF ) return; MustRecog( T_COMMA ); } } ReverseParms(); if( CurFunc->sym_type->u.fn.parms == NULL ) { CurFunc->flags |= SYM_OLD_STYLE_FUNC; AddParms(); } else { ChkParms(); } ParmList = NULL; if( VarParm( CurFunc ) ) { CurFunc->flags &= ~ SYM_OK_TO_RECURSE; } }