rstdump.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 450 行
C
450 行
/****************************************************************************
*
* 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: Resident symbol table dump module.
*
****************************************************************************/
#include "ftnstd.h"
#include "ecflags.h"
#include "errcod.h"
#include "undef.h"
#include "global.h"
#include "progsw.h"
#include "segsw.h"
#include "cpopt.h"
#include "iflookup.h"
#include "ferror.h"
#include "insert.h"
extern sym_id STFreeName(sym_id);
extern bool IsIFUsed(IFF);
extern sym_id AddSP2GList(sym_id);
extern sym_id AddCB2GList(sym_id);
extern unsigned_32 GetStmtNum(sym_id);
extern char *STGetName(sym_id,char *);
extern char *STNmListName(sym_id,char *);
extern sym_id STFree(sym_id);
extern void FreeSFHeader(sym_id);
extern void AllocGlobal(unsigned_32,bool);
extern bool ForceStatic(unsigned_16);
extern void CkSymDeclared( sym_id );
extern uint DataThreshold;
extern sym_id ReturnValue;
extern sym_id EPValue;
void STDump( void ) {
//================
// Dump symbol table.
sym_id sym;
// Merge IFList with NList
if( IFList != NULL ) {
sym = IFList;
while( sym->ns.link != NULL ) {
sym = sym->ns.link;
}
sym->ns.link = NList;
NList = IFList;
IFList = NULL;
}
if( !(ProgSw & PS_DONT_GENERATE) ) return;
ProgSw |= PS_SYMTAB_PROCESS;
DumpStmtNos(); // must be before DumpMagSyms()
DumpNameLists(); // dump the namelist data structures
DumpLocalVars();
DumpConsts();
DumpStrings(); // dump string data (must be last)
ProgSw &= ~PS_SYMTAB_PROCESS;
}
static bool CkInCommon( sym_id sym ) {
//========================================
// Check for variables in common.
sym_id leader;
com_eq *eq_ext;
unsigned_32 offset;
bool global_item;
global_item = FALSE;
if( sym->ns.flags & SY_IN_EQUIV ) {
offset = 0;
leader = sym;
for(;;) {
eq_ext = leader->ns.si.va.vi.ec_ext;
if( eq_ext->ec_flags & LEADER ) break;
offset += eq_ext->offset;
leader = eq_ext->link_eqv;
}
if( ( eq_ext->ec_flags & MEMBER_IN_COMMON ) == 0 ) {
if( !( eq_ext->ec_flags & EQUIV_SET_ALLOC ) ) {
if( ForceStatic(sym->ns.flags) || !(Options & OPT_AUTOMATIC) ) {
if( ( ProgSw & PS_BLOCK_DATA ) == 0 ) {
AllocGlobal( eq_ext->high - eq_ext->low,
(eq_ext->ec_flags & MEMBER_INITIALIZED) != 0 );
eq_ext->ec_flags |= EQUIV_SET_ALLOC;
}
}
}
}
}
return( global_item );
}
static bool DumpVariable( sym_id sym ) {
//==========================================
// Allocate space for the given variable.
unsigned_16 flags;
act_dim_list *dim_list;
bool global_item;
bool cp_reloc; // is array compile-time relocatable
global_item = FALSE;
flags = sym->ns.flags;
CkDataOk( sym );
if( !(flags & (SY_SUB_PARM | SY_DATA_INIT | SY_IN_EC)) ) {
if( (flags & SY_REFERENCED) && !(sym->ns.xflags & SY_DEFINED) ) {
NameWarn( VA_USED_NOT_DEFINED, sym );
}
}
if( ( flags & SY_IN_EQUIV ) &&
( sym->ns.si.va.vi.ec_ext->ec_flags & LEADER ) &&
( ( sym->ns.si.va.vi.ec_ext->ec_flags & ES_TYPE ) == ES_MIXED ) ) {
Extension( EV_MIXED_EQUIV );
}
if( flags & SY_SUBSCRIPTED ) {
dim_list = sym->ns.si.va.dim_ext;
cp_reloc = !( flags & SY_SUB_PARM ) && !_Allocatable( sym );
if( cp_reloc && ( dim_list->num_elts == 0 ) ) {
NameErr( SV_ARR_PARM, sym );
} else {
if( cp_reloc ) {
global_item = TRUE;
if( flags & SY_IN_EC ) {
global_item = CkInCommon( sym );
} else if( ( ProgSw & PS_BLOCK_DATA ) == 0 ) {
if( ForceStatic( flags ) || !(Options & OPT_AUTOMATIC) ) {
if( _SymSize( sym ) * _ArrElements( sym ) >
DataThreshold ) {
AllocGlobal( _SymSize( sym )*_ArrElements( sym ),
(flags & SY_DATA_INIT) != 0 );
}
}
}
}
}
} else if( sym->ns.typ == TY_STRUCTURE ) {
if( ( flags & SY_SUB_PARM ) == 0 ) {
if( (flags & SY_IN_DIMEXPR) && (flags & SY_IN_COMMON) == 0 ) {
NameErr( SV_ARR_DECL, sym );
} else {
global_item = TRUE;
if( flags & SY_IN_EC ) {
global_item = CkInCommon( sym );
} else if( ( ProgSw & PS_BLOCK_DATA ) == 0 ) {
if( ForceStatic( flags ) || !(Options & OPT_AUTOMATIC) ) {
if( sym->ns.xt.record->size > DataThreshold ) {
AllocGlobal( sym->ns.xt.record->size,
(flags & SY_DATA_INIT) != 0 );
}
}
}
}
}
} else if( sym->ns.typ == TY_CHAR ) {
if( ( flags & SY_SUB_PARM ) == 0 ) {
global_item = !_Allocatable( sym );
if( ( sym->ns.xt.size == 0 ) && !_Allocatable( sym ) ){
NameErr( CV_CHARSTAR_ILLEGAL, sym );
} else {
if( _Allocatable( sym ) ) {
Extension( VA_ALLOCATABLE_STORAGE, sym->ns.name );
}
if( flags & SY_IN_EC ) {
global_item = CkInCommon( sym );
} else if( ( ProgSw & PS_BLOCK_DATA ) == 0 ) {
if( ForceStatic( flags ) || !(Options & OPT_AUTOMATIC) ) {
AllocGlobal( sym->ns.xt.size,
(flags & SY_DATA_INIT) != 0 );
}
}
}
}
} else if( ( flags & ( SY_IN_EC | SY_SUB_PARM ) ) == 0 ) {
if( flags & SY_IN_DIMEXPR ) {
NameErr( SV_ARR_DECL, sym );
}
} else {
if( ( flags & SY_SUB_PARM ) == 0 ) {
global_item = CkInCommon( sym );
}
}
return( global_item );
}
static void DumpLocalVars( void ) {
//===============================
// Dump local variables.
unsigned_16 flags;
unsigned_16 class;
unsigned_16 subprog_type;
sym_id sym;
sym = NList;
while( sym != NULL ) {
flags = sym->ns.flags;
class = flags & SY_CLASS;
if( class == SY_VARIABLE ) {
if( (sym != ReturnValue) && (sym != EPValue) ) {
CkSymDeclared( sym );
if( (flags & (SY_REFERENCED | SY_IN_EC)) == 0 ) {
UnrefSym( sym );
}
DumpVariable( sym );
}
} else if( class == SY_SUBPROGRAM ) {
if( ( flags & ( SY_REFERENCED | SY_EXTERNAL ) ) == 0 ) {
UnrefSym( sym );
}
subprog_type = flags & SY_SUBPROG_TYPE;
if( subprog_type == SY_REMOTE_BLOCK ) {
if( ( flags & SY_RB_DEFINED ) == 0 ) {
NameErr( SP_RB_UNDEFINED, sym );
}
} else if( subprog_type == SY_STMT_FUNC ) {
} else if( subprog_type == SY_BLOCK_DATA ) {
AddSP2GList( sym );
} else if( !IsIntrinsic( flags ) ) {
AddSP2GList( sym );
} else if( IsIFUsed( sym->ns.si.fi.index ) ) {
AddSP2GList( sym );
}
} else { // if( class == SY_PARAMETER ) {
if( ( flags & SY_REFERENCED ) == 0 ) {
UnrefSym( sym );
}
}
sym = sym->ns.link;
}
// Common block list must be dumped after the name list so that the
// SY_COMMON_INIT bit gets set in the common block flags
// before we add the common block to the global list so that we can
// detect whether common blocks appear in more than one block data
// subprogram.
sym = BList;
while( sym != NULL ) { // common block list
if( ( SgmtSw & SG_BIG_SAVE ) || (Options & OPT_SAVE) ) {
sym->ns.flags |= SY_SAVED;
}
AddCB2GList( sym );
sym = STFreeName( sym );
}
BList = NULL;
// Free NList after processing it since we need to compute offsets
// of equivalenced names in the equivalence set
while( NList != NULL ) {
NList = STFreeName( NList );
}
}
static void UnrefSym( sym_id sym ) {
//======================================
// Issue a warning for unreferenced symbol.
if( !(sym->ns.xflags & SY_FAKE_REFERENCE) ) {
NameWarn( VA_UNREFERENCED, sym );
}
}
static void CkDataOk( sym_id sym ) {
//======================================
// Check that a data initialized variable in common is OK.
sym_id name;
com_eq *eq_ext;
unsigned_16 flags;
flags = sym->ns.flags;
if( ( flags & SY_DATA_INIT ) == 0 ) return;
name = sym;
if( flags & SY_IN_EC ) {
if( flags & SY_IN_COMMON ) {
sym = sym->ns.si.va.vi.ec_ext->com_blk;
} else { // if( flags & SY_IN_EQUIV ) {
for(;;) {
eq_ext = sym->ns.si.va.vi.ec_ext;
if( ( eq_ext->ec_flags & LEADER ) != 0 ) break;
sym = eq_ext->link_eqv;
}
if( ( eq_ext->ec_flags & MEMBER_IN_COMMON ) == 0 ) {
if( ProgSw & PS_BLOCK_DATA ) {
NameErr( BD_BLKDAT_NOT_COMMON, name );
}
return;
} else {
sym = eq_ext->com_blk;
}
}
if( ( sym->ns.flags & SY_BLANK_COMMON ) != 0 ) {
NameErr( DA_BLANK_INIT, name );
} else {
sym->ns.flags |= SY_COMMON_INIT;
if( ( ProgSw & PS_BLOCK_DATA ) == 0 ) {
NameExt( CM_COMMON, name );
}
}
} else {
if( ProgSw & PS_BLOCK_DATA ) {
NameErr( BD_BLKDAT_NOT_COMMON, name );
}
}
}
bool StmtNoRef( sym_id sn ) {
//==============================
// Check if statement number has been referenced.
if( StNumbers.wild_goto ) return( TRUE );
if( ( sn->st.flags & SN_AFTR_BRANCH ) == 0 ) return( TRUE );
if( sn->st.flags & ( SN_ASSIGNED | SN_BRANCHED_TO ) ) return( TRUE );
return( FALSE );
}
static void DumpStmtNos( void ) {
//=============================
// Check that statement numbers are all defined.
sym_id sn;
unsigned_16 sn_flags;
unsigned_32 st_number;
sn = SList;
while( sn != NULL ) {
sn_flags = sn->st.flags;
st_number = GetStmtNum( sn );
if( ( sn_flags & SN_DEFINED ) == 0 ) {
Error( ST_UNDEFINED, st_number, sn->st.line );
} else {
if( !StmtNoRef( sn ) ) {
Warning( ST_UNREFERENCED, st_number );
}
}
sn = STFree( sn );
}
SList = NULL;
}
static void DumpConsts( void ) {
//============================
// Dump constants from the symbol table.
while( CList != NULL ) {
CList = STFree( CList );
}
}
static void DumpStrings( void ) {
//=============================
// Dump constant literals and space for static temporaries.
while( LList != NULL ) {
LList = STFree( LList );
}
for( ; MList != NULL; MList = STFree( MList ) ) {
// check if shadow for function return value
if( MList->ns.flags & SY_PS_ENTRY ) continue;
if( MList->ns.typ == TY_CHAR ) {
if( ( MList->ns.xt.size != 0 ) && !( Options & OPT_AUTOMATIC ) ) {
AllocGlobal( MList->ns.xt.size, FALSE );
}
}
}
}
static void DumpNameLists( void ) {
//===============================
// Dump NAMELIST information.
char buff1[MAX_SYMLEN+1];
char buff2[MAX_SYMLEN+1];
sym_id nl;
grp_entry *ge;
sym_id sym;
unsigned_16 flags;
nl = NmList;
while( nl != NULL ) {
ge = nl->nl.group_list;
while( ge != NULL ) {
sym = ge->sym;
flags = sym->ns.flags;
// do error checks
if( ((flags & SY_CLASS) != SY_VARIABLE) || (flags & SY_SUB_PARM) ||
(sym->ns.typ == TY_STRUCTURE) || _Allocatable( sym ) ) {
STGetName( sym, buff1 );
STNmListName( nl, buff2 );
Error( VA_BAD_SYM_IN_NAMELIST, buff1, buff2 );
}
ge = ge->link;
}
nl = nl->nl.link;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?