brinfo.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,329 行 · 第 1/3 页
C
1,329 行
/****************************************************************************
*
* 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: Browsing information generation routines.
*
****************************************************************************/
#include "plusplus.h"
#include <stdio.h>
#include <errno.h>
#ifdef OPT_BR
#include "preproc.h"
#include "memmgr.h"
#include "errdefns.h"
#include "srcfile.h"
#include "iosupp.h"
#include "initdefs.h"
#include "brinfoim.h"
#include "ring.h"
#include "stats.h"
#include "icodes.h"
#include "pstk.h"
#include "pcheader.h"
#include "fname.h"
#if defined(__UNIX__)
#include <unistd.h>
#else
#include <direct.h>
#endif
#ifndef NDEBUG
#include "dbg.h"
#include "pragdefn.h"
#endif
#ifdef XTRA_RPT
ExtraRptCtr( ctr_namespace_decl );
ExtraRptCtr( ctr_symbol_decl );
ExtraRptCtr( ctr_template_class_decl );
ExtraRptCtr( ctr_typedef );
ExtraRptCtr( ctr_class_decl );
ExtraRptCtr( ctr_class_base );
ExtraRptCtr( ctr_class_memb );
ExtraRptCtr( ctr_class_fr );
ExtraRptCtr( ctr_defn_macro );
ExtraRptCtr( ctr_ref_func );
ExtraRptCtr( ctr_ref_data_memb_this );
ExtraRptCtr( ctr_ref_data_memb_static );
ExtraRptCtr( ctr_ref_data_bare_auto );
ExtraRptCtr( ctr_ref_data_bare_static );
ExtraRptCtr( ctr_ref_typedef );
ExtraRptCtr( ctr_ref_eval );
ExtraRptCtr( ctr_ref_evar );
ExtraRptCtr( ctr_ref_other );
ExtraRptCtr( ctr_ref_macro );
ExtraRptCtr( ctr_dep_macro_defined );
ExtraRptCtr( ctr_dep_macro_value );
ExtraRptCtr( ctr_nontrivial_scopes );
ExtraRptCtr( ctr_open_scope );
ExtraRptCtr( ctr_open_source );
#endif
typedef enum // BRINFO STATES:
{ BRS_INACTIVE // - inactive
, BRS_CMDLINE // - command line being processed
, BRS_COLLECTING // - collecting into CGIO file
, BRS_COLLECTED // - collected into CGIO file
, BRS_WRITING // - writing browse file
, BRS_PCH_RESTART // - restarting during PCH read
} BRS;
typedef struct ACTBLK ACTBLK;
typedef struct SCPINS SCPINS;
struct SCPINS // SCPINS -- scope instruction
{ SCPINS* next; // - next in ring
CGFILE_INS scope_ins; // - scope instruction
};
struct ACTBLK // ACTBLK -- active block scope
{ ACTBLK* next; // - next in ring
SCOPE scope; // - the scope
SCPINS* ins; // - ring of instruction addresses
};
static FILE* usage_file; // control for usage file
static char* usage_name; // name of usage file
static CGFILE* virtual_file; // virtual file for intermediate codes
static BRS brinfo_state; // state for processing
static SRCFILE ref_file; // reference file
static LINE_NO ref_line; // reference line
static COLUMN_NO ref_col; // reference column
static PSTK_CTL active_scopes; // active scopes
static PSTK_CTL sym_scopes; // active scopes for a definition
static carve_t carve_blk_scope; // carver: active block scopes
static carve_t carve_scope_ins; // carver: scope instructions
static ACTBLK* ring_active_blks;// ring of active block scopes
static boolean enableMacRefs; // TRUE ==> macro references to be processed
static BRI_Handle* bri_handle; // handle for browse-file writer
#define canWriteIc() \
brinfo_state == BRS_COLLECTING
static char* brinfPchGetBuffer // GET BUFFER FOR READ
( BRI_PCH_CTL* ctl // - control
, unsigned size ) // - size required
{
if( size > ctl->bsize ) {
CMemFreePtr( &ctl->buffer );
ctl->buffer = CMemAlloc( ( size + 1024 - 1 ) & -1024 );
}
return ctl->buffer;
}
static BRI_PCH_CTL* brinfPchInit // INITIALIZATION OF CONTROL INFO
( BRI_PCH_CTL* ctl ) // - control
{
ctl->bsize = 0;
ctl->buffer = 0;
brinfPchGetBuffer( ctl, 8 * 1024 );
return ctl;
}
static BRI_PCH_CTL* brinfPchFini // COMPLETION OF CONTROL INFO
( BRI_PCH_CTL* ctl ) // - control
{
CMemFreePtr( &ctl->buffer );
return ctl;
}
static uint_8 brinfReadPch1 // READ ONE BYTE FROM PCH
( BRI_PCH_CTL * ctl ) // - control
{
PCHReadUnaligned( ctl->buffer, 1 );
return *ctl->buffer;
}
static uint_32 brinfReadPch4 // READ FOUR BYTES FROM PCH
( BRI_PCH_CTL * ctl ) // - control
{
ctl = ctl;
return PCHReadUIntUnaligned();
}
static void* brinfReadPch // READ SUPPLIED # OF BYTES
( BRI_PCH_CTL * ctl // - control
, unsigned size ) // - size required
{
return PCHReadLocateUnaligned( brinfPchGetBuffer( ctl, size ), size );
}
static void brinfWriteIns // WRITE AN INSTRUCTION
( CGINTER* ins ) // - instruction
{
DbgVerify( NULL != virtual_file, "Attempt write to unopened file" );
CgioWriteIC( virtual_file, ins );
}
void BrinfWriteIns // WRITE IC, PTR OPERAND
( CGINTEROP opcode // - opcode
, void const *ptr ) // - operand
{
CGINTER ins; // - IC instruction
ins.opcode = opcode;
ins.value.pvalue = (void*)ptr;
brinfWriteIns( &ins );
}
static void brinfIcPtr // WRITE IC, PTR OPERAND
( CGINTEROP opcode // - opcode
, void const *ptr ) // - operand
{
if( canWriteIc() ) {
BrinfWriteIns( opcode, ptr );
}
}
static void brinfIcBin // WRITE IC, BINARY OPERAND
( CGINTEROP opcode // - opcode
, unsigned bin ) // - operand
{
if( canWriteIc() ) {
CGINTER ins; // - IC instruction
ins.opcode = opcode;
ins.value.uvalue = bin;
brinfWriteIns( &ins );
}
}
#if 0
static void brinfIc // WRITE IC, NO OPERAND
( CGINTEROP opcode ) // - opcode
{
brinfIcBin( opcode, 0 );
}
#endif
static ACTBLK* findActiveScope // FIND ACTIVE SCOPE ENTRY
( SCOPE scope ) // - the scope
{
ACTBLK* retn; // - entry for scope
ACTBLK* curr; // - search entry
retn = NULL;
RingIterBeg( ring_active_blks, curr ) {
if( scope == curr->scope ) {
retn = curr;
break;
}
} RingIterEnd( curr );
return retn;
}
static void recordBlkScopeIns // RECORD A BLK-SCOPE INSTRUCTION
( SCOPE scope ) // - scope for instruction
{
if( canWriteIc() ) {
SCPINS* ins;
ACTBLK* act = findActiveScope( scope );
if( NULL == act ) {
act = RingCarveAlloc( carve_blk_scope, &ring_active_blks );
act->scope = scope;
act->ins = NULL;
}
ins = RingCarveAlloc( carve_scope_ins, &act->ins );
ins->scope_ins = CgioLastWrite( virtual_file );
}
}
#ifndef NDEBUG
void _dbgScope
( SCOPE scope
, char const * text )
{
IfDbgToggle( browse ) {
switch( scope->id ) {
case SCOPE_FILE :
printf( "%s: File Scope %x\n", text, scope );
break;
case SCOPE_CLASS :
printf( "%s: Class Scope: %x", text, scope );
PrintFullType( scope->owner.type );
break;
case SCOPE_FUNCTION :
printf( "%s: Function Scope: %x %s\n"
, text
, scope
, DbgSymNameFull( scope->owner.sym ) );
break;
case SCOPE_BLOCK :
printf( "%s: Block Scope: %x %d\n"
, text
, scope
, scope->owner.index );
break;
case SCOPE_TEMPLATE_DECL :
printf( "%s: Template Declaration Scope %x\n", text, scope );
break;
case SCOPE_TEMPLATE_INST :
printf( "%s: Template Instantiation Scope %x\n", text, scope );
break;
case SCOPE_TEMPLATE_PARM :
printf( "%s: Template Parameters Scope %x\n", text, scope );
break;
}
}
}
#else
#define _dbgScope(a,b)
#endif
static void closeScopeIc // INTERMEDIATE CODE TO CLOSE A SCOPE
( SCOPE scope ) // - scope for instruction
{
_dbgScope( scope, "Br-inf-cls" );
brinfIcPtr( IC_BR_SCOPE_CLS, scope );
recordBlkScopeIns( scope );
}
static CGINTER nop_ins = { 0, IC_BR_NO_OP };
static void endBlkScope // END OF BLK SCOPE
( SCOPE scope ) // - scope being closed
{
if( canWriteIc() ) {
ACTBLK* act = findActiveScope( scope );
if( NULL != act ) {
if( ! scope->keep ) {
SCPINS* curr;
RingIterBeg( act->ins, curr ) {
CgioBuffZap( curr->scope_ins, &nop_ins );
} RingIterEnd( curr );
}
RingCarveFree( carve_scope_ins, &act->ins );
RingPrune( &ring_active_blks, act );
CarveFree( carve_blk_scope, act );
}
}
}
static TOKEN_LOCN const* adjustLocn // ADJUST FOR UNSPECIFIED LOCATION
( TOKEN_LOCN const* locn // - the location
, TOKEN_LOCN* temporary ) // - a TOKEN_LOCN temporary
{
temporary = temporary;
if( NULL != locn ) {
SRCFILE sf = locn->src_file;
if( NULL == sf
|| IsSrcFileCmdLine( sf ) ) {
locn = NULL;
}
}
return locn;
}
static void adjustSrcFile // ADJUST OPEN/CLOSE OF SOURCE FILE(S)
( TOKEN_LOCN const * locn ) // - location for reference/declaration
{
TOKEN_LOCN curr_locn;
locn = adjustLocn( locn, &curr_locn );
if( NULL != locn ) {
BrinfSrcSync( locn );
}
}
#ifndef NDEBUG
# define ShcVerify(t,m) if( !(t) ) printf( "%s\n", m );
#else
# define ShcVerify(a,b)
#endif
static boolean activeScopesReset// RESET ACTIVE SCOPES
( SCOPE scope // - new active scope
, TOKEN_LOCN const * locn ) // - file location to synchronize to
{
PSTK_ITER act_iter; // - iterator: old active scopes
PSTK_ITER sym_iter; // - iterator: new active scopes
SCOPE ascope; // - scope: old active scopes
SCOPE sscope; // - scope: new active scopes
boolean retn; // - return: TRUE ==> scope was adjusted
boolean short_circuit; // - can short-circuit scope adjustment
boolean in_template; // - active scope is in a TEMPLATE_PARM scope
if( canWriteIc() ) {
SCOPE top = PstkTopElement( &active_scopes );
DbgVerify( NULL == PstkTopElement( &sym_scopes )
, "Non-empty definition scope" );
if( scope->id == SCOPE_FUNCTION
&& NULL == scope->owner.sym ) {
// this is our kluge for analysing default-argument expr's
// we instead use the enclosing scope
scope = scope->enclosing;
}
switch( scope->id ) {
default :
if( scope == top ) {
short_circuit = TRUE;
break;
}
// drops thru
case SCOPE_TEMPLATE_DECL :
case SCOPE_TEMPLATE_PARM :
case SCOPE_TEMPLATE_INST :
short_circuit = FALSE;
break;
}
#ifdef NDEBUG
if( ! short_circuit )
#endif
{
sscope = scope;
for( ; sscope != NULL; sscope = sscope->enclosing ) {
PstkPush( &sym_scopes, sscope );
}
PstkIterUpOpen( &act_iter, &active_scopes );
PstkIterDnOpen( &sym_iter, &sym_scopes );
in_template = FALSE;
for( ; ; ) {
ascope = PstkIterUpNext( &act_iter );
sscope = PstkIterDnNext( &sym_iter );
if( ascope != sscope ) break;
if( ascope == NULL ) break;
if( ascope->id == SCOPE_TEMPLATE_PARM ){
in_template = TRUE;
}
}
if( ascope != NULL ) {
ShcVerify( ! short_circuit
, "failed short-circuit assumption" );
for( ; ; ) {
SCOPE top = PstkPopElement( &active_scopes );
closeScopeIc( top );
if( top == ascope ) break;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?