Change the filtering of helgrind's XML output.
New file helgrind/tests/filter_xml.
Update expected result for tc06_two_races_xml.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12077 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/helgrind/tests/filter_xml b/helgrind/tests/filter_xml
new file mode 100755
index 0000000..282de5c
--- /dev/null
+++ b/helgrind/tests/filter_xml
@@ -0,0 +1,156 @@
+#!/usr/bin/env perl
+
+#---------------------------------------------------------------------
+# Quick and dirty program to filter helgrind's XML output.
+# 
+# The script works line-by-line and is generally unaware of XML structure
+# and does not bother with issues of well-formedness.
+#
+# Consists of two parts
+# (1) Global match and replace (see PATTERNS below)
+# (2) Removal of stack frames
+#     Stack frames whose associated file name does not match any name in
+#     TOOL_FILES or in the list of files given on the command line
+#     will be discarded. For a sequence of one or more discarded frames
+#     a line   <frame>...</frame> will be inserted.
+#
+#---------------------------------------------------------------------
+
+use warnings;
+use strict;
+
+#---------------------------------------------------------------------
+# A list of files specific to the tool at hand. Line numbers in
+# these files will be removed from stack frames matching these files.
+#---------------------------------------------------------------------
+my @tool_files = ( "hg_intercepts.c", "vg_replace_malloc.c" );
+
+# List of patterns and replacement strings. 
+# Each pattern must identify a substring which will be replaced.
+my %patterns = (
+    "<pid>(.*)</pid>"       => "...",
+    "<ppid>(.*)</ppid>"     => "...",
+    "<time>(.*)</time>"     => "...",
+    "<obj>(.*)</obj>"       => "...",
+    "<dir>(.*)</dir>"       => "...",
+    "<exe>(.*)</exe>"       => "...",
+    "<tid>(.*)</tid>"       => "...",
+    "<unique>(.*)</unique>" => "...",
+    "thread #([0-9]+)"      => "x",
+    "0x([0-9a-zA-Z]+)"      => "........",
+    "Using Valgrind-([^\\s]*)"    => "X.Y.X",
+    "Copyright \\(C\\) ([0-9]{4}-[0-9]{4}).*" => "XXXX-YYYY"
+);
+
+# List of XML sections to be ignored.
+my %ignore_sections = (
+    "<errorcounts>" => "</errorcounts>",
+    "<suppcounts>"  => "</suppcounts>"
+);
+
+
+# If FILE matches any of the FILES return 1
+sub file_matches ($$) {
+    my ($file, $files) = @_;
+    my ($string, $qstring);
+
+    foreach $string (@$files) {
+        $qstring = quotemeta($string);
+        return 1 if ($file =~ /$qstring/);
+    }
+
+    return 0;
+}
+
+
+my $frame_buf = "";
+my ($file, $lineno, $in_frame, $keep_frame, $num_discarded, $ignore_line);
+
+$in_frame = $keep_frame = $num_discarded = $ignore_line = 0;
+
+line: 
+while (<STDIN>) {
+    my $line = $_;
+    chomp($line);
+
+# Check whether we're ignoring this piece of XML..
+    if ($ignore_line) {
+        foreach my $tag (keys %ignore_sections) {
+            if ($line =~ $ignore_sections{$tag}) {
+                print "$tag...$ignore_sections{$tag}\n";
+                $ignore_line = 0;
+                next line;
+            }
+        }
+    } else {
+        foreach my $tag (keys %ignore_sections) {
+            if ($line =~ $tag) {
+                $ignore_line = 1;
+            }
+        }
+    }
+
+    next if ($ignore_line);
+
+# OK. This line is not to be ignored.
+
+# Massage line by applying PATTERNS.
+    foreach my $key (keys %patterns) {
+        if ($line =~ $key) {
+                $line =~ s/$1/$patterns{$key}/g;
+        }
+    }
+
+# Handle frames
+    if ($in_frame) {
+        if ($line =~ /<\/frame>/) {
+            $frame_buf .= "$line\n";
+# The end of a frame
+            if ($keep_frame) {
+# First: If there were any preceding frames that were discarded
+#        print <frame>...</frame>
+                if ($num_discarded) {
+                    print "    <frame>...</frame>\n";
+                    $num_discarded = 0;
+                }
+# Secondly: Write out the frame itself
+                print "$frame_buf";
+            } else {
+# We don't want to write this frame
+                ++$num_discarded;
+            }
+            $in_frame = $keep_frame = 0;
+            $file = "";
+        } elsif ($line =~ /<file>(.*)<\/file>/) {
+            $frame_buf .= "$line\n";
+            $file = $1;
+            if (file_matches($file, \@tool_files) ||
+                file_matches($file, \@ARGV)) {
+                $keep_frame = 1;
+            }
+        } elsif ($line =~ /<line>(.*)<\/line>/) {
+# This code assumes that <file> always precedes <line>
+            $lineno = $1;
+            if (file_matches($file, \@tool_files)) {
+                $line =~ s/$1/.../;
+            }
+            $frame_buf .= "$line\n";
+        } else {
+            $frame_buf .= "$line\n";
+        }
+    } else {
+# not within frame
+        if ($line =~ /<\/stack>/) {
+            print "    <frame>...</frame>\n" if ($num_discarded);
+            $num_discarded = 0;
+        }
+        if ($line =~ /<frame>/)  {
+            $in_frame = 1;
+            $frame_buf = "$line\n";
+        } else {
+            print "$line\n";
+        }
+    }
+} 
+
+exit 0;
diff --git a/helgrind/tests/tc06_two_races_xml.stderr.exp b/helgrind/tests/tc06_two_races_xml.stderr.exp
index 25ee580..0fd5cd4 100644
--- a/helgrind/tests/tc06_two_races_xml.stderr.exp
+++ b/helgrind/tests/tc06_two_races_xml.stderr.exp
@@ -6,10 +6,10 @@
 <protocoltool>helgrind</protocoltool>
 
 <preamble>
-  <line>...</line>
-  <line>...</line>
-  <line>...</line>
-  <line>...</line>
+  <line>Helgrind, a thread error detector</line>
+  <line>Copyright (C) XXXX-YYYY, and GNU GPL'd, by OpenWorks LLP et al.</line>
+  <line>Using Valgrind-X.Y.X and LibVEX; rerun with -h for copyright info</line>
+  <line>Command: ./tc06_two_races</line>
 </preamble>
 
 <pid>...</pid>
@@ -17,9 +17,18 @@
 <tool>helgrind</tool>
 
 <args>
-  <vargv>...</vargv>
+  <vargv>
+    <exe>...</exe>
+    <arg>--command-line-only=yes</arg>
+    <arg>--memcheck:leak-check=no</arg>
+    <arg>--tool=helgrind</arg>
+    <arg>--read-var-info=yes</arg>
+    <arg>--xml=yes</arg>
+    <arg>--xml-fd=2</arg>
+    <arg>--log-file=/dev/null</arg>
+  </vargv>
   <argv>
-    <exe>./tc06_two_races</exe>
+    <exe>...</exe>
   </argv>
 </args>
 
@@ -36,22 +45,7 @@
 <announcethread>
   <hthreadid>2</hthreadid>
   <stack>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>clone</fn>
-      <dir>...</dir>
-      <file>clone.S</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>pthread_create@@GLIBC_2.2.5</fn>
-      <dir>...</dir>
-      <file>createthread.c</file>
-      <line>...</line>
-    </frame>
+    <frame>...</frame>
     <frame>
       <ip>0x........</ip>
       <obj>...</obj>
@@ -74,13 +68,13 @@
       <fn>main</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>26</line>
     </frame>
   </stack>
 </announcethread>
 
 <error>
-  <unique>0x........</unique>
+  <unique>...</unique>
   <tid>...</tid>
   <kind>Race</kind>
   <xwhat>
@@ -94,7 +88,7 @@
       <fn>main</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>31</line>
     </frame>
   </stack>
   <xauxwhat>
@@ -108,7 +102,7 @@
       <fn>child_fn</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>14</line>
     </frame>
     <frame>
       <ip>0x........</ip>
@@ -118,24 +112,14 @@
       <file>hg_intercepts.c</file>
       <line>...</line>
     </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>start_thread</fn>
-      <dir>...</dir>
-      <file>pthread_create.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-    </frame>
+    <frame>...</frame>
   </stack>
   <auxwhat>Location 0x........ is 0 bytes inside global var "unprot1"</auxwhat>
-  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>...</line> </xauxwhat>
+  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>9</line> </xauxwhat>
 </error>
 
 <error>
-  <unique>0x........</unique>
+  <unique>...</unique>
   <tid>...</tid>
   <kind>Race</kind>
   <xwhat>
@@ -149,7 +133,7 @@
       <fn>main</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>31</line>
     </frame>
   </stack>
   <xauxwhat>
@@ -163,7 +147,7 @@
       <fn>child_fn</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>14</line>
     </frame>
     <frame>
       <ip>0x........</ip>
@@ -173,24 +157,14 @@
       <file>hg_intercepts.c</file>
       <line>...</line>
     </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>start_thread</fn>
-      <dir>...</dir>
-      <file>pthread_create.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-    </frame>
+    <frame>...</frame>
   </stack>
   <auxwhat>Location 0x........ is 0 bytes inside global var "unprot1"</auxwhat>
-  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>...</line> </xauxwhat>
+  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>9</line> </xauxwhat>
 </error>
 
 <error>
-  <unique>0x........</unique>
+  <unique>...</unique>
   <tid>...</tid>
   <kind>Race</kind>
   <xwhat>
@@ -204,7 +178,7 @@
       <fn>main</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>35</line>
     </frame>
   </stack>
   <xauxwhat>
@@ -218,7 +192,7 @@
       <fn>child_fn</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>18</line>
     </frame>
     <frame>
       <ip>0x........</ip>
@@ -228,24 +202,14 @@
       <file>hg_intercepts.c</file>
       <line>...</line>
     </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>start_thread</fn>
-      <dir>...</dir>
-      <file>pthread_create.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-    </frame>
+    <frame>...</frame>
   </stack>
   <auxwhat>Location 0x........ is 0 bytes inside global var "unprot2"</auxwhat>
-  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>...</line> </xauxwhat>
+  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>9</line> </xauxwhat>
 </error>
 
 <error>
-  <unique>0x........</unique>
+  <unique>...</unique>
   <tid>...</tid>
   <kind>Race</kind>
   <xwhat>
@@ -259,7 +223,7 @@
       <fn>main</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>35</line>
     </frame>
   </stack>
   <xauxwhat>
@@ -273,7 +237,7 @@
       <fn>child_fn</fn>
       <dir>...</dir>
       <file>tc06_two_races.c</file>
-      <line>...</line>
+      <line>18</line>
     </frame>
     <frame>
       <ip>0x........</ip>
@@ -283,20 +247,10 @@
       <file>hg_intercepts.c</file>
       <line>...</line>
     </frame>
-    <frame>
-      <ip>0x........</ip>
-      <obj>...</obj>
-      <fn>start_thread</fn>
-      <dir>...</dir>
-      <file>pthread_create.c</file>
-      <line>...</line>
-    </frame>
-    <frame>
-      <ip>0x........</ip>
-    </frame>
+    <frame>...</frame>
   </stack>
   <auxwhat>Location 0x........ is 0 bytes inside global var "unprot2"</auxwhat>
-  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>...</line> </xauxwhat>
+  <xauxwhat><text>declared at tc06_two_races.c:9</text> <file>tc06_two_races.c</file> <line>9</line> </xauxwhat>
 </error>
 
 
@@ -305,24 +259,7 @@
   <time>...</time>
 </status>
 
-<errorcounts>
-  <pair>
-    <count>...</count>
-    <unique>0x........</unique>
-  </pair>
-  <pair>
-    <count>...</count>
-    <unique>0x........</unique>
-  </pair>
-  <pair>
-    <count>...</count>
-    <unique>0x........</unique>
-  </pair>
-  <pair>
-    <count>...</count>
-    <unique>0x........</unique>
-  </pair>
-</errorcounts>
+<errorcounts>...</errorcounts>
 
 <suppcounts>...</suppcounts>
 
diff --git a/helgrind/tests/tc06_two_races_xml.vgtest b/helgrind/tests/tc06_two_races_xml.vgtest
index 26f3e81..48c0528 100644
--- a/helgrind/tests/tc06_two_races_xml.vgtest
+++ b/helgrind/tests/tc06_two_races_xml.vgtest
@@ -1,3 +1,4 @@
 prog: tc06_two_races
 vgopts: --read-var-info=yes --xml=yes --xml-fd=2 --log-file=/dev/null
-stderr_filter: ../../memcheck/tests/filter_xml
+stderr_filter: ./filter_xml
+stderr_filter_args: tc06_two_races.c