#!/usr/bin/env perl
#
# Usage: analyzeMemLeaksLog file ...
#
# Summarize the data in a memleaks log file.
#
# The input log file contains one entry for each program run.
# The output sums the total memory allocated, freed and leaked, as well as the maximum
# amount of memory leaked.  
# The output also lists the amount of memory leaked in each category, and in a separate
# list, the total amount of memory leaked by each program that leaks.

if ($#ARGV > 0) {
    $flag = shift @ARGV;
    if ($flag eq "-show_strings") {
      print STDERR "[Warning: '-show_strings' is deprecated (string leaks are shown by default)]\n\n";
    }
}

while (<>) {
    if (m/Compiler Command : .*\s(.*\.chpl )$/) {
        $program = $1;
    } elsif (m/Execution Command:.*tmp\.\.\-(.*?)\./) {
        $path = $1;
        $path =~ s/\-/\//g;
        $program = "$path/$program";
    } elsif (m/Leaked Memory Report/) {
        $memleaks = 1;
    } elsif (m/Allocated Now:\s*(\d*)$/) {
        $totalLeakedMemory += $1;
    } elsif (m/Allocation High Water Mark:\s*(\d*)$/) {
        $maximumAllocatedMemory += $1;
    } elsif (m/Sum of Allocations:\s*(\d*)$/) {
        $totalAllocatedMemory += $1;
    } elsif (m/Sum of Frees:\s*(\d*)$/) {
        $totalFreedMemory += $1;
    } elsif ($memleaks == 1) {
        if (m/==============================================================/) {
            $memleaks = 2;
        }
    } elsif ($memleaks == 2) {
        if (m/==============================================================/) {
            $memleaks = 3;
        }
    } elsif ($memleaks == 3) {
        if (m/==============================================================/) {
            $memleaks = 0;
        } elsif (m/(\d*)\s*(\d*)\s*(.*)$/) {
            $TP{$program} += $2;
            $TZ{$3} += $2; # table of size of leaked memory
            $TN{$3} += $1; # table of number of leaked allocations
        }
    }
}

printf("=================\n");
printf("Memory Statistics\n");
printf("==============================================================\n");
printf("Total Leaked Memory:        %12d\n", $totalLeakedMemory);
printf("Total Allocated Memory:     %12d\n", $totalAllocatedMemory);
printf("Total Freed Memory:         %12d\n", $totalFreedMemory);
printf("Maximum Allocated Memory:   %12d\n", $maximumAllocatedMemory);
printf("Number of Tests with Leaks: %12d\n", scalar keys %TP);
printf("==============================================================\n");
printf("\n");
printf("====================\n");
printf("Leaked Memory Report\n");
printf("==============================================================\n");
printf("Number of leaked allocations\n");
printf("              Total leaked memory (bytes)\n");
printf("                           Description of allocation\n");
printf("==============================================================\n");

@descs = sort { $TZ{$b} <=> $TZ{$a} } keys %TZ;

foreach $desc (@descs) {
    printf("%12d  %12d  $desc\n", $TN{$desc}, $TZ{$desc});
}

printf("==============================================================\n");
printf("\n");
printf("=======================\n");
printf("Memory Leaking Programs\n");
printf("==============================================================\n");
printf("Total leaked memory (bytes)\n");
printf("              Program\n");
printf("==============================================================\n");

@programs = sort { $TP{$b} <=> $TP{$a} } keys %TP;

foreach $program (@programs) {
    printf("%12d  $program\n", $TP{$program});
}

printf("==============================================================\n");
