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 + -
显示快捷键?