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