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/vg_symtab2.c b/coregrind/vg_symtab2.c
index a05f130..eb6a3f3 100644
--- a/coregrind/vg_symtab2.c
+++ b/coregrind/vg_symtab2.c
@@ -2436,7 +2436,7 @@
      buf[n] = '\0';                                         \
    }
    UInt  lineno; 
-   UChar ibuf[20];
+   UChar ibuf[50];
    UInt  n = 0;
    static UChar buf_fn[VG_ERRTXT_LEN];
    static UChar buf_obj[VG_ERRTXT_LEN];
@@ -2445,29 +2445,62 @@
    Bool  know_objname = VG_(get_objname)(eip, buf_obj, VG_ERRTXT_LEN);
    Bool  know_srcloc  = VG_(get_filename_linenum)(eip, buf_srcloc,
                                                   VG_ERRTXT_LEN, &lineno);
-   VG_(sprintf)(ibuf,"0x%llx: ", (ULong)eip);
-   APPEND(ibuf);
-   if (know_fnname) { 
-      APPEND(buf_fn);
-      if (!know_srcloc && know_objname) {
-         APPEND(" (in ");
+
+   if (VG_(clo_xml)) {
+
+      /* Print in XML format, dumping in as much info as we know. */
+      APPEND("<frame>");
+      VG_(sprintf)(ibuf,"<ip>0x%llx</ip>", (ULong)eip);
+      APPEND(ibuf);
+      if (know_objname) {
+         APPEND("<obj>");
+         APPEND(buf_obj);
+         APPEND("</obj>");
+      }
+      if (know_fnname) {
+         APPEND("<fn>");
+         APPEND(buf_fn);
+         APPEND("</fn>");
+      }
+      if (know_srcloc) {
+         APPEND("<file>");
+         APPEND(buf_srcloc);
+         APPEND("</file>");
+         APPEND("<line>");
+         VG_(sprintf)(ibuf,"%d",lineno);
+         APPEND(ibuf);
+         APPEND("</line>");
+      }
+      APPEND("</frame>");
+
+   } else {
+
+      /* Print for humans to read */
+      VG_(sprintf)(ibuf,"0x%llx: ", (ULong)eip);
+      APPEND(ibuf);
+      if (know_fnname) { 
+         APPEND(buf_fn);
+         if (!know_srcloc && know_objname) {
+            APPEND(" (in ");
+            APPEND(buf_obj);
+            APPEND(")");
+         }
+      } else if (know_objname && !know_srcloc) {
+         APPEND("(within ");
          APPEND(buf_obj);
          APPEND(")");
+      } else {
+         APPEND("???");
       }
-   } else if (know_objname && !know_srcloc) {
-      APPEND("(within ");
-      APPEND(buf_obj);
-      APPEND(")");
-   } else {
-      APPEND("???");
-   }
-   if (know_srcloc) {
-      APPEND(" (");
-      APPEND(buf_srcloc);
-      APPEND(":");
-      VG_(sprintf)(ibuf,"%d",lineno);
-      APPEND(ibuf);
-      APPEND(")");
+      if (know_srcloc) {
+         APPEND(" (");
+         APPEND(buf_srcloc);
+         APPEND(":");
+         VG_(sprintf)(ibuf,"%d",lineno);
+         APPEND(ibuf);
+         APPEND(")");
+      }
+
    }
    return buf;