169d495de9c26f1b99c9af8b2d366a09f23b47b76njn#! @PERL@
269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
369d495de9c26f1b99c9af8b2d366a09f23b47b76njn##--------------------------------------------------------------------##
469d495de9c26f1b99c9af8b2d366a09f23b47b76njn##--- Cachegrind's differencer.                         cg_diff.in ---##
569d495de9c26f1b99c9af8b2d366a09f23b47b76njn##--------------------------------------------------------------------##
669d495de9c26f1b99c9af8b2d366a09f23b47b76njn
769d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  This file is part of Cachegrind, a Valgrind tool for cache
869d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  profiling programs.
969d495de9c26f1b99c9af8b2d366a09f23b47b76njn#
1006766bdbcfe770592c0c91353cfa9e8f4d1ee4e6florian#  Copyright (C) 2002-2013 Nicholas Nethercote
1169d495de9c26f1b99c9af8b2d366a09f23b47b76njn#     njn@valgrind.org
1269d495de9c26f1b99c9af8b2d366a09f23b47b76njn#
1369d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  This program is free software; you can redistribute it and/or
1469d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  modify it under the terms of the GNU General Public License as
1569d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  published by the Free Software Foundation; either version 2 of the
1669d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  License, or (at your option) any later version.
1769d495de9c26f1b99c9af8b2d366a09f23b47b76njn#
1869d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  This program is distributed in the hope that it will be useful, but
1969d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  WITHOUT ANY WARRANTY; without even the implied warranty of
2069d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2169d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  General Public License for more details.
2269d495de9c26f1b99c9af8b2d366a09f23b47b76njn#
2369d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  You should have received a copy of the GNU General Public License
2469d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  along with this program; if not, write to the Free Software
2569d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2669d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  02111-1307, USA.
2769d495de9c26f1b99c9af8b2d366a09f23b47b76njn#
2869d495de9c26f1b99c9af8b2d366a09f23b47b76njn#  The GNU General Public License is contained in the file COPYING.
2969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
3069d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
3169d495de9c26f1b99c9af8b2d366a09f23b47b76njn# This is a very cut-down and modified version of cg_annotate.
3269d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
3369d495de9c26f1b99c9af8b2d366a09f23b47b76njn
3469d495de9c26f1b99c9af8b2d366a09f23b47b76njnuse warnings;
3569d495de9c26f1b99c9af8b2d366a09f23b47b76njnuse strict;
3669d495de9c26f1b99c9af8b2d366a09f23b47b76njn
3769d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
3869d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Global variables
3969d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
4069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
4169d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Version number
4269d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $version = "@VERSION@";
4369d495de9c26f1b99c9af8b2d366a09f23b47b76njn
4469d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Usage message.
4569d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $usage = <<END
4669d495de9c26f1b99c9af8b2d366a09f23b47b76njnusage: cg_diff [options] <cachegrind-out-file1> <cachegrind-out-file2>
4769d495de9c26f1b99c9af8b2d366a09f23b47b76njn
4869d495de9c26f1b99c9af8b2d366a09f23b47b76njn  options for the user, with defaults in [ ], are:
4969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    -h --help             show this message
5069d495de9c26f1b99c9af8b2d366a09f23b47b76njn    -v --version          show version
5169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    --mod-filename=<expr> a Perl search-and-replace expression that is applied
5269d495de9c26f1b99c9af8b2d366a09f23b47b76njn                          to filenames, eg. --mod-filename='s/prog[0-9]/projN/'
53e5930dabbff46a55a9dc8056afaa688050ea12bdnjn    --mod-funcname=<expr> like --mod-filename, but applied to function names
5469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
5506766bdbcfe770592c0c91353cfa9e8f4d1ee4e6florian  cg_diff is Copyright (C) 2002-2013 Nicholas Nethercote.
5669d495de9c26f1b99c9af8b2d366a09f23b47b76njn  and licensed under the GNU General Public License, version 2.
5769d495de9c26f1b99c9af8b2d366a09f23b47b76njn  Bug reports, feedback, admiration, abuse, etc, to: njn\@valgrind.org.
5869d495de9c26f1b99c9af8b2d366a09f23b47b76njn                                                
5969d495de9c26f1b99c9af8b2d366a09f23b47b76njnEND
6069d495de9c26f1b99c9af8b2d366a09f23b47b76njn;
6169d495de9c26f1b99c9af8b2d366a09f23b47b76njn
6269d495de9c26f1b99c9af8b2d366a09f23b47b76njn# --mod-filename expression
6369d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $mod_filename = undef;
6469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
65e5930dabbff46a55a9dc8056afaa688050ea12bdnjn# --mod-funcname expression
66e5930dabbff46a55a9dc8056afaa688050ea12bdnjnmy $mod_funcname = undef;
67e5930dabbff46a55a9dc8056afaa688050ea12bdnjn
6869d495de9c26f1b99c9af8b2d366a09f23b47b76njn#-----------------------------------------------------------------------------
6969d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Argument and option handling
7069d495de9c26f1b99c9af8b2d366a09f23b47b76njn#-----------------------------------------------------------------------------
7169d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub process_cmd_line() 
7269d495de9c26f1b99c9af8b2d366a09f23b47b76njn{
7369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my ($file1, $file2) = (undef, undef);
7469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
7569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    for my $arg (@ARGV) { 
7669d495de9c26f1b99c9af8b2d366a09f23b47b76njn
7769d495de9c26f1b99c9af8b2d366a09f23b47b76njn        if ($arg =~ /^-/) {
7869d495de9c26f1b99c9af8b2d366a09f23b47b76njn            # --version
7969d495de9c26f1b99c9af8b2d366a09f23b47b76njn            if ($arg =~ /^-v$|^--version$/) {
8069d495de9c26f1b99c9af8b2d366a09f23b47b76njn                die("cg_diff-$version\n");
8169d495de9c26f1b99c9af8b2d366a09f23b47b76njn
8269d495de9c26f1b99c9af8b2d366a09f23b47b76njn            } elsif ($arg =~ /^--mod-filename=(.*)/) {
8369d495de9c26f1b99c9af8b2d366a09f23b47b76njn                $mod_filename = $1;
8469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
85e5930dabbff46a55a9dc8056afaa688050ea12bdnjn            } elsif ($arg =~ /^--mod-funcname=(.*)/) {
86e5930dabbff46a55a9dc8056afaa688050ea12bdnjn                $mod_funcname = $1;
87e5930dabbff46a55a9dc8056afaa688050ea12bdnjn
8869d495de9c26f1b99c9af8b2d366a09f23b47b76njn            } else {            # -h and --help fall under this case
8969d495de9c26f1b99c9af8b2d366a09f23b47b76njn                die($usage);
9069d495de9c26f1b99c9af8b2d366a09f23b47b76njn            }
9169d495de9c26f1b99c9af8b2d366a09f23b47b76njn
9269d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } elsif (not defined($file1)) {
9369d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $file1 = $arg;
9469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
9569d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } elsif (not defined($file2)) {
9669d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $file2 = $arg;
9769d495de9c26f1b99c9af8b2d366a09f23b47b76njn
9869d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } else {
9969d495de9c26f1b99c9af8b2d366a09f23b47b76njn            die($usage);
10069d495de9c26f1b99c9af8b2d366a09f23b47b76njn        }
10169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
10269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
10369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # Must have specified two input files.
10469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    if (not defined $file1 or not defined $file2) {
10569d495de9c26f1b99c9af8b2d366a09f23b47b76njn        die($usage);
10669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
10769d495de9c26f1b99c9af8b2d366a09f23b47b76njn
10869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    return ($file1, $file2);
10969d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
11069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
11169d495de9c26f1b99c9af8b2d366a09f23b47b76njn#-----------------------------------------------------------------------------
11269d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Reading of input file
11369d495de9c26f1b99c9af8b2d366a09f23b47b76njn#-----------------------------------------------------------------------------
11469d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub max ($$) 
11569d495de9c26f1b99c9af8b2d366a09f23b47b76njn{
11669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my ($x, $y) = @_;
11769d495de9c26f1b99c9af8b2d366a09f23b47b76njn    return ($x > $y ? $x : $y);
11869d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
11969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
12069d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Add the two arrays;  any '.' entries are ignored.  Two tricky things:
12169d495de9c26f1b99c9af8b2d366a09f23b47b76njn# 1. If $a2->[$i] is undefined, it defaults to 0 which is what we want; we turn
12269d495de9c26f1b99c9af8b2d366a09f23b47b76njn#    off warnings to allow this.  This makes things about 10% faster than
12369d495de9c26f1b99c9af8b2d366a09f23b47b76njn#    checking for definedness ourselves.
12469d495de9c26f1b99c9af8b2d366a09f23b47b76njn# 2. We don't add an undefined count or a ".", even though it's value is 0,
12569d495de9c26f1b99c9af8b2d366a09f23b47b76njn#    because we don't want to make an $a2->[$i] that is undef become 0
12669d495de9c26f1b99c9af8b2d366a09f23b47b76njn#    unnecessarily.
12769d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub add_array_a_to_b ($$) 
12869d495de9c26f1b99c9af8b2d366a09f23b47b76njn{
12969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my ($a, $b) = @_;
13069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
13169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $n = max(scalar @$a, scalar @$b);
13269d495de9c26f1b99c9af8b2d366a09f23b47b76njn    $^W = 0;
13369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    foreach my $i (0 .. $n-1) {
13469d495de9c26f1b99c9af8b2d366a09f23b47b76njn        $b->[$i] += $a->[$i] if (defined $a->[$i] && "." ne $a->[$i]);
13569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
13669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    $^W = 1;
13769d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
13869d495de9c26f1b99c9af8b2d366a09f23b47b76njn
13969d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub sub_array_b_from_a ($$) 
14069d495de9c26f1b99c9af8b2d366a09f23b47b76njn{
14169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my ($a, $b) = @_;
14269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
14369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $n = max(scalar @$a, scalar @$b);
14469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    $^W = 0;
14569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    foreach my $i (0 .. $n-1) {
14669d495de9c26f1b99c9af8b2d366a09f23b47b76njn        $a->[$i] -= $b->[$i];       # XXX: doesn't handle '.' entries
14769d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
14869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    $^W = 1;
14969d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
15069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
15169d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Add each event count to the CC array.  '.' counts become undef, as do
15269d495de9c26f1b99c9af8b2d366a09f23b47b76njn# missing entries (implicitly).
15369d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub line_to_CC ($$)
15469d495de9c26f1b99c9af8b2d366a09f23b47b76njn{
15569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my ($line, $numEvents) = @_;
15669d495de9c26f1b99c9af8b2d366a09f23b47b76njn
15769d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my @CC = (split /\s+/, $line);
15869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    (@CC <= $numEvents) or die("Line $.: too many event counts\n");
15969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    return \@CC;
16069d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
16169d495de9c26f1b99c9af8b2d366a09f23b47b76njn
16269d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub read_input_file($) 
16369d495de9c26f1b99c9af8b2d366a09f23b47b76njn{
16469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my ($input_file) = @_;
16569d495de9c26f1b99c9af8b2d366a09f23b47b76njn
16669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    open(INPUTFILE, "< $input_file") 
16769d495de9c26f1b99c9af8b2d366a09f23b47b76njn         || die "Cannot open $input_file for reading\n";
16869d495de9c26f1b99c9af8b2d366a09f23b47b76njn
16969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # Read "desc:" lines.
17069d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $desc;
17169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $line;
17269d495de9c26f1b99c9af8b2d366a09f23b47b76njn    while ($line = <INPUTFILE>) {
17369d495de9c26f1b99c9af8b2d366a09f23b47b76njn        if ($line =~ s/desc:\s+//) {
17469d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $desc .= $line;
17569d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } else {
17669d495de9c26f1b99c9af8b2d366a09f23b47b76njn            last;
17769d495de9c26f1b99c9af8b2d366a09f23b47b76njn        }
17869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
17969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
18069d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # Read "cmd:" line (Nb: will already be in $line from "desc:" loop above).
18169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    ($line =~ s/^cmd:\s+//) or die("Line $.: missing command line\n");
18269d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $cmd = $line;
18369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    chomp($cmd);    # Remove newline
18469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
18569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # Read "events:" line.  We make a temporary hash in which the Nth event's
18669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # value is N, which is useful for handling --show/--sort options below.
18769d495de9c26f1b99c9af8b2d366a09f23b47b76njn    $line = <INPUTFILE>;
18869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    (defined $line && $line =~ s/^events:\s+//) 
18969d495de9c26f1b99c9af8b2d366a09f23b47b76njn        or die("Line $.: missing events line\n");
19069d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my @events = split(/\s+/, $line);
19169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $numEvents = scalar @events;
19269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
19369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $currFileName;
19469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $currFileFuncName;
19569d495de9c26f1b99c9af8b2d366a09f23b47b76njn
19669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my %CCs;                    # hash("$filename#$funcname" => CC array)
19769d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $currCC = undef;         # CC array
19869d495de9c26f1b99c9af8b2d366a09f23b47b76njn
19969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $summaryCC;
20069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
20169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # Read body of input file.
20269d495de9c26f1b99c9af8b2d366a09f23b47b76njn    while (<INPUTFILE>) {
20369d495de9c26f1b99c9af8b2d366a09f23b47b76njn        s/#.*$//;   # remove comments
20469d495de9c26f1b99c9af8b2d366a09f23b47b76njn        if (s/^(\d+)\s+//) {
20569d495de9c26f1b99c9af8b2d366a09f23b47b76njn            my $CC = line_to_CC($_, $numEvents);
20669d495de9c26f1b99c9af8b2d366a09f23b47b76njn            defined($currCC) || die;
20769d495de9c26f1b99c9af8b2d366a09f23b47b76njn            add_array_a_to_b($CC, $currCC);
20869d495de9c26f1b99c9af8b2d366a09f23b47b76njn
20969d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } elsif (s/^fn=(.*)$//) {
21069d495de9c26f1b99c9af8b2d366a09f23b47b76njn            defined($currFileName) || die;
211e5930dabbff46a55a9dc8056afaa688050ea12bdnjn            my $tmpFuncName = $1;
212e5930dabbff46a55a9dc8056afaa688050ea12bdnjn            if (defined $mod_funcname) {
213e5930dabbff46a55a9dc8056afaa688050ea12bdnjn                eval "\$tmpFuncName =~ $mod_funcname";
214e5930dabbff46a55a9dc8056afaa688050ea12bdnjn            }
215e5930dabbff46a55a9dc8056afaa688050ea12bdnjn            $currFileFuncName = "$currFileName#$tmpFuncName";
21669d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $currCC = $CCs{$currFileFuncName};
21769d495de9c26f1b99c9af8b2d366a09f23b47b76njn            if (not defined $currCC) {
21869d495de9c26f1b99c9af8b2d366a09f23b47b76njn                $currCC = [];
21969d495de9c26f1b99c9af8b2d366a09f23b47b76njn                $CCs{$currFileFuncName} = $currCC;
22069d495de9c26f1b99c9af8b2d366a09f23b47b76njn            }
22169d495de9c26f1b99c9af8b2d366a09f23b47b76njn
22269d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } elsif (s/^fl=(.*)$//) {
22369d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $currFileName = $1;
22469d495de9c26f1b99c9af8b2d366a09f23b47b76njn            if (defined $mod_filename) {
22569d495de9c26f1b99c9af8b2d366a09f23b47b76njn                eval "\$currFileName =~ $mod_filename";
22669d495de9c26f1b99c9af8b2d366a09f23b47b76njn            }
22769d495de9c26f1b99c9af8b2d366a09f23b47b76njn            # Assume that a "fn=" line is followed by a "fl=" line.
22869d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $currFileFuncName = undef;  
22969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
23069d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } elsif (s/^\s*$//) {
23169d495de9c26f1b99c9af8b2d366a09f23b47b76njn            # blank, do nothing
23269d495de9c26f1b99c9af8b2d366a09f23b47b76njn        
23369d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } elsif (s/^summary:\s+//) {
23469d495de9c26f1b99c9af8b2d366a09f23b47b76njn            $summaryCC = line_to_CC($_, $numEvents);
23569d495de9c26f1b99c9af8b2d366a09f23b47b76njn            (scalar(@$summaryCC) == @events) 
23669d495de9c26f1b99c9af8b2d366a09f23b47b76njn                or die("Line $.: summary event and total event mismatch\n");
23769d495de9c26f1b99c9af8b2d366a09f23b47b76njn
23869d495de9c26f1b99c9af8b2d366a09f23b47b76njn        } else {
23969d495de9c26f1b99c9af8b2d366a09f23b47b76njn            warn("WARNING: line $. malformed, ignoring\n");
24069d495de9c26f1b99c9af8b2d366a09f23b47b76njn        }
24169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
24269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
24369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    # Check if summary line was present
24469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    if (not defined $summaryCC) {
24569d495de9c26f1b99c9af8b2d366a09f23b47b76njn        die("missing final summary line, aborting\n");
24669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
24769d495de9c26f1b99c9af8b2d366a09f23b47b76njn
24869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    close(INPUTFILE);
24969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
25069d495de9c26f1b99c9af8b2d366a09f23b47b76njn    return ($cmd, \@events, \%CCs, $summaryCC);
25169d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
25269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
25369d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
25469d495de9c26f1b99c9af8b2d366a09f23b47b76njn# "main()"
25569d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
25669d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Commands seen in the files.  Need not match.
25769d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $cmd1;
25869d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $cmd2;
25969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
26069d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Events seen in the files.  They must match.
26169d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $events1;
26269d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $events2;
26369d495de9c26f1b99c9af8b2d366a09f23b47b76njn
26469d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Individual CCs, organised by filename/funcname/line_num.
26569d495de9c26f1b99c9af8b2d366a09f23b47b76njn# hashref("$filename#$funcname", CC array)
26669d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $CCs1;
26769d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $CCs2;
26869d495de9c26f1b99c9af8b2d366a09f23b47b76njn
26969d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Total counts for summary (an arrayref).
27069d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $summaryCC1;
27169d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $summaryCC2;
27269d495de9c26f1b99c9af8b2d366a09f23b47b76njn
27369d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
27469d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Read the input files
27569d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
27669d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy ($file1, $file2) = process_cmd_line();
27769d495de9c26f1b99c9af8b2d366a09f23b47b76njn($cmd1, $events1, $CCs1, $summaryCC1) = read_input_file($file1);
27869d495de9c26f1b99c9af8b2d366a09f23b47b76njn($cmd2, $events2, $CCs2, $summaryCC2) = read_input_file($file2);
27969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
28069d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
28169d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Check the events match
28269d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
28369d495de9c26f1b99c9af8b2d366a09f23b47b76njnmy $n = max(scalar @$events1, scalar @$events2);
28469d495de9c26f1b99c9af8b2d366a09f23b47b76njn$^W = 0;    # turn off warnings, because we might hit undefs
28569d495de9c26f1b99c9af8b2d366a09f23b47b76njnforeach my $i (0 .. $n-1) {
28669d495de9c26f1b99c9af8b2d366a09f23b47b76njn    ($events1->[$i] eq $events2->[$i]) || die "events don't match, aborting\n";
28769d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
28869d495de9c26f1b99c9af8b2d366a09f23b47b76njn$^W = 1;
28969d495de9c26f1b99c9af8b2d366a09f23b47b76njn
29069d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
29169d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Do the subtraction: CCs2 -= CCs1
29269d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
29369d495de9c26f1b99c9af8b2d366a09f23b47b76njnwhile (my ($filefuncname, $CC1) = each(%$CCs1)) {
29469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my $CC2 = $CCs2->{$filefuncname};
29569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    if (not defined $CC2) {
29669d495de9c26f1b99c9af8b2d366a09f23b47b76njn        $CC2 = [];
29769d495de9c26f1b99c9af8b2d366a09f23b47b76njn        sub_array_b_from_a($CC2, $CC1);     # CC2 -= CC1
29869d495de9c26f1b99c9af8b2d366a09f23b47b76njn        $CCs2->{$filefuncname} = $CC2;
29969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    } else {
30069d495de9c26f1b99c9af8b2d366a09f23b47b76njn        sub_array_b_from_a($CC2, $CC1);     # CC2 -= CC1
30169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
30269d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
30369d495de9c26f1b99c9af8b2d366a09f23b47b76njnsub_array_b_from_a($summaryCC2, $summaryCC1);
30469d495de9c26f1b99c9af8b2d366a09f23b47b76njn
30569d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
30669d495de9c26f1b99c9af8b2d366a09f23b47b76njn# Print the result, in CCs2
30769d495de9c26f1b99c9af8b2d366a09f23b47b76njn#----------------------------------------------------------------------------
30869d495de9c26f1b99c9af8b2d366a09f23b47b76njnprint("desc: Files compared:   $file1; $file2\n");
30969d495de9c26f1b99c9af8b2d366a09f23b47b76njnprint("cmd:  $cmd1; $cmd2\n");
31069d495de9c26f1b99c9af8b2d366a09f23b47b76njnprint("events: ");
31169d495de9c26f1b99c9af8b2d366a09f23b47b76njnfor my $e (@$events1) {
31269d495de9c26f1b99c9af8b2d366a09f23b47b76njn    print(" $e");
31369d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
31469d495de9c26f1b99c9af8b2d366a09f23b47b76njnprint("\n");
31569d495de9c26f1b99c9af8b2d366a09f23b47b76njn
31669d495de9c26f1b99c9af8b2d366a09f23b47b76njnwhile (my ($filefuncname, $CC) = each(%$CCs2)) {
31769d495de9c26f1b99c9af8b2d366a09f23b47b76njn
31869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    my @x = split(/#/, $filefuncname);
31969d495de9c26f1b99c9af8b2d366a09f23b47b76njn    (scalar @x == 2) || die;
32069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
32169d495de9c26f1b99c9af8b2d366a09f23b47b76njn    print("fl=$x[0]\n");
32269d495de9c26f1b99c9af8b2d366a09f23b47b76njn    print("fn=$x[1]\n");
32369d495de9c26f1b99c9af8b2d366a09f23b47b76njn
32469d495de9c26f1b99c9af8b2d366a09f23b47b76njn    print("0");
32569d495de9c26f1b99c9af8b2d366a09f23b47b76njn    foreach my $n (@$CC) {
32669d495de9c26f1b99c9af8b2d366a09f23b47b76njn        print(" $n");
32769d495de9c26f1b99c9af8b2d366a09f23b47b76njn    }
32869d495de9c26f1b99c9af8b2d366a09f23b47b76njn    print("\n");
32969d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
33069d495de9c26f1b99c9af8b2d366a09f23b47b76njn
33169d495de9c26f1b99c9af8b2d366a09f23b47b76njnprint("summary:");
33269d495de9c26f1b99c9af8b2d366a09f23b47b76njnforeach my $n (@$summaryCC2) {
33369d495de9c26f1b99c9af8b2d366a09f23b47b76njn    print(" $n");
33469d495de9c26f1b99c9af8b2d366a09f23b47b76njn}
33569d495de9c26f1b99c9af8b2d366a09f23b47b76njnprint("\n");
33669d495de9c26f1b99c9af8b2d366a09f23b47b76njn
33769d495de9c26f1b99c9af8b2d366a09f23b47b76njn##--------------------------------------------------------------------##
33869d495de9c26f1b99c9af8b2d366a09f23b47b76njn##--- end                                                          ---##
33969d495de9c26f1b99c9af8b2d366a09f23b47b76njn##--------------------------------------------------------------------##
340