#!/usr/bin/perl -w

my $inmemcheckheader = 0;
my $incallstack      = 0;
my $inmemstack       = 0;
my $blanklines       = 0;
my $message;
my $callstack;
my $memstack;
my $key;
my $insummary = 0;
my %stackhash = ();

while (<ARGV>)
{
    chomp;

    next if !( $_ =~ /.*==[0-9]+== / ); # skip non memcheck lines
    $_ =~ s/.*==[0-9]+== //;   # remove memcheck process id

    if ($_ =~ /Memcheck, a memory error detector/)
    {
	$inmemcheckheader = 1;
	$incallstack = $inmemstack = $insummary = 0;
	$blanklines       = 0;
	next;
    }

    if ($_ =~ /ERROR SUMMARY/)
    {
	$insummary = 1;
	$inmemcheckheader = $incallstack = $inmemstack = 0;
	$blanklines = 0;
    }

    next if ($insummary);
    
    if (!$_)
    {
	++$blanklines;
    }

    if ($inmemcheckheader)
    {
	if ($blanklines == 2)
	{
	    $inmemcheckheader = 0;
	    $incallstack = $inmemstack = 0;
	    $blanklines       = 0;
	}
	next;
    }

    if ($_ && !$incallstack && !$inmemstack)
    {
	$incallstack = 1;
	$message     = $_;
	@callstack   = ();
	@memstack    = ();
	next;
    }

    if ($_ =~ / Address/)
    {
	$incallstack = 0;
	$inmemstack  = 1;
	s/Address 0x[0-9A-F]*/Address/;
	s/[0-9,]* bytes inside a block of size [0-9,]*/inside a block/;
	push @memstack, $_;
	next;
    }

    if (($incallstack || $inmemstack) && $blanklines == 1)
    {
	$key = "$message;\t" . 
	    (join ";\t", @callstack);
	if (@memstack)
	{
	    $key .= "\n\t" . (join ";\t", @memstack);
	}

	if (!$stackhash{$key})
	{
	    $stackhash{$key} = 0;
	    #print "KEY NEW: $key\n";
	}
	$stackhash{$key} += 1;
	#print "KEY CNT: $key\n";
       
	$incallstack = $inmemstack = 0;
	$blanklines = 0;
	@callstack = ();
	@memstack = ();

	next;
    }

    $_ =~ s/ *(at|by) 0x[0-9A-F]+: //;

    if ($incallstack)
    {
	push @callstack, $_;
    }

    if ($inmemstack)
    {
	push @memstack, $_;
    }
	
}

foreach $key (sort {
    #$stackhash{$b} <=> $stackhash{$a} or $a cmp $b 
    $a cmp $b 
    } keys %stackhash)
{
    my $stack = $key;;
    $stack =~ s/;/\n/g;

    print "$stackhash{$key} $stack\n\n";
}
