Blame src/binding/cxx/mpicovsimple.cxx

Packit 0848f5
//-*- Mode: C++; c-basic-offset:4 ; -*- */
Packit 0848f5
//
Packit 0848f5
//  Copyright (C) 2004 by Argonne National Laboratory.
Packit 0848f5
//      See COPYRIGHT in top-level directory.
Packit 0848f5
//
Packit 0848f5
// This is a *very* simple tool for basic coverage analysis.  
Packit 0848f5
// This is intended as a stop-gap until gcov works with the C++ files
Packit 0848f5
// used in the MPICH binding of C++ (as of 2/23/2004, gcov aborts when
Packit 0848f5
// processing the coverage files produced by g++ for the MPICH C++
Packit 0848f5
// binding).
Packit 0848f5
//
Packit 0848f5
Packit 0848f5
#include <iostream.h>
Packit 0848f5
#include <fstream.h>
Packit 0848f5
#include <string.h>
Packit 0848f5
Packit 0848f5
#include "mpicovsimple.h"
Packit 0848f5
Packit 0848f5
/* For remove */
Packit 0848f5
#include <stdio.h>
Packit 0848f5
Packit 0848f5
// Find the matching entry or insert and initialize a new one
Packit 0848f5
covinfo * MPIX_Coverage::findOrInsert( const char name[], int argcount )
Packit 0848f5
{
Packit 0848f5
    covinfo *p = head, *newp;
Packit 0848f5
    int cmp;
Packit 0848f5
    static covinfo *lastp = 0;    // We use lastp to start where we
Packit 0848f5
                                  // left off if we can; this speeds
Packit 0848f5
                                  // sorted inserts
Packit 0848f5
    
Packit 0848f5
    // See if we can skip ahead...
Packit 0848f5
    if (lastp) {
Packit 0848f5
	cmp = strcmp( lastp->name, name );
Packit 0848f5
	if (cmp < 0 || (cmp == 0 && lastp->argcount <= argcount )) p = lastp;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    while (p) {
Packit 0848f5
	cmp = strcmp( p->name, name );
Packit 0848f5
	if (cmp == 0) {
Packit 0848f5
	    cmp = p->argcount - argcount;
Packit 0848f5
	    if (cmp == 0) { 
Packit 0848f5
		// If still 0, we've found our match.
Packit 0848f5
		lastp = p;
Packit 0848f5
		return p;
Packit 0848f5
	    }
Packit 0848f5
	}
Packit 0848f5
Packit 0848f5
	if (cmp > 0) {
Packit 0848f5
	    // If we got here, backup and exit to perform the insert
Packit 0848f5
	    p = p->bLink;
Packit 0848f5
	    break;
Packit 0848f5
	}
Packit 0848f5
	// If we're at the end of the list, this p is the last element,
Packit 0848f5
	// so we exit now
Packit 0848f5
	if (!p->fLink) break;
Packit 0848f5
Packit 0848f5
	p = p->fLink;
Packit 0848f5
    }
Packit 0848f5
    
Packit 0848f5
    // If we got here, we need to insert after p
Packit 0848f5
    newp             = new covinfo;
Packit 0848f5
    newp->name       = new char [strlen(name)+1];
Packit 0848f5
    strcpy( newp->name, name );
Packit 0848f5
    newp->argcount   = argcount;
Packit 0848f5
    newp->count      = 0;
Packit 0848f5
    newp->sourceFile = 0;
Packit 0848f5
    newp->firstLine  = -1;
Packit 0848f5
    newp->lastLine   = -1;
Packit 0848f5
    newp->bLink      = p;
Packit 0848f5
    if (p) {
Packit 0848f5
	// insert after p
Packit 0848f5
	newp->fLink = p->fLink;
Packit 0848f5
	p->fLink    = newp;
Packit 0848f5
	if (newp->fLink) {
Packit 0848f5
	    newp->fLink->bLink = newp;
Packit 0848f5
	}
Packit 0848f5
    }
Packit 0848f5
    else {
Packit 0848f5
	// insert at the head of the list
Packit 0848f5
	newp->fLink = head;
Packit 0848f5
	if (head) { 
Packit 0848f5
	    head->bLink = newp; 
Packit 0848f5
	}
Packit 0848f5
	head        = newp;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    lastp = newp;
Packit 0848f5
    return newp;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
// Add an item to the coverage list, including the first line
Packit 0848f5
void MPIX_Coverage::Add( const char name[], int argcnt, 
Packit 0848f5
		    const char file[], int line )
Packit 0848f5
{
Packit 0848f5
    covinfo *p = findOrInsert( name, argcnt );
Packit 0848f5
Packit 0848f5
    p->count ++;
Packit 0848f5
    if (!p->sourceFile) {
Packit 0848f5
	p->sourceFile = new char [strlen(file)+1];
Packit 0848f5
	strcpy( p->sourceFile, file );
Packit 0848f5
	p->firstLine = line;
Packit 0848f5
    }
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
// Add the last line value to an item in the coverage list
Packit 0848f5
void MPIX_Coverage::AddEnd( const char name[], int argcnt,
Packit 0848f5
		       const char file[], int line )
Packit 0848f5
{
Packit 0848f5
    covinfo *p = findOrInsert( name, argcnt );
Packit 0848f5
Packit 0848f5
    if (p->lastLine < 0) 
Packit 0848f5
	p->lastLine = line;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
//
Packit 0848f5
// Merge the coverage data with the data in the file
Packit 0848f5
// The directory for the coverage file is defined by the
Packit 0848f5
// cpp value COVERAGE_DIR
Packit 0848f5
int MPIX_Coverage::FileMerge( const char filename[] )
Packit 0848f5
{
Packit 0848f5
    ifstream infile;
Packit 0848f5
    ofstream outfile;
Packit 0848f5
    covinfo *p;
Packit 0848f5
    covinfo fp;
Packit 0848f5
    char *infilename, *tmpfilename;
Packit 0848f5
Packit 0848f5
    // Try to open the input file.  
Packit 0848f5
    {
Packit 0848f5
#ifdef COVERAGE_DIR
Packit 0848f5
	infilename = new char [strlen(filename) + strlen(COVERAGE_DIR) + 2 ];
Packit 0848f5
	strcpy( infilename, COVERAGE_DIR );
Packit 0848f5
	strcat( infilename, "/" );
Packit 0848f5
	strcat( infilename, filename );
Packit 0848f5
#else
Packit 0848f5
	infilename = (char *)filename;
Packit 0848f5
#endif
Packit 0848f5
	infile.open( infilename );
Packit 0848f5
Packit 0848f5
	// Create a place in which to read the data
Packit 0848f5
	fp.name       = new char [1024];
Packit 0848f5
	fp.sourceFile = new char [1024];
Packit 0848f5
Packit 0848f5
	// Add the contents of the file to the internal list
Packit 0848f5
	// This is easy but not the most memory efficient.
Packit 0848f5
	// If this becomes a problem, we can merge the two
Packit 0848f5
	// into a single output
Packit 0848f5
	while (infile) {
Packit 0848f5
	    fp.count = -1;  // Set a sentinal on eof in infile
Packit 0848f5
	    infile >> fp.name >> fp.argcount >> fp.count >> fp.sourceFile >>
Packit 0848f5
		fp.firstLine >> fp.lastLine;
Packit 0848f5
	    if (fp.count == -1) break;
Packit 0848f5
	    p = findOrInsert( fp.name, fp.argcount );
Packit 0848f5
	    if (!p->sourceFile) {
Packit 0848f5
		p->sourceFile = strdup( fp.sourceFile );
Packit 0848f5
		p->firstLine  = fp.firstLine;
Packit 0848f5
		p->lastLine   = fp.lastLine;
Packit 0848f5
	    }
Packit 0848f5
	    p->count += fp.count;
Packit 0848f5
	}
Packit 0848f5
	infile.close();
Packit 0848f5
	// Recover new storage
Packit 0848f5
	delete fp.name;
Packit 0848f5
	delete fp.sourceFile;
Packit 0848f5
    }
Packit 0848f5
    
Packit 0848f5
    // Try to open the output file
Packit 0848f5
#ifdef COVERAGE_DIR
Packit 0848f5
    tmpfilename = new char [strlen(".covtmp") + strlen(COVERAGE_DIR) + 2 ];
Packit 0848f5
    strcpy( tmpfilename, COVERAGE_DIR );
Packit 0848f5
    strcat( tmpfilename, "/" );
Packit 0848f5
    strcat( tmpfilename, ".covtmp" );
Packit 0848f5
#else
Packit 0848f5
    tmpfilename = ".covtmp";
Packit 0848f5
#endif
Packit 0848f5
    outfile.open( tmpfilename );
Packit 0848f5
Packit 0848f5
    p = head;
Packit 0848f5
    while (p) {
Packit 0848f5
	outfile << p->name << '\t' << p->argcount << '\t' << 
Packit 0848f5
	    p->count << '\t' << p->sourceFile << '\t' <<
Packit 0848f5
	    p->firstLine << '\t' << p->lastLine << '\n';
Packit 0848f5
	p = p->fLink;
Packit 0848f5
    }
Packit 0848f5
    
Packit 0848f5
    outfile.close();
Packit 0848f5
    
Packit 0848f5
    // Now, remove the old file and move the new file over it
Packit 0848f5
    remove( infilename );
Packit 0848f5
    rename( tmpfilename, infilename );
Packit 0848f5
Packit 0848f5
    return 0;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
#if 0
Packit 0848f5
// This is partial and incomplete code for an alternative version of
Packit 0848f5
// FileMerge that avoids reading the entire file into memory
Packit 0848f5
// This was a early version that was lost in a terrible keyboarding 
Packit 0848f5
// accident just after it was debugged :)
Packit 0848f5
// This predates the current form of the coverage file and contains
Packit 0848f5
// a number of bugs, but it would be a reasonable starting point 
Packit 0848f5
// if it is desired to avoid reading the entire file into memory.
Packit 0848f5
int MPIX_Ooverage::FileMerge( const char filename[] )
Packit 0848f5
{
Packit 0848f5
    covinfo *p, *fp=0;
Packit 0848f5
    ifstream infile;
Packit 0848f5
    ofstream outfile;
Packit 0848f5
    char *tmpfile;
Packit 0848f5
Packit 0848f5
    infile.open( filename, ios::in );
Packit 0848f5
Packit 0848f5
    tmpfile = new char [ strlen(filename) + 5 ];
Packit 0848f5
    strcpy( tmpfile, filename );
Packit 0848f5
    strcat( tmpfile, ".tmp" );
Packit 0848f5
    outfile.open( tmpfile );
Packit 0848f5
    if (!outfile) {
Packit 0848f5
	cerr << "Unable to open " << tmpfile << "\n";
Packit 0848f5
    }
Packit 0848f5
    p = head;
Packit 0848f5
    if (infile) {
Packit 0848f5
	fp = new covinfo;
Packit 0848f5
	fp->name = new char [1024];
Packit 0848f5
	infile >> fp->name >> fp->argcount >> fp->count;
Packit 0848f5
    }
Packit 0848f5
    while (p) {
Packit 0848f5
	int cmp = 0;
Packit 0848f5
	if (fp) {
Packit 0848f5
	    cmp = strcmp( fp->name, p->name );
Packit 0848f5
	    if (cmp == 0) {
Packit 0848f5
		cmp = fp->argcount - p->argcount;
Packit 0848f5
	    }
Packit 0848f5
	    if (cmp < 0) {
Packit 0848f5
		// output the file entry
Packit 0848f5
		outfile << fp->name << '\t' << fp->argcount << '\t' <<
Packit 0848f5
		    fp->count << '\n';
Packit 0848f5
		infile >> fp->name >> fp->argcount >> fp->count;
Packit 0848f5
		if (infile.eof()) break;
Packit 0848f5
		continue;
Packit 0848f5
	    }
Packit 0848f5
	    else if (cmp == 0) {
Packit 0848f5
		// Increment the p entry 
Packit 0848f5
		p->count += fp->count;
Packit 0848f5
		infile >> fp->name >> fp->argcount >> fp->count;
Packit 0848f5
		if (infile.eof()) break;
Packit 0848f5
	    }
Packit 0848f5
	    // else keep this entry
Packit 0848f5
	}
Packit 0848f5
	outfile << p->name << '\t' << p->argcount << '\t' << p->count << '\n';
Packit 0848f5
	p = p->fLink;
Packit 0848f5
    }
Packit 0848f5
    // Read the rest of the file, if any
Packit 0848f5
    while (infile && !infile.eof()) {
Packit 0848f5
	infile >> fp->name >> fp->argcount fp->count;
Packit 0848f5
	outfile << fp->name << '\t' << fp->argcount << '\t' <<
Packit 0848f5
	    fp->count << '\n';
Packit 0848f5
    }
Packit 0848f5
    // Output the rest of the list
Packit 0848f5
    while (p) {
Packit 0848f5
	outfile << p->name << '\t' << p->argcount << '\t' << p->count << '\n';
Packit 0848f5
	p = p->fLink;
Packit 0848f5
    }
Packit 0848f5
    // Close the input file if we opened it...
Packit 0848f5
    if (fp) {
Packit 0848f5
	infile.close();
Packit 0848f5
	... remove code as above
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
}
Packit 0848f5
#endif
Packit 0848f5
Packit 0848f5
MPIX_Coverage MPIR_Cov;
Packit 0848f5
Packit 0848f5
//#define TEST_PROGRAM
Packit 0848f5
#ifdef TEST_PROGRAM
Packit 0848f5
int main( int argc, char **argv )
Packit 0848f5
{
Packit 0848f5
    MPIR_Cov.Add( "foo", 2, __FILE__, __LINE__ );
Packit 0848f5
    MPIR_Cov.Add( "foo", 1, __FILE__, __LINE__ );
Packit 0848f5
    MPIR_Cov.Add( "bar", 2, __FILE__, __LINE__ );
Packit 0848f5
    
Packit 0848f5
    MPIR_Cov.FileMerge( "covtest.dat" );
Packit 0848f5
    return 0;
Packit 0848f5
}
Packit 0848f5
#endif