First pass at adding ability for Memcheck to print all output in XML
form.  The relevant flag is --xml=yes.  Currently this only works with
Memcheck.

Specifying this flag fixes various other options relating to verbosity
and behaviour of the leak checker, so that the resulting output is in
a relatively fixed form suitable for parsing by GUIs.

Still to do:

* Add mechanism to show error counts
* Add regression test
* Document the resulting format



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3773 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index df05c20..79b2d15 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -251,11 +251,18 @@
 
 static void pp_Error ( Error* err, Bool printCount )
 {
-   if (printCount)
-      VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
-   if (err->tid > 0 && err->tid != last_tid_printed) {
-      VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
-      last_tid_printed = err->tid;
+   if (VG_(clo_xml)) {
+      VG_(message)(Vg_UserMsg, "<error>");
+      VG_(message)(Vg_UserMsg, "  <tid>%d</tid>", err->tid);
+   }
+
+   if (!VG_(clo_xml)) {
+      if (printCount)
+         VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
+      if (err->tid > 0 && err->tid != last_tid_printed) {
+         VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
+         last_tid_printed = err->tid;
+      }
    }
 
    switch (err->ekind) {
@@ -274,6 +281,9 @@
             VG_(tool_panic)("unhandled error type");
          }
    }
+
+   if (VG_(clo_xml))
+      VG_(message)(Vg_UserMsg, "</error>");
 }
 
 /* Figure out if we want to perform a given action for this error, possibly
@@ -629,6 +639,31 @@
 /*--- Exported fns                                         ---*/
 /*------------------------------------------------------------*/
 
+/* Show the used suppressions.  Returns False if no suppression
+   got used. */
+static Bool show_used_suppressions ( void )
+{
+   Supp  *su;
+   Bool  any_supp;
+
+   any_supp = False;
+   for (su = suppressions; su != NULL; su = su->next) {
+      if (su->count <= 0)
+         continue;
+      any_supp = True;
+      if (VG_(clo_xml)) {
+         VG_(message)(Vg_DebugMsg, 
+                      "<supp><count>%d</count><name>%s</name></supp>", 
+                      su->count, su->sname);
+      } else {
+         VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
+      }
+   }
+
+   return any_supp;
+}
+
+
 /* This is called not from generated code but from the scheduler */
 void VG_(show_all_errors) ( void )
 {
@@ -652,6 +687,15 @@
       if (su->count > 0)
          n_supp_contexts++;
    }
+
+   /* If we're printing XML, just show the suppressions and stop.
+    */
+   if (VG_(clo_xml)) {
+      (void)show_used_suppressions();
+      return;
+   }
+
+   /* We only get here if not printing XML. */
    VG_(message)(Vg_UserMsg,
                 "ERROR SUMMARY: "
                 "%d errors from %d contexts (suppressed: %d from %d)",
@@ -691,13 +735,7 @@
 
    if (n_supp_contexts > 0) 
       VG_(message)(Vg_DebugMsg, "");
-   any_supp = False;
-   for (su = suppressions; su != NULL; su = su->next) {
-      if (su->count > 0) {
-         any_supp = True;
-         VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
-      }
-   }
+   any_supp = show_used_suppressions();
 
    if (n_err_contexts > 0) {
       if (any_supp)