stmtno.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 371 行
C
371 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
//
// STMTNO : routines to handle all aspects of statement numbers
//
#include "ftnstd.h"
#include "errcod.h"
#include "ctrlflgs.h"
#include "global.h"
#include "intcnv.h"
#include "cpopt.h"
#include "ferror.h"
#include "insert.h"
extern label_id NextLabel(void);
extern void GStmtLabel(sym_id);
extern bool RecNumber(void);
extern sym_id STStmtNo(unsigned_32);
extern unsigned_32 GetStmtNum(sym_id);
extern int FmtS2I(char *,int,bool,intstar4 *,bool,int *);
// NOTE : These modules will check for errors and give any error
// messages relating to statement numbers.
// If you wish to have a label to branch to, use LkUpStmtNo().
// If you need the label of a format statement, use LkUpFormat().
//
// Explanation :
// The method used to detect branches into or between control
// structures is as follows:
// assigned a block number. the number is incremented every time,
// therefore each block has a unique number
// - when a statement number is first encountered the block number
// it occurred in (at head of CS list) is remembered on the
// statement number tree
// - if the definition occurs before the branch ( i.e. DefStmtNo is
// invoked before LkStmtNo ) the block the definition occurred in
// must still be unfinished ( i.e. be in the CS list ) when the
// branch is encountered
// - if the branch occurs before the definition the block number
// the definition occurs in must less than or equal to the block
// number where the branch occurred ( i.e. the current block had
// begun before the branch occurred )
//
intstar4 GetStmtNo( void ) {
//===========================
// Create statement number from operand field of CITNode must be before
// routines who call this routine since it returns unsigned_32.
intstar4 num;
if( RecNumber() ) {
if( ( FmtS2I( CITNode->opnd, CITNode->opnd_size, FALSE, &num, FALSE, NULL )
== INT_OK ) && ( num <= 99999 ) ) {
if( num == 0 ) {
Error( ST_NUM_ZERO );
}
} else {
Error( ST_NUM_TOO_BIG );
num = 0;
}
} else {
Error( ST_NO_STMTNO );
num = 0;
}
return( num );
}
sym_id LookUp( unsigned_32 num ) {
//=================================
sym_id sym_ptr;
sym_ptr = NULL;
if( num != 0 ) {
sym_ptr = STStmtNo( num );
if( ( sym_ptr->st.flags & SN_INIT_MASK ) == SN_INIT ) {
sym_ptr->st.line = SrcRecNum;
}
}
return( sym_ptr );
}
void Err( int errcod, sym_id sym_ptr ) {
//=========================================
Error( errcod, GetStmtNum( sym_ptr ), sym_ptr->st.line );
}
sym_id LkUpStmtNo( void ) {
//====================
// Return the branch label of a statement number.
sym_id sym_ptr;
unsigned_16 flags;
csnode *csptr;
sym_ptr = LookUp( GetStmtNo() );
if( sym_ptr != NULL ) {
sym_ptr->st.ref_count++;
flags = sym_ptr->st.flags;
if( GetStmtNum( sym_ptr ) == StmtNo ) {
Warning( ST_TO_SELF ); // this is only a warning
} // eg. 10 IF( FNX( Y ) )10,20,30
// will not necessarily be infinite
if( ( flags & SN_DEFINED ) != 0 ) {
if( ( flags & SN_BAD_BRANCH ) != 0 ) {
Err( ST_CANNOT_BRANCH, sym_ptr );
}
csptr = CSHead;
for(;;) {
if( sym_ptr->st.block == csptr->block ) break;
csptr = csptr->link;
if( csptr == NULL ) break;
}
if( csptr == NULL ) {
if( !(Options & OPT_WILD) ) {
Err( SP_INTO_STRUCTURE, sym_ptr );
}
}
if( StNumbers.in_remote && ( ( flags & SN_IN_REMOTE ) == 0 ) ) {
Err( SP_OUT_OF_BLOCK, sym_ptr );
}
} else {
if( ( sym_ptr->st.block > CSHead->block ) ||
( ( flags & SN_BRANCHED_TO ) == 0 ) ||
// Consider: DO 10 I==1,2
// GOTO 10
// DO 10 J==1,2
// 10 CONTINUE
// When we compile "GOTO 10", 10 is no longer only
// a DO terminal statement number.
( flags & SN_ONLY_DO_TERM ) ) {
sym_ptr->st.flags &= ~SN_ONLY_DO_TERM;
sym_ptr->st.block = CSHead->block;
sym_ptr->st.line = SrcRecNum;
}
if( StNumbers.in_remote ) {
sym_ptr->st.flags |= SN_IN_REMOTE;
}
}
sym_ptr->st.flags |= SN_BRANCHED_TO;
}
return( sym_ptr );
}
sym_id LkUpFormat( void ) {
//====================
// Return the label of a format statement number.
sym_id sym_ptr;
sym_ptr = LookUp( GetStmtNo() );
if( sym_ptr != NULL ) {
if( ( sym_ptr->st.flags & SN_DEFINED ) != 0 ) {
if( ( sym_ptr->st.flags & SN_FORMAT ) == 0 ) {
Err( ST_NOT_FORMAT, sym_ptr );
}
} else {
sym_ptr->st.flags |= ( SN_FORMAT | SN_BAD_BRANCH );
}
}
return( sym_ptr );
}
sym_id FmtPointer( void ) {
//====================
// Return the label of the current statement number.
sym_id sym_ptr;
sym_ptr = LookUp( StmtNo );
if( sym_ptr == NULL ) {
Warning( FM_NO_STMTNO );
}
return( sym_ptr );
}
sym_id LkUpAssign( void ) {
//====================
// Return label for ASSIGN 10 TO I.
sym_id sym_ptr;
sym_ptr = LookUp( GetStmtNo() );
if( sym_ptr != NULL ) {
sym_ptr->st.ref_count++;
sym_ptr->st.flags |= SN_ASSIGNED;
if( ( sym_ptr->st.flags & SN_DEFINED ) &&
( ( sym_ptr->st.flags & SN_FORMAT ) == 0 ) &&
( sym_ptr->st.flags & SN_BAD_BRANCH ) ) {
Err( GO_CANNOT_ASSIGN, sym_ptr );
sym_ptr->st.flags &= ~SN_ASSIGNED;
}
}
return( sym_ptr );
}
unsigned_32 LkUpDoTerm( void ) {
//============================
// Look up a statement numbers for a do terminator.
sym_id sym_ptr;
unsigned_16 flags;
unsigned_32 num;
num = GetStmtNo();
if( num != 0 ) {
sym_ptr = LookUp( num );
flags = sym_ptr->st.flags;
if( ( flags & SN_DEFINED ) != 0 ) {
Err( DO_BACKWARDS_DO, sym_ptr );
}
if( ( flags & SN_ONLY_DO_TERM ) != 0 ) {
sym_ptr->st.block = CSHead->block;
sym_ptr->st.line = SrcRecNum;
} else if( ( flags & (SN_INIT_MASK & ~SN_ASSIGNED) ) == SN_INIT ) {
// Assert: SN_ASSIGNED is only bit that might be set
// Consider: ASSIGN 10 to I
// DO 10
// 10 CONTINUE
// update the block number so we don't issue an SP_FROM_OUTSIDE
// in Update() when we compile the CONTINUE statement
if( flags & SN_ASSIGNED ) {
sym_ptr->st.block = CSHead->block;
}
sym_ptr->st.flags |= SN_ONLY_DO_TERM;
}
sym_ptr->st.flags |= SN_BRANCHED_TO;
}
return( num );
}
void DefStmtNo( unsigned_32 num ) {
//====================================
// Generate label for statement number.
sym_id sym_ptr;
sym_ptr = LookUp( num );
sym_ptr->st.ref_count++;
if( ( sym_ptr->st.flags & SN_DEFINED ) != 0 ) {
Err( ST_ALREADY, sym_ptr );
} else {
StNumbers.blk_before = CSHead->block;
if( Remember.transfer ) {
sym_ptr->st.flags |= SN_AFTR_BRANCH;
}
if( StmtProc == PR_FMT ) {
sym_ptr->st.flags |= SN_FORMAT;
} else if( !CtrlFlgOn( CF_BAD_BRANCH_OBJECT ) ) {
GStmtLabel( sym_ptr );
}
if( StNumbers.in_remote ) {
sym_ptr->st.flags |= SN_IN_REMOTE;
}
}
}
void Update( unsigned_32 num ) {
//=================================
// Update the statement number after compiling the statement.
sym_id sym;
unsigned_16 block;
sym = LookUp( num );
if( ( sym->st.flags & SN_DEFINED ) == 0 ) {
sym->st.flags |= SN_DEFINED;
block = StNumbers.blk_before; // allow branch to start of block
if( block > CSHead->block ) { // end of structure occurred
block = CSHead->block; // allow branch to end of block
}
if( ( sym->st.flags & SN_BRANCHED_TO ) != 0 ) {
if( sym->st.block < block ) {
if( !(Options & OPT_WILD) ) {
Err( SP_FROM_OUTSIDE, sym );
}
}
if( !StNumbers.in_remote &&
( ( sym->st.flags & SN_IN_REMOTE ) != 0 ) ) {
Err( SP_OUT_OF_BLOCK, sym );
}
}
sym->st.block = block;
}
if( CtrlFlgOn( CF_BAD_BRANCH_OBJECT ) ) {
sym->st.flags |= SN_BAD_BRANCH;
if( ( sym->st.flags & SN_BRANCHED_TO ) != 0 ) {
StmtIntErr( ST_BAD_BRANCHED, sym->st.line );
}
sym->st.flags &= ~SN_AFTR_BRANCH;
if( ( sym->st.flags & SN_ASSIGNED ) && ( StmtProc != PR_FMT ) ) {
StmtIntErr( GO_ASSIGNED_BAD, sym->st.line );
}
}
if( !CtrlFlgOn( CF_NOT_EXECUTABLE ) ) {
sym->st.flags |= SN_EXECUTABLE;
}
if( StmtProc != PR_FMT ) {
if( ( sym->st.flags & SN_FORMAT ) != 0 ) {
Err( ST_EXPECT_FORMAT, sym );
}
}
sym->st.line = SrcRecNum;
}
void InitStNumbers( void ) {
//=======================
// Intitialize statement number processing.
StNumbers.wild_goto = FALSE;
StNumbers.var_format = FALSE;
StNumbers.in_remote = FALSE;
StNumbers.branches = NextLabel();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?