Commits

Anonymous committed 56e24eb

ERR: Adding xml.c back to ITK-1-4 branch after accidental remove.

  • Participants
  • Parent commits 2e6aaed
  • Branches ITK-1-4
  • Tags ITK-1-4-0, ITK-1-4-bp

Comments (0)

Files changed (2)

File GCC/gcc/cp/xml.c

+/*=========================================================================
+
+  Program:   GCC-XML
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+/* Organization of this source:
+   The entry point is do_xml_output(), which is called from the end of
+   finish_translation_unit() in semantics.c.
+   
+   xml_output_* functions are called to actually write the XML output.
+   
+   xml_print_*_attribute functions are used to write out the XML attributes
+   for common attribute name/pair values.
+*/
+
+/* Use GCC_XML_GCC_VERSION to modify code based on the version of GCC
+   in which we are being built.  This is set in the patched version of
+   cp-tree.h.  The format is 0xMMmmpp, where MM is the major version
+   number, mm is the minor version number, and pp is the patch level.
+   Examples:  gcc 3.0.4 = 0x030004
+              gcc 3.2.0 = 0x030200  */
+
+#include "config.h"
+#include "system.h"
+#include "sys/stat.h"
+
+/* GCC 3.4 and above need these headers here.  The GCC-XML patches for
+   these versions define GCC_XML_GCC_VERSION in config.h instead of
+   cp-tree.h, so the macro is available here.  The patches for older
+   versions may provide the macro in cp-tree.h, but in that case
+   we don't need these headers anyway.  */
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030400)
+# include "coretypes.h"
+# include "tm.h"
+#endif
+
+#include "tree.h"
+#include "cp-tree.h"
+#include "decl.h"
+#include "rtl.h"
+#include "varray.h"
+
+#include "splay-tree.h"
+
+/* Decide how to call cp_error.  */
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030100)
+# define XML_CP_ERROR cp_error_at
+#else
+# define XML_CP_ERROR cp_error
+# define XML_HAVE_FAKE_STD_NODE
+#endif
+
+/* Decide how to get the attributes node from a declaration.  */
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030100)
+# define GCC_XML_DECL_ATTRIBUTES(n) DECL_ATTRIBUTES(n)
+#else
+# define GCC_XML_DECL_ATTRIBUTES(n) DECL_MACHINE_ATTRIBUTES(n)
+#endif
+
+/* Decide how to access base classes.  */
+#if !defined(GCC_XML_GCC_VERSION) || (GCC_XML_GCC_VERSION < 0x030400)
+# define XML_PRE_3_4_TREE_VIA_PUBLIC
+#endif
+
+/* A "dump node" corresponding to a particular tree node.  */
+typedef struct xml_dump_node
+{
+  /* The index for the node.  */
+  unsigned int index;
+
+  /* Whether the node is complete.  */
+  unsigned int complete;
+} *xml_dump_node_p;
+
+/* A node on the queue of dump nodes.  */
+typedef struct xml_dump_queue
+{
+  /* The queued tree node.  */
+  tree tree_node;
+
+  /* The corresponding dump node.  */
+  xml_dump_node_p dump_node;
+
+  /* The next node in the queue.  */
+  struct xml_dump_queue *next;
+} *xml_dump_queue_p;
+
+/* A node on the queue of file names.  */
+typedef struct xml_file_queue
+{
+  /* The queued file name.  */
+  splay_tree_node tree_node;
+
+  /* The next node in the queue.  */
+  struct xml_file_queue *next;
+} *xml_file_queue_p;
+
+/* Dump control structure.  A pointer one instance of this is passed
+   to nearly every function.  */
+typedef struct xml_dump_info
+{
+  /* Output file stream of dump.  */
+  FILE* file;
+  
+  /* Which pass of the loop we are doing (1=complete or 0=incomplete).  */
+  int require_complete;
+  
+  /* Next available index to identify node.  */
+  unsigned int next_index;
+
+  /* The first node in the queue of complete nodes.  */
+  xml_dump_queue_p queue;
+
+  /* The last node in the queue of complete nodes.  */
+  xml_dump_queue_p queue_end;
+  
+  /* List of free xml_dump_queue nodes.  */
+  xml_dump_queue_p queue_free;
+  
+  /* All nodes that have been encountered.  */
+  splay_tree dump_nodes;
+
+  /* Index of the next available file queue position.  */
+  unsigned int file_index;
+
+  /* The first file in the queue of filenames.  */
+  xml_file_queue_p file_queue;
+
+  /* The last file in the queue of filenames.  */
+  xml_file_queue_p file_queue_end;
+
+  /* All files that have been queued.  */
+  splay_tree file_nodes;
+} *xml_dump_info_p;
+
+/* Return non-zero if the given _DECL is an internally generated decl.  */
+#define DECL_INTERNAL_P(d) (DECL_SOURCE_LINE(d) == 0)
+
+void do_xml_output PARAMS ((const char*));
+
+static int xml_add_node PARAMS((xml_dump_info_p, tree, int));
+static void xml_dump PARAMS((xml_dump_info_p));
+static int xml_queue_incomplete_dump_nodes PARAMS((splay_tree_node, void*));
+static void xml_dump_tree_node PARAMS((xml_dump_info_p, tree, xml_dump_node_p));
+static void xml_dump_files PARAMS((xml_dump_info_p));
+
+static void xml_add_start_nodes PARAMS((xml_dump_info_p, const char*));
+
+static const char* xml_get_encoded_string PARAMS ((tree));
+static const char* xml_get_encoded_string_from_string PARAMS ((const char*));
+static tree xml_get_encoded_identifier_from_string PARAMS ((const char*));
+
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030100)
+# include "diagnostic.h"
+#else
+extern int errorcount;
+#endif
+
+/* Switch to 1 to enable debugging of dump node selection.  */
+#if 0
+# define xml_add_node(xdi, node, complete)                                    \
+   (fprintf(stderr, "Adding node at line %d\n", __LINE__),                    \
+    xml_add_node(xdi, node, complete))
+#endif
+
+/* Main XML output function.  Called by parser at the end of a translation
+   unit.  Walk the entire translation unit starting at the global
+   namespace.  Output all declarations.  */
+void
+do_xml_output (const char* filename)
+{
+  FILE* file;
+  struct xml_dump_info xdi;
+  
+  /* Do not dump if errors occurred during parsing.  */
+  if(errorcount)
+    {
+    /* Delete any existing output file.  */
+    unlink(filename);
+    return;
+    }
+  
+  /* Open the XML output file.  */
+  file = fopen (filename, "w");
+  if (!file)
+    {
+    XML_CP_ERROR ("could not open xml-dump file `%s'", filename);
+    return;
+    }
+  
+  /* Prepare dump.  */
+  xdi.file = file;
+  xdi.queue = 0;
+  xdi.queue_end = 0;
+  xdi.queue_free = 0;
+  xdi.next_index = 1;
+  xdi.dump_nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
+                                   (splay_tree_delete_value_fn) &free);
+  xdi.file_queue = 0;
+  xdi.file_queue_end = 0;
+  xdi.file_index = 0;
+  xdi.file_nodes = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+  xdi.require_complete = 1;
+  
+  /* Add the starting nodes for the dump.  */
+  if (flag_xml_start)
+    {
+    /* Use the specified starting locations.  */
+    xml_add_start_nodes (&xdi, flag_xml_start);
+    }
+  else
+    {
+    /* No start specified.  Use global namespace.  */
+    xml_add_node (&xdi, global_namespace, 1);
+
+    /* Also add std namespace because it is not always referenced.  */
+    if(std_node)
+      {
+      xml_add_node (&xdi, std_node, 1);
+      }
+    }
+  
+  /* Start dump.  */
+  fprintf (file, "<?xml version=\"1.0\"?>\n");
+#if defined(GCCXML_VERSION_FULL)
+  fprintf (file, "<GCC_XML version=\"" GCCXML_VERSION_FULL "\">\n");
+#else
+  fprintf (file, "<GCC_XML>\n");
+#endif
+  
+  /* Dump the complete nodes.  */
+  xml_dump (&xdi);  
+  
+  /* Queue all the incomplete nodes.  */
+  splay_tree_foreach (xdi.dump_nodes,
+                      &xml_queue_incomplete_dump_nodes, &xdi);
+  
+  /* Dump the incomplete nodes.  */
+  xdi.require_complete = 0;
+  xml_dump (&xdi);
+  
+  /* Dump the filename queue.  */
+  xml_dump_files (&xdi);
+  
+  /* Finish dump.  */
+  fprintf (file, "</GCC_XML>\n");
+  
+  /* Clean up.  */
+  {
+  xml_dump_queue_p dq = xdi.queue_free;
+  while(dq)
+    {
+    xml_dump_queue_p nq = dq->next;
+    free(dq);
+    dq = nq;
+    }
+  }
+  splay_tree_delete (xdi.dump_nodes);
+  splay_tree_delete (xdi.file_nodes);
+  fclose (file);
+}
+
+/* Return the xml_dump_node corresponding to tree node T.  If none exists,
+   one will be created with an index of 0.  */
+static xml_dump_node_p
+xml_get_dump_node(xml_dump_info_p xdi, tree t)
+{
+  /* See if the node has already been inserted.  */
+  splay_tree_node n = splay_tree_lookup (xdi->dump_nodes, (splay_tree_key) t);
+  if(!n)
+    {
+    /* Need to add the node, create it.  */
+    xml_dump_node_p v =
+      (xml_dump_node_p) xmalloc (sizeof (struct xml_dump_node));
+
+    /* Initialize it.  */
+    v->index = 0;
+    v->complete = 0;
+
+    /* Insert the node.  */
+    n = splay_tree_insert (xdi->dump_nodes, (splay_tree_key) t,
+                           (splay_tree_value) v);
+    }
+
+  /* Return a pointer to the dump node.  */
+  return (xml_dump_node_p)n->value;
+}
+
+/* Queue the given tree node for output as a complete node.  */
+static void
+xml_queue_node (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  xml_dump_queue_p dq;
+  
+  /* Obtain a new queue node.  */
+  if (xdi->queue_free)
+    {
+    dq = xdi->queue_free;
+    xdi->queue_free = dq->next;
+    }
+  else
+    {
+    dq = (xml_dump_queue_p) xmalloc (sizeof (struct xml_dump_queue));
+    }
+  
+  /* Point the queue node at its corresponding tree node and dump node.  */
+  dq->next = 0;
+  dq->tree_node = t;
+  dq->dump_node = dn;
+  
+  /* Add it to the end of the queue.  */
+  if (!xdi->queue_end)
+    {
+    xdi->queue = dq;
+    }
+  else
+    {
+    xdi->queue_end->next = dq;
+    }
+  xdi->queue_end = dq;
+}
+
+/* Add tree node N to those encountered.  Return its index.  */
+static int
+xml_add_node_real (xml_dump_info_p xdi, tree n, int complete)
+{
+  /* Get the dump node for this tree node.  */
+  xml_dump_node_p dn = xml_get_dump_node (xdi, n);
+  if (dn->index)
+    {
+    /* Node was already encountered.  See if it is now complete.  */
+    if(complete && !dn->complete)
+      {
+      /* Node is now complete, but wasn't before.  Queue it.  */
+      dn->complete = 1;
+      xml_queue_node (xdi, n, dn);
+      }
+    /* Return node's index.  */
+    return dn->index;
+    }
+  
+  /* This is a new node.  Assign it an index.  */
+  dn->index = xdi->next_index++;
+  dn->complete = complete;
+  if(complete || !xdi->require_complete)
+    {
+    /* Node is complete.  Queue it.  */
+    xml_queue_node (xdi, n, dn);
+    }
+  
+  if(!xdi->require_complete && complete)
+    {
+    XML_CP_ERROR ("XML dump bug: complete node added during incomplete phase.\n");
+    }
+
+  /* Return node's index.  */
+  return dn->index;
+}
+
+/* Called for each node in the splay tree of dump nodes.  Queues
+   a dump node if it is incomplete.  */
+int xml_queue_incomplete_dump_nodes (splay_tree_node n, void* in_xdi)
+{
+  tree key = (tree)n->key;
+  xml_dump_node_p dn = (xml_dump_node_p)n->value;
+  xml_dump_info_p xdi = (xml_dump_info_p)in_xdi;
+  if (!dn->complete)
+    {
+    xml_queue_node (xdi, key, dn);
+    }
+  return 0;
+}
+
+/* The xml dump loop.  */
+void
+xml_dump (xml_dump_info_p xdi)
+{
+  /* Dump the complete nodes.  */
+  while(xdi->queue)
+    {
+    /* Get the next queue entry.  */
+    xml_dump_queue_p dq = xdi->queue;
+    tree t = dq->tree_node;
+    xml_dump_node_p dn = dq->dump_node;
+    
+    /* Remove the entry from the queue.  */
+    xdi->queue = dq->next;
+    if(!xdi->queue)
+      {
+      xdi->queue_end = 0;
+      }
+    
+    /* Put the entry on the free list.  */
+    dq->next = xdi->queue_free;
+    xdi->queue_free = dq;
+    
+    /* Dump the node.  */
+    xml_dump_tree_node(xdi, t, dn);
+    }
+}
+
+/* Queue a filename for later output.  If the file has already been
+   queued, it is not queued again.  In either case, the queue index
+   assigned to the file is returned.  */
+static unsigned int
+xml_queue_file (xml_dump_info_p xdi, const char* filename)
+{
+  tree t = xml_get_encoded_identifier_from_string (filename);
+  
+  /* See if we've already queued this file.  */
+  splay_tree_node n = splay_tree_lookup (xdi->file_nodes, (splay_tree_key) t);
+  if (n)
+    {
+    /* File was already queued.  Return its index.  */
+    return n->value;
+    }
+  else
+    {
+    /* File needs to be queued.  */
+    xml_file_queue_p fq;
+
+    /* Assign the next available index.  */
+    unsigned int index = xdi->file_index++;
+
+    /* Obtain a new queue node.  */
+    fq = (xml_file_queue_p) xmalloc (sizeof (struct xml_file_queue));
+
+    /* Create a new entry in the splay-tree.  */
+    fq->tree_node = splay_tree_insert (xdi->file_nodes, (splay_tree_key) t, 
+                                       (splay_tree_value) index);
+    
+    /* Add it to the end of the queue.  */
+    fq->next = 0;
+    if (!xdi->file_queue_end)
+      {
+      xdi->file_queue = fq;
+      }
+    else
+      {
+      xdi->file_queue_end->next = fq;
+      }
+    xdi->file_queue_end = fq;
+    
+    /* Return the index.  */
+    return index;
+    }
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Print the XML attribute location="fid:line" for the given decl.  */
+static void
+xml_print_location_attribute (xml_dump_info_p xdi, tree d)
+{
+  unsigned int source_file = xml_queue_file (xdi, DECL_SOURCE_FILE (d));
+  unsigned int source_line = DECL_SOURCE_LINE (d);
+  
+  fprintf (xdi->file, " location=\"f%d:%d\"", source_file, source_line);
+}
+
+/* Print the XML attribute endline="line" for the given COMPOUND_STMT.  */
+static void
+xml_print_endline_attribute (xml_dump_info_p xdi, tree stmt)
+{
+  fprintf (xdi->file, " endline=\"%d\"", STMT_LINENO(stmt));
+}
+
+/* Print the XML attribute id="..." for the given node.  */
+static void
+xml_print_id_attribute (xml_dump_info_p xdi, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, " id=\"_%d\"", dn->index);
+}
+
+/* Print the XML attribute name="..." for the given node.  */
+static void
+xml_print_name_attribute (xml_dump_info_p xdi, tree n)
+{
+  const char* name = xml_get_encoded_string (n);
+  fprintf (xdi->file, " name=\"%s\"", name);
+}
+
+/* Print the XML attribute type="..." for the given type.  If the type
+   has cv-qualifiers, they are appended to the type's id as single
+   characters (c=const, v=volatile, r=restrict).  */
+static void
+xml_print_type_attribute (xml_dump_info_p xdi, tree t, int complete)
+{
+  const char* ch_const = "";
+  const char* ch_volatile = "";
+  const char* ch_restrict = "";
+  int id = xml_add_node (xdi, TYPE_MAIN_VARIANT(t), complete);
+  if (CP_TYPE_CONST_P (t)) { ch_const = "c"; }
+  if (CP_TYPE_VOLATILE_P (t)) { ch_volatile = "v"; }
+  if (CP_TYPE_RESTRICT_P (t)) { ch_restrict = "r"; }  
+  fprintf (xdi->file, " type=\"_%d%s%s%s\"",
+           id, ch_const, ch_volatile, ch_restrict);
+}
+
+/* Print the XML attribute returns="tid" for the given function type.  */
+static void
+xml_print_returns_attribute (xml_dump_info_p xdi, tree t, int complete)
+{
+  const char* ch_const = "";
+  const char* ch_volatile = "";
+  const char* ch_restrict = "";
+  int id = xml_add_node (xdi, TYPE_MAIN_VARIANT(t), complete);
+  if (CP_TYPE_CONST_P (t)) { ch_const = "c"; }
+  if (CP_TYPE_VOLATILE_P (t)) { ch_volatile = "v"; }
+  if (CP_TYPE_RESTRICT_P (t)) { ch_restrict = "r"; }  
+  fprintf (xdi->file, " returns=\"_%d%s%s%s\"",
+           id, ch_const, ch_volatile, ch_restrict);
+}
+
+/* Print XML attribute basetype="..." with the given type.  */
+static void
+xml_print_base_type_attribute (xml_dump_info_p xdi, tree t, int complete)
+{
+  int id = xml_add_node (xdi, t, complete);
+  fprintf (xdi->file, " basetype=\"_%d\"", id);
+}
+
+/* Print the XML attribute context="..." for the given node.  */
+static void
+xml_print_context_attribute (xml_dump_info_p xdi, tree n)
+{
+  if(n != global_namespace)
+    {
+    fprintf (xdi->file, " context=\"_%d\"",
+             xml_add_node (xdi, CP_DECL_CONTEXT (n), 0));
+    }
+}
+
+/* Print the XML attribute access="..." for the given decl.  */
+static void
+xml_print_access_attribute (xml_dump_info_p xdi, tree d)
+{
+  tree context = CP_DECL_CONTEXT (d);
+  if (context && TYPE_P(context))
+    {
+    if (TREE_PRIVATE (d))
+      {
+      fprintf (xdi->file, " access=\"private\"");
+      }
+    else if (TREE_PROTECTED (d))
+      {
+      fprintf (xdi->file, " access=\"protected\"");
+      }
+    else
+      {
+      /* Default for access attribute is public.  */
+      /* fprintf (xdi->file, " access=\"public\"");  */
+      }
+    }
+}
+
+/* Print XML attribute const="1" for const methods.  */
+static void
+xml_print_const_method_attribute (xml_dump_info_p xdi, tree fd)
+{  
+  if (DECL_CONST_MEMFUNC_P (fd))
+    {
+    fprintf (xdi->file, " const=\"1\"");
+    }
+}
+
+/* Print XML attribute static="1" for static methods.  */
+static void
+xml_print_static_method_attribute (xml_dump_info_p xdi, tree fd)
+{
+  if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (fd))
+    {
+    fprintf (xdi->file, " static=\"1\"");
+    }
+}
+
+/* Print XML attributes virtual="" and pure_virtual="" for a decl.  */
+static void
+xml_print_virtual_method_attributes (xml_dump_info_p xdi, tree d)
+{  
+  if (DECL_VIRTUAL_P (d))
+    {
+    fprintf (xdi->file, " virtual=\"1\"");
+    }
+  
+  if (DECL_PURE_VIRTUAL_P (d))
+    {
+    fprintf (xdi->file, " pure_virtual=\"1\"");
+    }
+}
+
+/* Print the XML attribute extern="1" if the given decl is external.  */
+static void
+xml_print_extern_attribute (xml_dump_info_p xdi, tree d)
+{
+  if (DECL_EXTERNAL (d))
+    {
+    fprintf (xdi->file, " extern=\"1\"");
+    }
+}
+
+/* Print the XML attribute extern="1" if the given decl is external.  */
+static void
+xml_print_function_extern_attribute (xml_dump_info_p xdi, tree fd)
+{
+  if (DECL_REALLY_EXTERN (fd))
+    {
+    fprintf (xdi->file, " extern=\"1\"");
+    }
+}
+
+/* Print XML attribute for a default argument.  */
+static void
+xml_print_default_argument_attribute (xml_dump_info_p xdi, tree t)
+{
+  const char* value;
+
+  switch (TREE_CODE(t))
+    {
+    case CAST_EXPR:
+      value = xml_get_encoded_string_from_string ("<gccxml-cast-expr>");
+      break;
+    default:
+      value = xml_get_encoded_string_from_string (expr_as_string (t, 0));
+      break;
+    };
+  fprintf (xdi->file, " default=\"%s\"", value);
+}
+
+/* Print XML attribute init="..." for a variable initializer.  */
+static void
+xml_print_init_attribute (xml_dump_info_p xdi, tree t)
+{
+  const char* value;
+  
+  if (!t || (t == error_mark_node)) return;
+  
+  value = xml_get_encoded_string_from_string (expr_as_string (t, 0));
+  fprintf (xdi->file, " init=\"%s\"", value);
+}
+
+/* Print the XML attribute incomplete="..." for the given type.  */
+static void
+xml_print_incomplete_attribute (xml_dump_info_p xdi, tree t)
+{
+  if (!COMPLETE_TYPE_P (t))
+    {
+    fprintf (xdi->file, " incomplete=\"1\"");
+    }
+}
+
+/* Print the XML attribute abstract="..." for the given type.  */
+static void
+xml_print_abstract_attribute (xml_dump_info_p xdi, tree t)
+{
+  if (CLASSTYPE_PURE_VIRTUALS (t) != 0)
+    {
+    fprintf (xdi->file, " abstract=\"1\"");
+    }
+}
+
+/* Print XML empty tag for an ellipsis at the end of an argument list.  */
+static void
+xml_output_ellipsis (xml_dump_info_p xdi)
+{
+  fprintf (xdi->file,
+           "    <Ellipsis/>\n");
+}
+
+/* Print XML attributes min="0" max="..." for an array type.  */
+static void
+xml_print_array_attributes (xml_dump_info_p xdi, tree at)
+{
+  const char* length = "";
+  
+  if (TYPE_DOMAIN (at))
+    length = xml_get_encoded_string_from_string (
+      expr_as_string (TYPE_MAX_VALUE (TYPE_DOMAIN (at)), 0));
+
+  fprintf (xdi->file, " min=\"0\" max=\"%s\"", length);
+}
+
+/* Print XML attribute listing types that this type can throw.  */
+static void
+xml_print_throw_attribute (xml_dump_info_p xdi, tree ft, int complete)
+{
+  tree raises = TYPE_RAISES_EXCEPTIONS (ft);
+  if(raises)
+    {
+    fprintf (xdi->file, " throw=\"");
+    if(TREE_VALUE (raises))
+      {
+      for (;
+           raises != NULL_TREE; raises = TREE_CHAIN (raises))
+        {
+        tree t = TREE_VALUE (raises);
+        const char* ch_const = "";
+        const char* ch_volatile = "";
+        const char* ch_restrict = "";
+        int id = xml_add_node (xdi, TYPE_MAIN_VARIANT (t), complete);
+        if (CP_TYPE_CONST_P (t)) { ch_const = "c"; }
+        if (CP_TYPE_VOLATILE_P (t)) { ch_volatile = "v"; }
+        if (CP_TYPE_RESTRICT_P (t)) { ch_restrict = "r"; }
+        fprintf (xdi->file, "%s_%d%s%s%s",
+                 (raises == TYPE_RAISES_EXCEPTIONS (ft))?"":" ",
+                 id, ch_const, ch_volatile, ch_restrict);
+        }
+      }
+    fprintf (xdi->file, "\"");
+    }
+}
+
+/* Print XML attribute listing the contents of the __attribute__ node
+   given.  */
+static void
+xml_print_attributes_attribute (xml_dump_info_p xdi, tree attributes1,
+                                tree attributes2)
+{
+  if(attributes1 || attributes2)
+    {
+    const char* space = "";
+    tree attribute;
+    fprintf(xdi->file, " attributes=\"");
+    for(attribute = attributes1; attribute;
+        attribute = TREE_CHAIN(attribute))
+      {
+      fprintf(xdi->file, "%s%s", space,
+              xml_get_encoded_string(TREE_PURPOSE (attribute)));
+      space = " ";
+      }
+    for(attribute = attributes2; attribute;
+        attribute = TREE_CHAIN(attribute))
+      {
+      fprintf(xdi->file, "%s%s", space,
+              xml_get_encoded_string(TREE_PURPOSE (attribute)));
+      space = " ";
+      }
+    fprintf(xdi->file, "\"");
+    }
+}
+
+/* Print XML empty tag describing an unimplemented TREE_CODE that has been
+   encountered.  */
+static void
+xml_output_unimplemented (xml_dump_info_p xdi, tree t, xml_dump_node_p dn,
+                          const char* where)
+{
+  int tree_code = TREE_CODE (t);
+  fprintf (xdi->file,
+           "  <Unimplemented id=\"_%d\" tree_code=\"%d\""
+           " tree_code_name=\"%s\" node=\"%p\"",
+           (dn? dn->index : 0),
+           tree_code, tree_code_name [tree_code], t);
+  if (where)
+    {
+    fprintf (xdi->file, " function=\"%s\"", where);
+    }
+  fprintf (xdi->file, "/>\n");
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Dump a NAMESPACE_DECL.  */
+static void
+xml_output_namespace_decl (xml_dump_info_p xdi, tree ns, xml_dump_node_p dn)
+{
+  /* Only walk a real namespace.  */
+  if (!DECL_NAMESPACE_ALIAS (ns))
+    {
+    fprintf (xdi->file, "  <Namespace");
+    xml_print_id_attribute (xdi, dn);
+    xml_print_name_attribute (xdi, DECL_NAME (ns));
+    xml_print_context_attribute (xdi, ns);
+    xml_print_attributes_attribute (xdi, GCC_XML_DECL_ATTRIBUTES(ns), 0);
+    
+    /* If complete dump, walk the namespace.  */
+    if(dn->complete)
+      {
+      tree cur_decl;
+      fprintf (xdi->file, " members=\"");
+      for (cur_decl = cp_namespace_decls(ns); cur_decl;
+           cur_decl = TREE_CHAIN (cur_decl))
+        {
+        if (!DECL_INTERNAL_P (cur_decl))
+          {
+          int id = xml_add_node (xdi, cur_decl, 1);
+          if (id)
+            {
+            fprintf (xdi->file, "_%d ", id);
+            }
+          }
+        }
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030300)
+      // Add child namespaces
+      for (cur_decl = cp_namespace_namespaces(ns); cur_decl;
+           cur_decl = TREE_CHAIN (cur_decl))
+        {
+        if (!DECL_INTERNAL_P (cur_decl))
+          {
+          int id = xml_add_node (xdi, cur_decl, 1);
+          if (id)
+            {
+            fprintf (xdi->file, "_%d ", id);
+            }
+          }
+        }
+#endif
+      
+      fprintf (xdi->file, "\"");
+      }
+    
+    fprintf (xdi->file, "/>\n");
+    }
+  /* If it is a namespace alias, just indicate that.  */
+  else
+    {
+    tree real_ns = ns;
+    /* Find the real namespace.  */
+    while (DECL_NAMESPACE_ALIAS (real_ns))
+      {
+      real_ns = DECL_NAMESPACE_ALIAS (real_ns);
+      }
+    
+    fprintf (xdi->file, "  <NamespaceAlias");
+    xml_print_id_attribute (xdi, dn);
+    xml_print_name_attribute (xdi, DECL_NAME (ns));
+    xml_print_context_attribute (xdi, ns);
+    fprintf (xdi->file, " namespace=\"_%d\"",
+             xml_add_node (xdi, real_ns, 0));
+    fprintf (xdi->file, "/>\n");
+    }
+}
+
+/* Output for a typedef.  The name and associated type are output.  */
+static void
+xml_output_typedef (xml_dump_info_p xdi, tree td, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <Typedef");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_name_attribute (xdi, DECL_NAME (td));
+  
+  /* Get the original type out of the typedef, if any.  */
+  if (DECL_ORIGINAL_TYPE (td))
+    {
+    xml_print_type_attribute (xdi, DECL_ORIGINAL_TYPE (td), dn->complete);
+    }
+  else
+    {
+    xml_print_type_attribute (xdi, TREE_TYPE (td), dn->complete);
+    }
+  
+  xml_print_context_attribute (xdi, td);
+  xml_print_location_attribute (xdi, td);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for a PARM_DECL / TREE_LIST corresponding to a function argument.  */
+static void
+xml_output_argument (xml_dump_info_p xdi, tree pd, tree tl, int complete)
+{
+  /* Don't process any compiler-generated arguments.  These occur for
+     things like constructors of classes with virtual inheritance.  */
+  if (pd && DECL_ARTIFICIAL (pd)) return;
+  
+  fprintf (xdi->file, "    <Argument");
+  if(pd && DECL_NAME (pd))
+    {
+    xml_print_name_attribute (xdi, DECL_NAME (pd));
+    }
+  
+  if (pd && DECL_ARG_TYPE_AS_WRITTEN (pd))
+    {
+    xml_print_type_attribute (xdi, DECL_ARG_TYPE_AS_WRITTEN (pd), complete);
+    }
+  else if (pd && TREE_TYPE (pd))
+    {
+    xml_print_type_attribute (xdi, TREE_TYPE (pd), complete);
+    }
+  else
+    {
+    xml_print_type_attribute (xdi, TREE_VALUE (tl), complete);
+    }
+  
+  if (TREE_PURPOSE (tl))
+    {
+    xml_print_default_argument_attribute (xdi, TREE_PURPOSE (tl));
+    }
+
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Lookup the real name of an operator whose ansi_opname or ansi_assopname
+   is NAME.  */
+static tree
+xml_reverse_opname_lookup (tree name)
+{
+  static const char* unknown_operator = "{unknown operator}";
+  int i;
+
+  /* Make sure we know about this internal name.  */
+  if (!IDENTIFIER_OPNAME_P (name))
+    return get_identifier (unknown_operator);
+
+  /* Search the list of internal anmes */
+  for (i=0; i < LAST_CPLUS_TREE_CODE ; ++i)
+    {
+    if (ansi_opname(i) == name)
+      return get_identifier (operator_name_info[i].name);
+    else if (ansi_assopname(i) == name)
+      return get_identifier (assignment_operator_name_info[i].name);
+    }
+  
+  return get_identifier (unknown_operator);
+}
+
+/* Output for a FUNCTION_DECL.  */
+static void
+xml_output_function_decl (xml_dump_info_p xdi, tree fd, xml_dump_node_p dn)
+{
+  tree arg;
+  tree arg_type;
+  const char* tag;
+  tree name = DECL_NAME (fd);
+  tree body = DECL_SAVED_TREE(fd);
+  int do_returns = 0;
+  int do_access = 0;
+  int do_const = 0;
+  int do_virtual = 0;
+  int do_static = 0;
+
+  /* Print out the begin tag for this type of function.  */
+  if (DECL_CONSTRUCTOR_P (fd))
+    {
+    /* A class constructor.  */
+    tag = "Constructor"; do_access = 1;
+    }
+  else if (DECL_DESTRUCTOR_P (fd))
+    {
+    /* A class destructor.  */
+    tag = "Destructor"; do_access = 1; do_virtual = 1;
+    }
+  else if (DECL_OVERLOADED_OPERATOR_P (fd))
+    {
+    if (DECL_CONV_FN_P (fd))
+      {
+      /* A type-conversion operator in a class.  */
+      tag = "Converter";
+      do_returns = 1; do_access = 1; do_const = 1; do_virtual = 1;
+      }
+    else
+      {
+      if (DECL_FUNCTION_MEMBER_P (fd))
+        {
+        /* An operator in a class.  */
+        tag = "OperatorMethod";
+        name = xml_reverse_opname_lookup (DECL_NAME (fd));
+        do_returns = 1; do_access = 1; do_const = 1; do_virtual = 1;
+        do_static = 1;
+        }
+      else
+        {
+        /* An operator in a namespace.  */
+        tag = "OperatorFunction";
+        name = xml_reverse_opname_lookup (DECL_NAME (fd));
+        do_returns = 1;
+        }
+      }
+    }
+  else
+    {
+    if (DECL_FUNCTION_MEMBER_P (fd))
+      {
+      /* A member of a class.  */
+      tag = "Method"; do_returns = 1; do_access = 1; do_const = 1;
+      do_virtual = 1; do_static = 1;
+      }
+    else
+      {
+      /* A member of a namespace.  */
+      tag = "Function"; do_returns = 1;
+      }
+    }
+
+  fprintf (xdi->file, "  <%s", tag);
+  xml_print_id_attribute (xdi, dn);
+  xml_print_name_attribute (xdi, name);
+
+  if(do_returns)
+    {
+    xml_print_returns_attribute (xdi, TREE_TYPE (TREE_TYPE (fd)), dn->complete);
+    }
+  if(do_access)  xml_print_access_attribute (xdi, fd);
+  if(do_const)   xml_print_const_method_attribute (xdi, fd);
+  if(do_virtual) xml_print_virtual_method_attributes (xdi, fd);
+  if(do_static)  xml_print_static_method_attribute (xdi, fd);
+  xml_print_throw_attribute (xdi, TREE_TYPE (fd), dn->complete);
+  xml_print_context_attribute (xdi, fd);
+  xml_print_location_attribute (xdi, fd);
+  if(body)
+    {
+    xml_print_endline_attribute (xdi, body);
+    }
+  xml_print_function_extern_attribute (xdi, fd);
+  xml_print_attributes_attribute (xdi, GCC_XML_DECL_ATTRIBUTES(fd),
+                                  TYPE_ATTRIBUTES(TREE_TYPE(fd)));
+  
+  /* Prepare to iterator through argument list.  */
+  arg = DECL_ARGUMENTS (fd);
+  arg_type = TYPE_ARG_TYPES (TREE_TYPE (fd));
+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fd))
+    {
+    /* Skip "this" argument.  */
+    if(arg) arg = TREE_CHAIN (arg);
+    arg_type = TREE_CHAIN (arg_type);
+    }
+  
+  /* If there are no arguments, finish the element.  */
+  if (arg_type == void_list_node)
+    {
+    fprintf (xdi->file, "/>\n");
+    return;
+    }
+  else
+    {
+    fprintf (xdi->file, ">\n");
+    }
+  
+  /* Print out the argument list for this function.  */
+  while (arg_type && (arg_type != void_list_node))
+    {
+    xml_output_argument (xdi, arg, arg_type, dn->complete);
+    if(arg) arg = TREE_CHAIN (arg);
+    arg_type = TREE_CHAIN (arg_type);
+    }
+  
+  if(!arg_type)
+    {
+    /* Function has variable number of arguments.  Print ellipsis.  */
+    xml_output_ellipsis (xdi);
+    }
+  
+  fprintf (xdi->file, "  </%s>\n", tag);
+}
+
+/* Output for a VAR_DECL.  The name and type of the variable are output,
+   as well as the initializer if it exists.  */
+static void
+xml_output_var_decl (xml_dump_info_p xdi, tree vd, xml_dump_node_p dn)
+{
+  tree type = TREE_TYPE (vd);
+  fprintf (xdi->file, "  <Variable");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_name_attribute (xdi, DECL_NAME (vd));
+  if(TYPE_NAME (type) && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+    type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+  xml_print_type_attribute (xdi, type, dn->complete);
+  xml_print_init_attribute (xdi, DECL_INITIAL (vd));
+  xml_print_context_attribute (xdi, vd);
+  xml_print_access_attribute (xdi, vd);
+  xml_print_location_attribute (xdi, vd);
+  xml_print_extern_attribute (xdi, vd);
+  xml_print_attributes_attribute (xdi, GCC_XML_DECL_ATTRIBUTES(vd), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for a FIELD_DECL.  The name and type of the variable are output,
+   as well as the initializer if it exists.  */
+static void
+xml_output_field_decl (xml_dump_info_p xdi, tree fd, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <Field");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_name_attribute (xdi, DECL_NAME (fd));
+  xml_print_access_attribute (xdi, fd);
+  /* TODO: handle bit field case.  */
+  xml_print_type_attribute (xdi, TREE_TYPE (fd), dn->complete);
+  xml_print_context_attribute (xdi, fd);
+  xml_print_location_attribute (xdi, fd);
+  xml_print_attributes_attribute (xdi, GCC_XML_DECL_ATTRIBUTES(fd), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output a RECORD_TYPE that is not a pointer-to-member-function.
+   Prints beginning and ending tags, and all class member declarations
+   between.  Also handles a UNION_TYPE.  */
+static void
+xml_output_record_type (xml_dump_info_p xdi, tree rt, xml_dump_node_p dn)
+{
+  tree field;
+  tree func;
+  const char* tag;
+  
+  if (TREE_CODE(rt) == RECORD_TYPE)
+    {
+    if (CLASSTYPE_DECLARED_CLASS (rt)) { tag = "Class"; }
+    else { tag = "Struct"; }
+    }
+  else { tag = "Union"; }
+  
+  fprintf (xdi->file, "  <%s", tag);
+  xml_print_id_attribute (xdi, dn);
+  xml_print_name_attribute (xdi, DECL_NAME (TYPE_NAME (rt)));
+  xml_print_context_attribute (xdi, TYPE_NAME (rt));
+  xml_print_access_attribute (xdi, TYPE_NAME (rt));
+  xml_print_abstract_attribute (xdi, rt);
+  xml_print_incomplete_attribute (xdi, rt);
+  xml_print_location_attribute (xdi, TYPE_NAME (rt));
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(rt), 0);
+  
+  if (dn->complete && COMPLETE_TYPE_P (rt))
+    {
+    fprintf (xdi->file, " members=\"");
+    /* Output all the non-method declarations in the class.  */
+    for (field = TYPE_FIELDS (rt) ; field ; field = TREE_CHAIN (field))
+      {
+      /* Don't process any internally generated declarations.  */
+      if (DECL_INTERNAL_P (field)) continue;
+
+      /* Don't process any compiler-generated fields.  */
+      if (DECL_ARTIFICIAL(field) && !DECL_IMPLICIT_TYPEDEF_P(field)) continue;
+
+      /* A class or struct internally typedefs itself.  Don't
+         output this extra typedef.  */
+      if (!((TREE_CODE (field) == TYPE_DECL)
+            && (TREE_TYPE (field) == rt)))
+        {
+        int id = xml_add_node (xdi, field, 1);
+        if (id)
+          {
+          fprintf (xdi->file, "_%d ", id);
+          }
+        }
+      }
+    
+    /* Output all the method declarations in the class.  */
+    for (func = TYPE_METHODS (rt) ; func ; func = TREE_CHAIN (func))
+      {
+      int id;
+
+      /* Don't process any internally generated declarations.  */
+      if (DECL_INTERNAL_P (func)) continue;
+      
+      /* Don't process any compiler-generated functions except constructors
+         and destructors.  */
+      if (DECL_ARTIFICIAL(func)
+          && !DECL_CONSTRUCTOR_P (func)
+          && !DECL_DESTRUCTOR_P (func)) continue;
+      
+      /* Don't output the cloned functions.  */
+      if (DECL_CLONED_FUNCTION_P (func)) continue;
+
+      id = xml_add_node (xdi, func, 1);
+      if(id)
+        {
+        fprintf (xdi->file, "_%d ", id);
+        }
+      }
+    
+    /* TODO: List member template instantiations as members.  */
+
+    fprintf (xdi->file, "\"");
+    }  
+  
+  /* Output all the base classes.  */
+  if (dn->complete && COMPLETE_TYPE_P (rt))
+    {
+    tree binfo = TYPE_BINFO (rt);
+    tree binfos = BINFO_BASETYPES (binfo);
+    int n_baselinks = binfos? TREE_VEC_LENGTH (binfos) : 0;
+#if !defined (XML_PRE_3_4_TREE_VIA_PUBLIC)
+    tree accesses = BINFO_BASEACCESSES (binfo);
+#endif
+    int i;
+    
+    fprintf (xdi->file, " bases=\"");
+    for (i = 0; i < n_baselinks; i++)
+      {
+      tree base_binfo = TREE_VEC_ELT (binfos, i);
+      if (base_binfo)
+        {
+        /* Output this base class.  Default is public access.  */
+#if defined (XML_PRE_3_4_TREE_VIA_PUBLIC)
+        const char* access = 0;
+        if (TREE_VIA_PUBLIC (base_binfo)) { access = ""; }
+        else if (TREE_VIA_PROTECTED (base_binfo)) { access = "protected:"; }
+        else { access="private:"; }
+#else
+        tree n_access = (accesses ? TREE_VEC_ELT (accesses, i)
+                                  : access_public_node);
+        const char* access = "";
+        if (n_access == access_protected_node) { access = "protected:"; }
+        else if (n_access == access_private_node) { access = "private:"; }
+#endif
+        
+        fprintf (xdi->file, "%s_%d ", access,
+                 xml_add_node (xdi, BINFO_TYPE (base_binfo), 1));
+        }
+      }
+    fprintf (xdi->file, "\"");
+    }
+  
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for a fundamental type.  */
+static void
+xml_output_fundamental_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <FundamentalType");
+  xml_print_id_attribute (xdi, dn);
+  /*xml_print_name_attribute (
+    xdi, DECL_NAME (TYPE_NAME (TYPE_MAIN_VARIANT (t))));*/
+  xml_print_name_attribute (xdi, DECL_NAME (TYPE_NAME (t)));
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for a FUNCTION_TYPE.  */
+static void
+xml_output_function_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  tree arg_type;
+  
+  fprintf (xdi->file, "  <FunctionType");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_returns_attribute (xdi, TREE_TYPE (t), dn->complete);
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, ">\n");
+  
+  /* Prepare to iterator through argument list.  */
+  arg_type = TYPE_ARG_TYPES (t);
+
+  /* Print out the argument list for this function.  */
+  while (arg_type && (arg_type != void_list_node))
+    {
+    xml_output_argument (xdi, NULL, arg_type, dn->complete);
+    arg_type = TREE_CHAIN (arg_type);
+    }
+  
+  if(arg_type != void_list_node)
+    {
+    /* Function has variable number of arguments.  */
+    xml_output_ellipsis (xdi);
+    }
+  
+  fprintf (xdi->file, "  </FunctionType>\n");
+}
+
+/* Output for a METHOD_TYPE.  */
+static void
+xml_output_method_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  tree arg_type;
+  tree this_type;
+  
+  fprintf (xdi->file, "  <MethodType");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_base_type_attribute (xdi, TYPE_METHOD_BASETYPE (t), dn->complete);
+  xml_print_returns_attribute (xdi, TREE_TYPE (t), dn->complete);
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  
+  /* Prepare to iterator through argument list.  */
+  arg_type = TYPE_ARG_TYPES (t);
+
+  /* We need to find out if the implicity argument points to a CV
+     qualified type. */
+  this_type = TREE_TYPE(TREE_VALUE (arg_type));
+  if (this_type)
+    {
+    if (TYPE_READONLY (this_type))
+      {
+      fprintf (xdi->file, " const=\"1\"");
+      }
+    if (TYPE_VOLATILE (this_type))
+      {
+      fprintf (xdi->file, " volatile=\"1\"");
+      }
+    }
+  
+  fprintf (xdi->file, ">\n");
+  
+  /* Skip "this" argument.  */
+  arg_type = TREE_CHAIN (arg_type);
+  
+  /* Print out the argument list for this method.  */
+  while (arg_type && (arg_type != void_list_node))
+    {
+    xml_output_argument (xdi, NULL, arg_type, dn->complete);
+    arg_type = TREE_CHAIN (arg_type);
+    }
+  
+  if(arg_type != void_list_node)
+    {
+    /* Method has variable number of arguments.  */
+    xml_output_ellipsis (xdi);
+    }
+  
+  fprintf (xdi->file, "  </MethodType>\n");
+}
+
+/* Output for a POINTER_TYPE.  */
+static void
+xml_output_pointer_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <PointerType");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_type_attribute (xdi, TREE_TYPE (t), 0);
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for a REFERENCE_TYPE.  */
+static void
+xml_output_reference_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <ReferenceType");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_type_attribute (xdi, TREE_TYPE (t), 0);
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for an OFFSET_TYPE.  */
+static void
+xml_output_offset_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <OffsetType");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_base_type_attribute (xdi, TYPE_OFFSET_BASETYPE (t), dn->complete);
+  xml_print_type_attribute (xdi, TREE_TYPE (t), dn->complete);
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for an ARRAY_TYPE.  */
+static void
+xml_output_array_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  fprintf (xdi->file, "  <ArrayType");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_array_attributes (xdi, t);
+  xml_print_type_attribute (xdi, TREE_TYPE (t), dn->complete);
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, "/>\n");
+}
+
+/* Output for an ENUMERAL_TYPE.  */
+static void
+xml_output_enumeral_type (xml_dump_info_p xdi, tree t, xml_dump_node_p dn)
+{
+  tree tv;
+  
+  fprintf (xdi->file, "  <Enumeration");
+  xml_print_id_attribute (xdi, dn);
+  xml_print_name_attribute (xdi, DECL_NAME (TYPE_NAME (t)));
+  xml_print_context_attribute (xdi, TYPE_NAME (t));
+  xml_print_access_attribute (xdi, TYPE_NAME (t));
+  xml_print_location_attribute (xdi, TYPE_NAME (t));
+  xml_print_attributes_attribute (xdi, TYPE_ATTRIBUTES(t), 0);
+  fprintf (xdi->file, ">\n");
+  
+  /* Output the list of possible values for the enumeration type.  */
+  for (tv = TYPE_VALUES (t); tv ; tv = TREE_CHAIN (tv))
+    {
+    int value = TREE_INT_CST_LOW (TREE_VALUE (tv));
+    fprintf (xdi->file,
+             "    <EnumValue name=\"%s\" init=\"%d\"/>\n",
+             xml_get_encoded_string ( TREE_PURPOSE(tv)), value);
+    }
+  
+  fprintf (xdi->file, "  </Enumeration>\n");
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* When a class, struct, or union type is defined, it is automatically
+   given a member typedef to itself.  Given a RECORD_TYPE or
+   UNION_TYPE, this returns that field's name.  Although this should
+   never happen, 0 is returned when the field cannot be found.  */
+static tree
+xml_find_self_typedef_name (tree rt)
+{
+  tree field;
+  for (field = TYPE_FIELDS (rt) ; field ; field = TREE_CHAIN (field))
+    {
+    /* The field must be artificial because someone could have written
+       their own typedef of the class's name.  */
+    if ((TREE_CODE (field) == TYPE_DECL)
+        && (TREE_TYPE (field) == rt)
+        && DECL_ARTIFICIAL (field))
+      {
+      return DECL_NAME (field);
+      }
+    }
+
+  return 0;
+}
+
+/* Add the given typedef if it really came from user code.  */
+static int
+xml_add_typedef (xml_dump_info_p xdi, tree td, int complete)
+{
+  tree t;
+  
+  /* If the typedef points to its own name in the same context, ignore
+     it.  */
+  if(!DECL_ORIGINAL_TYPE (td)
+     && TREE_TYPE (td) && TYPE_NAME (TREE_TYPE (td))
+     && (DECL_NAME (td) == DECL_NAME (TYPE_NAME (TREE_TYPE (td))))
+     && (DECL_CONTEXT (td) == DECL_CONTEXT (TYPE_NAME (TREE_TYPE (td)))))
+    {
+    return 0;
+    }
+  
+  /* Find the typedef's real target type.  */
+  if (DECL_ORIGINAL_TYPE (td))
+    {
+    t = DECL_ORIGINAL_TYPE (td);
+    }
+  else
+    {
+    t = TREE_TYPE (td);
+    }
+  
+  if (TYPE_MAIN_VARIANT (t))
+    {
+    t = TYPE_MAIN_VARIANT (t);
+    }
+  
+  /* Only add the typedef if its target will be dumped.  */
+  if (xml_add_node (xdi, t, complete))
+    {
+    return xml_add_node_real (xdi, td, complete);
+    }
+  else
+    {
+    return 0;
+    }
+}
+
+/* Dispatch output of a TYPE_DECL.  This is either a typedef, or a new
+   type (class/struct/union) definition.  */
+static int
+xml_add_type_decl (xml_dump_info_p xdi, tree td, int complete)
+{
+  /* Get the type from the TYPE_DECL.  We don't want to use complete_type
+     because it may modify something.  We are doing a read-only dump.  */
+  tree t = TREE_TYPE (td);
+  
+  switch (TREE_CODE (t))
+    {
+    case ARRAY_TYPE:
+    case LANG_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case INTEGER_TYPE:
+    case VOID_TYPE:
+    case BOOLEAN_TYPE:
+    case REAL_TYPE:
+    case COMPLEX_TYPE:
+    case FUNCTION_TYPE:
+    case TYPENAME_TYPE:
+    case TEMPLATE_TYPE_PARM:
+      /* A typedef to a predefined type.  */
+      return xml_add_typedef (xdi, td, complete);
+      break;
+    case ENUMERAL_TYPE:
+    case UNION_TYPE:
+    case RECORD_TYPE:
+      if ((TREE_CODE (t) == RECORD_TYPE) && TYPE_PTRMEMFUNC_P (t))
+        {
+        /* A typedef to a pointer to member.  */
+        return xml_add_typedef (xdi, td, complete);
+        }
+      /* This is a complicated test to tell apart a real class declaration
+         or definition from a typedef to it.  This must be able to detect
+         the difference for the following cases:
+
+            Code:                            Meaning:
+         1.  struct A {};                     "struct A"
+         2.  struct A {}; typedef A B;        "struct A" "typedef A B"
+         3.  typedef struct {} A;             "struct A"
+         4.  typedef struct A {} B;           "struct A" "typedef A B"
+         5.  typedef struct A {} A;           "struct A"
+         6.  struct A {}; typedef struct A A; "struct A"
+         
+         DECL_IMPLICIT_TYPEDEF_P will recognize the TYPE_DECL that
+         points to the real class definition for cases 1, 2, 3, and 4,
+         and is sufficient to make the decision.
+         
+         For cases 5 and 6, the second test makes sure the context of
+         the TYPE_DECL matches the context of the RECORD_TYPE, which
+         can only happen for a TYPE_DECL in the same scope as the
+         class.  It then looks at the RECORD_TYPE to find its
+         artificial member that is a typedef to its own class.  The
+         name of this field is compared to the name of the original
+         TYPE_DECL.  If it matches and the type's TYPE_NAME node is
+         this TYPE_DECL, then we have found the class's definition.
+         Otherwise, it is assumed that it is simply a typedef.  */
+      else if (DECL_IMPLICIT_TYPEDEF_P (td)
+               || (((DECL_CONTEXT (td) == TYPE_CONTEXT (t))
+                     && (xml_find_self_typedef_name (t) == DECL_NAME (td))
+                     && (TYPE_NAME (t) == td))))
+        {
+        /* This is a new class or enumeration type.  */
+        return xml_add_node (xdi, t, complete);
+        }
+      else
+        {
+        /* A typedef to an existing class or enumeration type.  */
+        return xml_add_typedef (xdi, td, complete);
+        }
+      break;
+    default:
+      xml_output_unimplemented (xdi, t, 0, "xml_add_type_decl");
+    }
+  return 0;
+}
+
+/* Dump for an OVERLOAD.  Dump all the functions in the overload list.   */
+static int
+xml_add_overload (xml_dump_info_p xdi, tree o, int complete)
+{
+  tree cur_overload = o;
+  while (cur_overload)
+    {
+    xml_add_node (xdi, OVL_CURRENT (cur_overload), complete);
+    cur_overload = OVL_NEXT (cur_overload);
+    }
+  return 0;
+}
+
+/* Dump for a TEMPLATE_DECL.  The set of specializations (including
+   instantiations) is dumped.  */
+static int
+xml_add_template_decl (xml_dump_info_p xdi, tree td, int complete)
+{
+  tree tl;
+  
+  /* Dump the template specializations.  */
+  for (tl = DECL_TEMPLATE_SPECIALIZATIONS (td);
+       tl ; tl = TREE_CHAIN (tl))
+    {
+    tree ts = TREE_VALUE (tl);
+    switch (TREE_CODE (ts))
+      {
+      case FUNCTION_DECL:
+        xml_add_node (xdi, ts, complete);
+        break;
+      case TEMPLATE_DECL:
+        break;
+      default:
+        /* xml_output_unimplemented (xdi, ts, 0,
+          "xml_dump_template_decl SPECIALIZATIONS");  */
+        break;
+      }
+    }
+  
+  /* Dump the template instantiations.  */
+  for (tl = DECL_TEMPLATE_INSTANTIATIONS (td);
+       tl ; tl = TREE_CHAIN (tl))
+    {
+    tree ts = TYPE_NAME (TREE_VALUE (tl));
+    switch (TREE_CODE (ts))
+      {
+      case TYPE_DECL:
+        /* Add the instantiation only if it is real.  */
+        if (!DECL_ARTIFICIAL(ts))
+          {
+          xml_add_node (xdi, ts, complete);
+          }
+        break;
+      default:
+        /* xml_output_unimplemented (xdi, ts, 0,
+           "xml_dump_template_decl INSTANTIATIONS");  */
+        break;
+      }
+    }
+  
+  /* Dump any member template instantiations.  */
+  if (complete)
+    {
+    for (tl = TYPE_FIELDS (TREE_TYPE (td)); tl; tl = TREE_CHAIN (tl))
+      {
+      if (TREE_CODE (tl) == TEMPLATE_DECL)
+        {
+        xml_add_template_decl (xdi, tl, 1);
+        }
+      }
+    }
+  
+  return 0;
+}
+
+/* Dump the given tree node.  */
+void
+xml_dump_tree_node (xml_dump_info_p xdi, tree n, xml_dump_node_p dn)
+{
+  switch (TREE_CODE (n))
+    {
+    case NAMESPACE_DECL:
+      xml_output_namespace_decl (xdi, n, dn);
+      break;
+    case TYPE_DECL:
+      xml_output_typedef (xdi, n, dn);
+      break;          
+    case FUNCTION_DECL:
+      xml_output_function_decl (xdi, n, dn);
+      break;
+    case VAR_DECL:
+      xml_output_var_decl (xdi, n, dn);
+      break;
+    case FIELD_DECL:
+      xml_output_field_decl (xdi, n, dn);
+      break;
+    case UNION_TYPE:
+    case RECORD_TYPE:
+      xml_output_record_type (xdi, n, dn);
+      break;
+    case ARRAY_TYPE:
+      xml_output_array_type (xdi, n, dn);
+      break;
+    case POINTER_TYPE:
+      xml_output_pointer_type (xdi, n, dn);
+      break;
+    case REFERENCE_TYPE:
+      xml_output_reference_type (xdi, n, dn);
+      break;
+    case FUNCTION_TYPE:
+      xml_output_function_type (xdi, n, dn);
+      break;
+    case METHOD_TYPE:
+      xml_output_method_type (xdi, n, dn);
+      break;
+    case OFFSET_TYPE:
+      xml_output_offset_type (xdi, n, dn);
+      break;
+    case ENUMERAL_TYPE:
+      xml_output_enumeral_type (xdi, n, dn);
+      break;
+    case LANG_TYPE:
+    case INTEGER_TYPE:
+    case BOOLEAN_TYPE:
+    case REAL_TYPE:
+    case VOID_TYPE:
+    case COMPLEX_TYPE:
+      xml_output_fundamental_type (xdi, n, dn);
+      break;
+      
+    /* Let the following fall through to unimplemented for now.  */
+    case RESULT_DECL:
+    case USING_DECL:
+      /* case THUNK_DECL: */
+      /* This is compiler-generated.  Just ignore it.  */
+      /* break; */
+    case SCOPE_REF:
+    case TEMPLATE_PARM_INDEX:
+    case INTEGER_CST:
+    case TYPENAME_TYPE:
+    case TEMPLATE_TYPE_PARM:
+    default:
+      xml_output_unimplemented (xdi, n, dn, 0);
+    }
+}
+
+/* If we enabled xml dump debugging, undefine the macro.  */
+#if defined(xml_add_node)
+# undef xml_add_node
+#endif
+
+/* Add tree node N to those encountered.  Return its index.  */
+int
+xml_add_node (xml_dump_info_p xdi, tree n, int complete)
+{
+  /* Some nodes don't need to be dumped and just refer to other nodes.
+     These nodes should can have index zero because they should never
+     be referenced.  */
+  switch (TREE_CODE (n))
+    {
+    case NAMESPACE_DECL:
+#if defined(XML_HAVE_FAKE_STD_NODE)
+      if(n != fake_std_node)
+#endif
+        {
+        return xml_add_node_real (xdi, n, complete);
+        }
+      break;
+    case TYPE_DECL:
+      return xml_add_type_decl(xdi, n, complete);
+      break;
+    case TREE_LIST:
+      return xml_add_overload (xdi, TREE_VALUE (n), complete);
+      break;
+    case OVERLOAD:
+      return xml_add_overload (xdi, n, complete);
+      break;
+    case TEMPLATE_DECL:
+      return xml_add_template_decl (xdi, n, complete);
+      break;
+    case UNION_TYPE:
+    case RECORD_TYPE:
+      if ((TREE_CODE (n) == RECORD_TYPE) && TYPE_PTRMEMFUNC_P (n))
+        {
+        /* Pointer-to-member-functions are stored in a RECORD_TYPE.  */
+        return xml_add_node (xdi, TYPE_PTRMEMFUNC_FN_TYPE (n), complete);
+        }
+      else if (!CLASSTYPE_IS_TEMPLATE (n))
+        {
+        /* This is a struct or class type.  */
+        return xml_add_node_real (xdi, n, complete);
+        }
+      else
+        {
+        /* This is a class template.  We don't want to dump it.  */
+        return 0;
+        }
+      break;
+    case CONST_DECL:
+      /* Enumeration value constant.  Dumped by the enumeration type.  */
+      return 0;
+      break;
+    default:
+      /* This node must really be added.  */
+      return xml_add_node_real (xdi, n, complete);
+    }
+  
+  return 0;
+}  
+
+/* Dump the queue of file names.  */
+void xml_dump_files (xml_dump_info_p xdi)
+{
+  xml_file_queue_p fq;
+  xml_file_queue_p next_fq; 
+  for(fq = xdi->file_queue; fq ; fq = next_fq)
+    {
+    fprintf (xdi->file, "  <File id=\"f%d\" name=\"%s\"/>\n",
+             (unsigned int) fq->tree_node->value,
+             IDENTIFIER_POINTER ((tree) fq->tree_node->key));
+    next_fq = fq->next;
+    free (fq);
+    }
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Starting in the given scope, look for the qualified name.  */
+static tree
+xml_lookup_start_node (tree scope, const char* qualified_name)
+{
+  tree node = 0;
+  char* name = 0;
+  int pos = 0;
+  tree id;
+  
+  /* Parse off the first qualifier.  */
+  while (qualified_name[pos] && (qualified_name[pos] != ':')) { ++pos; }
+  name = xmalloc(pos+1);
+  strncpy (name, qualified_name, pos);
+  name[pos] = 0;
+  id = get_identifier (name);
+  free (name);
+
+  /* Lookup the first qualifier.  */
+  if (TREE_CODE (scope) == NAMESPACE_DECL)
+    {
+    node = lookup_namespace_name (scope, id);
+    }
+  else if ((TREE_CODE (scope) == TYPE_DECL)
+           && (TREE_CODE (TREE_TYPE (scope)) == RECORD_TYPE))
+    {
+    node = lookup_member (TREE_TYPE (scope), id, 2, 0);
+    }
+  
+  if (!node) { return 0; }
+  
+  /* Find the start of the next qualifier, if any.  */
+  while (qualified_name[pos] && (qualified_name[pos] == ':')) { ++pos; }
+  
+  /* If that was not the last qualifier, lookup the rest recursively.  */
+  if (qualified_name[pos])
+    {
+    return xml_lookup_start_node (node, qualified_name+pos);
+    }
+  else
+    {
+    return node;
+    }
+}
+
+/* Add the given node as a starting node.  */
+static void
+xml_add_start_node (xml_dump_info_p xdi, tree n)
+{
+  /* If a list was returned (from lookup_member), add all
+     candidates.  */
+  if ((TREE_CODE (n) == TREE_LIST)
+      && (TREE_TYPE (n) == error_mark_node))
+    {
+    tree l = n;
+    while (l)
+      {
+      xml_add_node (xdi, TREE_VALUE (l), 1);
+      l = TREE_CHAIN (l);
+      }
+    }
+  else
+    {
+    xml_add_node (xdi, n, 1);
+    }
+}
+
+/* Parse the comma-separated list of start nodes.  Lookup and add each
+   one.  */
+void
+xml_add_start_nodes (xml_dump_info_p xdi, const char* in_start_list)
+{
+  size_t len = strlen(in_start_list);
+  int pos=0;
+  char* start_list = (char*)xmalloc(len+1);
+  char* cur_start = start_list;
+  tree node = 0;
+  strcpy(start_list, in_start_list);
+  
+  /* Parse out the comma-separated list.  */
+  while (start_list[pos])
+    {
+    /* Split the list at each comma.  */
+    if (start_list[pos] == ',')
+      {
+      start_list[pos] = 0;
+      
+      /* Add the node for this list entry.  */
+      node = xml_lookup_start_node (global_namespace, cur_start);      
+      if (node)
+        {
+        xml_add_start_node (xdi, node);
+        }
+      
+      /* Start the next list entry.  */
+      cur_start = start_list+pos+1;
+      }
+    ++pos;
+    }  
+  
+  /* Add the node for the last list entry.  */
+  node = xml_lookup_start_node (global_namespace, cur_start);
+  if (node)
+    {
+    xml_add_start_node (xdi, node);
+    }
+  
+  free (start_list);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* Convert the identifier IN_ID to an XML encoded form by passing its string
+   to xml_get_encoded_string_from_string().  */
+const char*
+xml_get_encoded_string (tree in_id)
+{
+  if(in_id)
+    return xml_get_encoded_string_from_string (IDENTIFIER_POINTER (in_id));
+  else
+    return "";
+}
+
+#define XML_AMPERSAND     "&amp;"
+#define XML_LESS_THAN     "&lt;"
+#define XML_GREATER_THAN  "&gt;"
+#define XML_SINGLE_QUOTE  "&apos;"
+#define XML_DOUBLE_QUOTE  "&quot;"
+
+const char*
+xml_get_encoded_string_from_string (const char* in_str)
+{
+  return IDENTIFIER_POINTER (xml_get_encoded_identifier_from_string (in_str));
+}
+
+/* Convert the name IN_STR to an XML encoded form.
+   This replaces '&', '<', and '>'
+   with their corresponding unicode character references.  */
+tree
+xml_get_encoded_identifier_from_string (const char* in_str)
+{
+  int length_increase = 0;
+  const char* inCh;
+  char* outCh;
+  char* newStr;
+  tree id;
+
+  /* Count special characters and calculate extra length needed for encoded
+     form of string.  */
+  for(inCh = in_str; *inCh != '\0' ; ++inCh)
+    {
+    switch (*inCh)
+      {
+      case '&': length_increase += strlen(XML_AMPERSAND)-1; break;
+      case '<': length_increase += strlen(XML_LESS_THAN)-1; break;
+      case '>': length_increase += strlen(XML_GREATER_THAN)-1; break;
+      case '\'': length_increase += strlen(XML_SINGLE_QUOTE)-1; break;
+      case '"': length_increase += strlen(XML_DOUBLE_QUOTE)-1; break;
+      }
+    }
+
+  newStr = (char*) xmalloc (strlen (in_str) + length_increase + 1);
+  outCh = newStr;
+
+  /* Create encoded form of string.  */
+  for(inCh = in_str ; *inCh != '\0' ; ++inCh)
+    {
+    switch (*inCh)
+      {
+      case '&': strcpy (outCh, XML_AMPERSAND); outCh += strlen(XML_AMPERSAND); break;
+      case '<': strcpy (outCh, XML_LESS_THAN);  outCh += strlen(XML_LESS_THAN); break;
+      case '>': strcpy (outCh, XML_GREATER_THAN);  outCh += strlen(XML_GREATER_THAN); break;
+      case '\'': strcpy (outCh, XML_SINGLE_QUOTE);  outCh += strlen(XML_SINGLE_QUOTE); break;
+      case '"': strcpy (outCh, XML_DOUBLE_QUOTE);  outCh += strlen(XML_DOUBLE_QUOTE); break;
+      default: *outCh++ = *inCh;
+      }
+    }  
+
+  *outCh = '\0';
+
+  /* Ask for "identifier" of this string and free our own copy of the
+     memory.  */
+  id = get_identifier(newStr);
+  free(newStr);
+  return id;
+}
+
+#undef XML_AMPERSAND
+#undef XML_LESS_THAN
+#undef XML_GREATER_THAN
+#undef XML_SINGLE_QUOTE
+#undef XML_DOUBLE_QUOTE

File GCC_XML/xml.c

+/*=========================================================================
+
+  Program:   GCC-XML
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+/* Organization of this source:
+   The entry point is do_xml_output(), which is called from the end of
+   finish_translation_unit() in semantics.c.
+   
+   xml_output_* functions are called to actually write the XML output.
+   
+   xml_print_*_attribute functions are used to write out the XML attributes
+   for common attribute name/pair values.
+*/
+
+/* Use GCC_XML_GCC_VERSION to modify code based on the version of GCC
+   in which we are being built.  This is set in the patched version of
+   cp-tree.h.  The format is 0xMMmmpp, where MM is the major version
+   number, mm is the minor version number, and pp is the patch level.
+   Examples:  gcc 3.0.4 = 0x030004
+              gcc 3.2.0 = 0x030200  */
+
+#include "config.h"
+#include "system.h"
+#include "sys/stat.h"
+
+/* GCC 3.4 and above need these headers here.  The GCC-XML patches for
+   these versions define GCC_XML_GCC_VERSION in config.h instead of
+   cp-tree.h, so the macro is available here.  The patches for older
+   versions may provide the macro in cp-tree.h, but in that case
+   we don't need these headers anyway.  */
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030400)
+# include "coretypes.h"
+# include "tm.h"
+#endif
+
+#include "tree.h"
+#include "cp-tree.h"
+#include "decl.h"
+#include "rtl.h"
+#include "varray.h"
+
+#include "splay-tree.h"
+
+/* Decide how to call cp_error.  */
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030100)
+# define XML_CP_ERROR cp_error_at
+#else
+# define XML_CP_ERROR cp_error
+# define XML_HAVE_FAKE_STD_NODE
+#endif
+
+/* Decide how to get the attributes node from a declaration.  */
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030100)
+# define GCC_XML_DECL_ATTRIBUTES(n) DECL_ATTRIBUTES(n)
+#else
+# define GCC_XML_DECL_ATTRIBUTES(n) DECL_MACHINE_ATTRIBUTES(n)
+#endif
+
+/* Decide how to access base classes.  */
+#if !defined(GCC_XML_GCC_VERSION) || (GCC_XML_GCC_VERSION < 0x030400)
+# define XML_PRE_3_4_TREE_VIA_PUBLIC
+#endif
+
+/* A "dump node" corresponding to a particular tree node.  */
+typedef struct xml_dump_node
+{
+  /* The index for the node.  */
+  unsigned int index;
+
+  /* Whether the node is complete.  */
+  unsigned int complete;
+} *xml_dump_node_p;
+
+/* A node on the queue of dump nodes.  */
+typedef struct xml_dump_queue
+{
+  /* The queued tree node.  */
+  tree tree_node;
+
+  /* The corresponding dump node.  */
+  xml_dump_node_p dump_node;
+
+  /* The next node in the queue.  */
+  struct xml_dump_queue *next;
+} *xml_dump_queue_p;
+
+/* A node on the queue of file names.  */
+typedef struct xml_file_queue
+{
+  /* The queued file name.  */
+  splay_tree_node tree_node;
+
+  /* The next node in the queue.  */
+  struct xml_file_queue *next;
+} *xml_file_queue_p;
+
+/* Dump control structure.  A pointer one instance of this is passed
+   to nearly every function.  */
+typedef struct xml_dump_info
+{
+  /* Output file stream of dump.  */
+  FILE* file;
+  
+  /* Which pass of the loop we are doing (1=complete or 0=incomplete).  */
+  int require_complete;
+  
+  /* Next available index to identify node.  */
+  unsigned int next_index;
+
+  /* The first node in the queue of complete nodes.  */
+  xml_dump_queue_p queue;
+
+  /* The last node in the queue of complete nodes.  */
+  xml_dump_queue_p queue_end;
+  
+  /* List of free xml_dump_queue nodes.  */
+  xml_dump_queue_p queue_free;
+  
+  /* All nodes that have been encountered.  */
+  splay_tree dump_nodes;
+
+  /* Index of the next available file queue position.  */
+  unsigned int file_index;
+
+  /* The first file in the queue of filenames.  */
+  xml_file_queue_p file_queue;
+
+  /* The last file in the queue of filenames.  */
+  xml_file_queue_p file_queue_end;
+
+  /* All files that have been queued.  */
+  splay_tree file_nodes;
+} *xml_dump_info_p;
+
+/* Return non-zero if the given _DECL is an internally generated decl.  */
+#define DECL_INTERNAL_P(d) (DECL_SOURCE_LINE(d) == 0)
+
+void do_xml_output PARAMS ((const char*));
+
+static int xml_add_node PARAMS((xml_dump_info_p, tree, int));
+static void xml_dump PARAMS((xml_dump_info_p));
+static int xml_queue_incomplete_dump_nodes PARAMS((splay_tree_node, void*));
+static void xml_dump_tree_node PARAMS((xml_dump_info_p, tree, xml_dump_node_p));
+static void xml_dump_files PARAMS((xml_dump_info_p));
+
+static void xml_add_start_nodes PARAMS((xml_dump_info_p, const char*));
+
+static const char* xml_get_encoded_string PARAMS ((tree));
+static const char* xml_get_encoded_string_from_string PARAMS ((const char*));
+static tree xml_get_encoded_identifier_from_string PARAMS ((const char*));
+
+#if defined(GCC_XML_GCC_VERSION) && (GCC_XML_GCC_VERSION >= 0x030100)
+# include "diagnostic.h"
+#else
+extern int errorcount;
+#endif
+
+/* Switch to 1 to enable debugging of dump node selection.  */
+#if 0
+# define xml_add_node(xdi, node, complete)                                    \
+   (fprintf(stderr, "Adding node at line %d\n", __LINE__),                    \
+    xml_add_node(xdi, node, complete))
+#endif
+
+/* Main XML output function.  Called by parser at the end of a translation
+   unit.  Walk the entire translation unit starting at the global
+   namespace.  Output all declarations.  */
+void
+do_xml_output (const char* filename)
+{
+  FILE* file;
+  struct xml_dump_info xdi;
+  
+  /* Do not dump if errors occurred during parsing.  */
+  if(errorcount)
+    {
+    /* Delete any existing output file.  */
+    unlink(filename);
+    return;
+    }
+  
+  /* Open the XML output file.  */
+  file = fopen (filename, "w");
+  if (!file)
+    {
+    XML_CP_ERROR ("could not open xml-dump file `%s'", filename);
+    return;
+    }
+  
+  /* Prepare dump.  */
+  xdi.file = file;
+  xdi.queue = 0;
+  xdi.queue_end = 0;
+  xdi.queue_free = 0;
+  xdi.next_index = 1;
+  xdi.dump_nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
+                                   (splay_tree_delete_value_fn) &free);
+  xdi.file_queue = 0;
+  xdi.file_queue_end = 0;
+  xdi.file_index = 0;
+  xdi.file_nodes = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+  xdi.require_complete = 1;
+  
+  /* Add the starting nodes for the dump.  */
+  if (flag_xml_start)
+    {
+    /* Use the specified starting locations.  */
+    xml_add_start_nodes (&xdi, flag_xml_start);
+    }
+  else
+    {
+    /* No start specified.  Use global namespace.  */
+    xml_add_node (&xdi, global_namespace, 1);
+
+    /* Also add std namespace because it is not always referenced.  */
+    if(std_node)
+      {
+      xml_add_node (&xdi, std_node, 1);
+      }
+    }
+  
+  /* Start dump.  */
+  fprintf (file, "<?xml version=\"1.0\"?>\n");
+#if defined(GCCXML_VERSION_FULL)
+  fprintf (file, "<GCC_XML version=\"" GCCXML_VERSION_FULL "\">\n");
+#else
+  fprintf (file, "<GCC_XML>\n");
+#endif
+  
+  /* Dump the complete nodes.  */
+  xml_dump (&xdi);  
+  
+  /* Queue all the incomplete nodes.  */
+  splay_tree_foreach (xdi.dump_nodes,
+                      &xml_queue_incomplete_dump_nodes, &xdi);
+  
+  /* Dump the incomplete nodes.  */
+  xdi.require_complete = 0;
+  xml_dump (&xdi);
+  
+  /* Dump the filename queue.  */
+  xml_dump_files (&xdi);
+  
+  /* Finish dump.  */
+  fprintf (file, "</GCC_XML>\n");
+  
+  /* Clean up.  */
+  {
+  xml_dump_queue_p dq = xdi.queue_free;
+  while(dq)
+    {
+    xml_dump_queue_p nq = dq->next;
+    free(dq);
+    dq = nq;
+    }
+  }
+  splay_tree_delete (xdi.dump_nodes);
+  splay_tree_delete (xdi.file_nodes);
+  fclose (file);
+}
+
+/* Return the xml_dump_node corresponding to tree node T.  If none exists,</