#!/usr/bin/perl -w # # add2db.pl dbfile test < smatch.output # # Copyright 2003-2007 Michael Stefaniuc # # Takes the output of the smatch scripts and checks/adds them to the db file. # Format of the db file: # # comment # filename:fingerprint:linenr:test:status:comment # where: # filename = path of file relative to the root of the wine repository # fingerprint = smatch's finger print, output of get_func_pos() # linenr = linenr's where the error is produced # test = test that produced this. the subtest is added after a "/" to the test # status = status of the bug. one of NEW, UNKNOWN, BUG, NOTABUG, PATCH, FIXED # comment = anything use strict; # Variables ############ # Path to the root of the wine tree. Used to decide if it's a wine error. my $wine_path = "/j/s"; # global hash with all the entries my %globaldb = (); # database file my $dbfile = ""; # test from which this output is my $running_test = ""; # tests for which to import the comments too. Actual value is not important my %has_comment = ( "redundant_null_check" => '', "unfree-wine" => '', "crosscalls_WtoA" => '', "file_handles" => '', ); my $comment_f = 0; # statistics my %stats = ( "new" => 0, # new entries "old" => 0, # old entries still valid "notfound" => 0, # entries that couldn't be found in the # smatch output "other" => 0, # entries from other tests ); my $date = `date +%Y%m%d`; chomp($date); # Functions ############ sub usage { print "Usage: add2db.pl dbfile test < smatch.output\n"; } sub parse_dbfile() { open(my $fd, "<$dbfile") or return; while(<$fd>) { m/^#/ and do {next;}; m/^\s*$/ and do {next;}; if (tr/:/:/ < 5) { print(STDERR "WARN: couldn't parse in db file\n\t$_"); next; } my %rec = (); chomp; my @line = split(/:/, $_); $rec{"filename"} = shift(@line); $rec{"fingerprint"} = shift(@line); $rec{"linenr"} = shift(@line); $rec{"test"} = shift(@line); $rec{"status"} = shift(@line); if (defined($line[0])) { $rec{"comment"} = shift(@line); } else { $rec{"comment"} = ""; } # the comment may have contained a ':' while (defined($line[0])) { $rec{"comment"} .= ':' . shift(@line); } my $key = $rec{"filename"} . ":" . $rec{"fingerprint"}; $globaldb{$key} = \%rec; } } sub parse_smatch_output() { while (<>) { s/^$wine_path\/// and do { m/^(\S+) ((?:\d+ )+)(\w+\(\d+\)) (.*)$/ and do { my $filename = $1; my $linenr = $2; chop($linenr); $linenr =~ tr/ /-/; my $fingerprint = $3; my $key = "$filename:$fingerprint"; my $comment = $4; if ($comment_f) { $comment = ""; } if (!exists($globaldb{$key})) { my %rec = ( "filename" => $filename, "fingerprint" => $fingerprint, "linenr" => $linenr, "test" => $running_test, "status" => "NEW", "comment" => "" . $comment, "found" => 1, ); $stats{"new"}++; $globaldb{$key} = \%rec; } else { ${$globaldb{$key}}{"linenr"} = $linenr; if (${$globaldb{$key}}{"status"} eq "FIXED") { ${$globaldb{$key}}{"status"} = "NEW"; ${$globaldb{$key}}{"comment"} = "reopened"; $stats{"new"}++; } else { $stats{"old"}++; } ${$globaldb{$key}}{"found"} = 1; ${$globaldb{$key}}{"comment"} =~ s/\" . $$rec{"comment"}; $stats{"notfound"}++; } } else { $stats{"other"}++; } printf($fd "%s:%s:%s:%s:%s:%s\n", $$rec{"filename"}, $$rec{"fingerprint"}, $$rec{"linenr"}, $$rec{"test"}, $$rec{"status"}, $$rec{"comment"}); } } sub print_stats() { print("Test \"$running_test\" entries:\n"); printf(" new: %3d\n", $stats{"new"}); printf(" old: %3d\n", $stats{"old"}); printf(" not found: %3d\n", $stats{"notfound"}); printf("Other entries: %3d\n", $stats{"other"}); printf("Total entries: %3d\n", $stats{"new"} + $stats{"old"} + $stats{"notfound"} + $stats{"other"}); } # Main ####### if ($#ARGV + 1 != 2) { usage(); exit 1; } $dbfile = shift(@ARGV); $running_test = shift(@ARGV); my $base_test = $running_test; $base_test =~ s,/.+$,,; if (!exists($has_comment{$base_test})) { $comment_f = 1; } parse_dbfile(); parse_smatch_output(); write_db(); print_stats();