stats.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 632 行 · 第 1/2 页
C
632 行
/****************************************************************************
*
* 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!
*
****************************************************************************/
#include "plusplus.h"
#include "stats.h"
#include "preproc.h"
#include "initdefs.h"
#include "errdefns.h"
#include "vbuf.h"
#include "vstk.h"
static void statsInit( // INITIALIZE STATISTICS GATHERING
INITFINI* defn ) // - definition
{
defn = defn;
CompFlags.stats_printed = 0;
CompFlags.extra_stats_wanted = 0;
SrcLineCount = 0;
IncLineCount = 0;
WngCount = 0;
ErrCount = 0;
}
// this prints grammatically correct messages.
// i.e. no errors, or 1 error, or 5 errors
static void intPrint // PRINT INT LINE SEGMENT
( VBUF *buf
, char *thing
, char *end
, unsigned int count )
{
if( count == 0 ) {
VStrConcStr( buf, "no " );
} else {
VStrConcDecimal( buf, count );
VStrConcChr( buf, ' ' );
}
VStrConcStr( buf, thing );
if( count != 1 ) {
VStrConcChr( buf, 's' );
}
VStrConcStr( buf, end );
}
static void statsPrint( // PRINT STATISTICS
INITFINI* defn ) // - definition
{
defn = defn;
if( CompFlags.stats_printed ) {
return;
}
if( CompFlags.quiet_mode ) {
return;
}
if( ! CompFlags.srcfile_compiled ) {
return;
}
if( WholeFName != NULL ) {
VBUF buffer;
VbufInit( &buffer );
VStrNull( &buffer );
VStrConcStr( &buffer, WholeFName );
VStrConcStr( &buffer, ": " );
intPrint( &buffer, "line", ", ", SrcLineCount );
if( IncLineCount != 0 ) {
VStrConcStr( &buffer, "included " );
VStrConcDecimal( &buffer, IncLineCount );
VStrConcStr( &buffer, ", " );
}
intPrint( &buffer, "warning", ", ", WngCount );
intPrint( &buffer, "error", "", ErrCount );
MsgDisplayLine( buffer.buf );
CompFlags.stats_printed = 1;
VbufFree( &buffer );
}
}
INITDEFN( statistics, statsInit, statsPrint )
#ifdef XTRA_RPT
#include "carve.h"
#include "ring.h"
#define printf @use MsgDisplayLine@
#define puts @use MsgDisplayLine@
// The extra-report support is compiled only when XTRA_RPT is defined.
// At present, that occurs only in debug versions of the compiler.
typedef union rptreg RPTREG;
typedef struct rptreg_base RPTREG_BASE;
struct rptreg_base // RPTREG_BASE -- report registration
{ RPTREG* next; // - next in ring
void (*processor)( // - print processor
RPTREG* ); // - - takes self as arg.
};
typedef struct rptreg_ctr RPTREG_CTR;
struct rptreg_ctr // RPTREG_CTR -- report registration for ctr
{ RPTREG_BASE base; // - base
const char* text; // - report line
long* a_ctr; // - addr[ ctr ]
};
typedef struct rptreg_avg RPTREG_AVG;
struct rptreg_avg // RPTREG_AVG -- report registration for average
{ RPTREG_BASE base; // - base
const char* text; // - report line
RPTREG* total; // - total accumulation
RPTREG* count; // - count accumulation
};
typedef struct rptreg_tab RPTREG_TAB;
struct rptreg_tab // RPTREG_TAB -- report registration for table
{ RPTREG_BASE base; // - base
const char* title; // - title
const char * const *row_labels;// - row labels
long* table; // - values
unsigned dim_row; // - row dimension
unsigned dim_col; // - column dimension
};
union rptreg // RPTREG: one of
{ RPTREG_BASE base; // - a base
RPTREG_CTR ctr; // - counter entry
RPTREG_AVG avg; // - average entry
RPTREG_TAB tab; // - table
};
typedef struct // REPO_STAT -- repository statistics
{ VSTK_CTL refset; // - set of references to symbols
VSTK_CTL typeset; // - set of references to types
SRCFILE srcfile; // - source file
long defns; // - # definitions
} REPO_STAT;
static RPTREG* rpt_registrations; // registrations
static carve_t carve_ctr; // carving: RPTREG_CTR
static carve_t carve_avg; // carving: RPTREG_AVG
static carve_t carve_tab; // carving: RPTREG_TAB
static carve_t carve_sf; // carving: REPO_STAT
static VSTK_CTL srcFiles; // SRCFILE usages
static boolean isReposSym // TEST IF REPOSITORY SYMBOL
( SYMBOL sym ) // - the symbol
{
return CompFlags.extra_stats_wanted
&& ! SymIsTemporary( sym )
&& ( SF2_TOKEN_LOCN & sym->flag2 );
}
static REPO_STAT* reposStat // GET REPOSITORY STATISTICS FOR SRCFILE
( SRCFILE sf ) // - the source file
{
REPO_STAT** last; // - addr[ REPO_STAT ]
REPO_STAT* retn; // - REPO_STAT for source file
for( last = VstkTop( &srcFiles ); ; last = VstkNext( &srcFiles, last ) ) {
if( NULL == last ) {
retn = CarveAlloc( carve_sf );
*(REPO_STAT**)VstkPush( &srcFiles ) = retn;
VstkOpen( &retn->refset, sizeof( SYMBOL ), 32 );
VstkOpen( &retn->typeset, sizeof( TYPE ), 32 );
retn->srcfile = sf;
retn->defns = 0;
break;
}
retn = *last;
if( sf == retn->srcfile ) break;
}
return retn;
}
static void reportOnType // SET UP TYPE REFERENCE
( SRCFILE curr // - current source file
, TYPE type // - a type
, SYMBOL sym ) // - symbol for type
{
if( NULL != sym
&& ( SF2_TOKEN_LOCN & sym->flag2 ) ) {
SRCFILE refed = sym->locn->tl.src_file;
if( curr != refed ) {
REPO_STAT* repo = reposStat( curr );
TYPE* last;
for( last = VstkTop( &repo->typeset )
;
; last = VstkNext( &repo->typeset, last ) ) {
if( NULL == last ) {
*(TYPE*)VstkPush( &repo->typeset ) = type;
break;
}
if( type == *last ) break;
}
}
}
}
static void extraRptTypeUsage // TYPE USAGE
( TYPE type ) // - the type
{
SRCFILE current = SrcFileCurrent();
for( ; type != NULL; type = type->of ) {
switch( type->id ) {
case TYP_ENUM :
case TYP_TYPEDEF :
{ SYMBOL sym = type->u.t.sym;
reportOnType( current, type, sym );
} break;
case TYP_CLASS :
{ SYMBOL sym = type->u.c.scope->owner.sym;
reportOnType( current, type, sym );
} break;
case TYP_MEMBER_POINTER :
extraRptTypeUsage( type->u.mp.host );
continue;
case TYP_FUNCTION :
{ arg_list* args = type->u.f.args;
int count = args->num_args;
for( ; count > 0; ) {
-- count;
extraRptTypeUsage( args->type_list[count] );
}
}
// drops thru
default :
continue;
}
break;
}
}
void ExtraRptSymUsage( // REPORT SYMBOL USAGE FROM PRIMARY SOURCE
SYMBOL sym )
{
extraRptTypeUsage( sym->sym_type );
if( isReposSym( sym ) ) {
SRCFILE current = SrcFileCurrent();
SRCFILE refed = sym->locn->tl.src_file;
if( current != refed ) {
REPO_STAT* repo = reposStat( current );
SYMBOL* last;
for( last = VstkTop( &repo->refset )
;
; last = VstkNext( &repo->refset, last ) ) {
if( NULL == last ) {
*(SYMBOL*)VstkPush( &repo->refset ) = sym;
break;
}
if( sym == *last ) break;
}
}
}
}
void ExtraRptSymDefn( // REPORT SYMBOL DEFINITION IN PRIMARY SOURCE
SYMBOL sym )
{
extraRptTypeUsage( sym->sym_type );
if( isReposSym( sym ) ) {
SRCFILE current = SrcFileCurrent();
REPO_STAT* repo = reposStat( current );
++ repo->defns;
}
}
static char sbuff[512];
static char const fmt_repos[] = "%5d %5d %5d %5d %s";
static void rptRepository // PRINT REPOSITORY REPORT
( INITFINI* defn ) // - definition
{
REPO_STAT** last; // - addr[ REPO_STAT ]
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?