#!/usr/bin/perl
#
# Purpose: analyse output from GNU gcov command
#
# Run gcov sequentially on each .cpp source code file
# and sum up the source lines by function and file
# into coverage figures. Throw away meaningless gcov drivel,
# (ie. all the 0.00% results)
#
# Usage:
#
#     1. Compile program with -ftest-coverage -fprofile-arcs
#     2. <file>.cpp  --->   <file>.bb
#     3. Run program, <file>.da written to source code directory
#        when program terminates. Make sure you allow write access
#        for running uid to this directory.
#     4. Run ./gcovfilt in directory you wish to find out coverage
#        for (e.g. ~/src). gcov processes the .da files and
#        produces a summary. Remove the .da files if you want
#        to re-run program and not accumulate coverage
#        statistics aggregated with previous runs.
#
# If you can think of some great way to automate this, let me know.
# See also `zless /usr/info/gcc.info.gz` on a Linux box
# and tcov(1) on a Solaris box, which works in a similar fashion.
#

if ($ARGV[1] eq "--byfunction") {
    $byfunction = 1;
}

print "Analysing gcov output from:\n";

opendir(DIR, ".") or die "Cannot open directory '.' : $!\n";
my @files = readdir(DIR);
close(DIR);
foreach my $srcfile (@files) {
    next unless ($srcfile =~ m/.cpp$/);
    open (S, "gcov -l -b -f $srcfile | ") || die "Cannot run gcov on $srcfile: $!\n";
    while (<S>) {
        chomp;
        next if /  0.00%/;
        next if /^Creating/;
        next if /^No executable/;
        next if /\.\.\/\.\.\//;
        if (/(.*%) of .* source lines executed in file/) {
           $file{$1} = $_;
        }
        if (/(.*%) of .* source lines executed in function/) {
           $func{$1} = $_ . " (from $srcfile)";
        }
    }
    $| = 1;
    print "$srcfile ";
}

$| = 0;
print "\nLines:\n";

foreach $f (sort (keys %file)) {
     print "$file{$f}\n";
}

if ($byfunction) {
    print "\nFunctions:\n";

    foreach $f (sort (keys %func)) {
         print "$func{$f}\n";
    }
}

