#!/usr/bin/perl -w
# vim:sw=4:et:ts=4:tw=72
# process-cad.pl - Perl script to process
#   seamonkey-crash-analysis-detailed reports.
# L. David Baron, 2001-08-18

use 5.004;
use strict;
use Getopt::Long;

my $logname = "seamonkey-crash-analysis-detailed";

GetOptions("date=s", "db=s");

($::opt_db && $::opt_date) || die qq{
usage: $0
  --date YYYYMMDD    The date of the $logname file.  [REQUIRED]
  --db <filename>    The database.  [REQUIRED]
};

require "dbfuncs.pl";

sub process_cad($$) {
    my ($tbfile, $db) = @_;
    open(TBFILE, "<".$tbfile);
    my $line;
    my $stacksig;
    while ($line = <TBFILE>) {
        if ($line =~ /^Stack Trace: $/) {
            # find the signature and the real signature out of the stack trace
            $line = <TBFILE>;
            $line = <TBFILE>;
            ($stacksig) = ($line =~ /^\s*(\S*).*\n$/);
            # chop off "()"
            if ($stacksig =~ /\(\)$/) {
                ($stacksig) = ($stacksig =~ /^(.*)\(\)$/);
            }
            while ($line =~ /^\t /) {
                $line = <TBFILE>;
            }

            # process all the reports
            while ($line && $line =~ /\S/) {
                # Get $stacksig again, since template parameters with
                # spaces mess up the previous one, and so we can get the
                # DLL offset (but not the full address!).
                ($stacksig) = ($line =~ /^\s*(.*) \S*$/);
                if (my ($subsig) =
                        ($stacksig =~ /(.* \+ 0x[0-9a-f]*) \(0x[0-9a-f]*\)/)) {
                    $stacksig = $subsig;
                }
                my $bbid;
                my %entry;
                $entry{stacksig} = $stacksig;
                if (!defined($entry{realsig})) {
                    $entry{realsig} = ""; # we can't do any better here
                }
                $line = <TBFILE>; # LXR for line
                $line = <TBFILE>;
                if (my ($builddate) = ($line =~ /^\tBuild: ([^ ]*).*\n$/)) {
                    $entry{builddate} = $builddate;
                } else {
                    die "Build field not found in \"$line\".";
                }
                $line = <TBFILE>;
                if (my ($platform) = ($line =~ /^\tOS: ([^ ]*).*\n$/)) {
                    $entry{platform} = $platform;
                } else {
                    die "OS field not found";
                }
                $line = <TBFILE>;
                unless (($bbid) = ($line =~ /^.*\?bbid=(.*)\n$/)) {
                    die "BBID not found";
                }
                $line = <TBFILE>; # StackTrace
                $line = <TBFILE>;
                while (($line =~ /^     \([0-9]*\).*\n$/)
                    && ($line = <TBFILE>)) {
                    # do nothing
                }
                $line = <TBFILE>;

                # Fix up stack signatures on Linux that end in "()".
                if ($entry{platform} eq "Linux"
                     && (($stacksig) = ($entry{stacksig} =~ /^(.*)\(\)$/))) {
                    $entry{stacksig} = $stacksig;
                }

                # add the report to the hash
                $db->{$bbid} = \%entry;
            }
        }
    }
}

my $database = {};  # nicer than |my %database;| and |\%database|
read_database($::opt_db, $database);
process_cad($logname . "/" . $::opt_date, $database);
write_database($::opt_db, $database);
