+static void
+xinclude_end_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, const char *body_text)
+{
+ struct xinclude_parsing_data *data = user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_default (void *data_, const XML_Char *s, int len)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* If we are inside of e.g. xi:include or the DTD, don't save this
+ string. */
+ if (data->skip_depth)
+ return;
+
+ /* Otherwise just add it to the end of the document we're building
+ up. */
+ obstack_grow (&data->obstack, s, len);
+}
+
+static void XMLCALL
+xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
+ const XML_Char *sysid, const XML_Char *pubid,
+ int has_internal_subset)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* Don't print out the doctype, or the contents of the DTD internal
+ subset, if any. */
+ data->skip_depth++;
+}
+
+static void XMLCALL
+xml_xinclude_end_doctype (void *data_)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_xml_decl (void *data_, const XML_Char *version,
+ const XML_Char *encoding, int standalone)
+{
+ /* Do nothing - this function prevents the default handler from
+ being called, thus suppressing the XML declaration from the
+ output. */
+}
+
+static void
+xml_xinclude_cleanup (void *data_)
+{
+ struct xinclude_parsing_data *data = data_;
+
+ obstack_free (&data->obstack, NULL);
+ xfree (data);
+}
+
+const struct gdb_xml_attribute xinclude_attributes[] = {
+ { "href", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element xinclude_elements[] = {
+ { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
+ GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+ xinclude_start_include, xinclude_end_include },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* The main entry point for <xi:include> processing. */
+
+char *
+xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth)
+{
+ struct gdb_xml_parser *parser;
+ struct xinclude_parsing_data *data;
+ struct cleanup *back_to;
+ char *result = NULL;
+
+ data = XCNEW (struct xinclude_parsing_data);
+ obstack_init (&data->obstack);
+ back_to = make_cleanup (xml_xinclude_cleanup, data);
+
+ gdb_xml_create_parser_and_cleanup (name, xinclude_elements,
+ data, &parser);
+ parser->is_xinclude = 1;
+
+ data->include_depth = depth;
+ data->fetcher = fetcher;
+ data->fetcher_baton = fetcher_baton;
+
+ XML_SetCharacterDataHandler (parser->expat_parser, NULL);
+ XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
+
+ /* Always discard the XML version declarations; the only important
+ thing this provides is encoding, and our result will have been
+ converted to UTF-8. */
+ XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
+
+ if (depth > 0)
+ /* Discard the doctype for included documents. */
+ XML_SetDoctypeDeclHandler (parser->expat_parser,
+ xml_xinclude_start_doctype,
+ xml_xinclude_end_doctype);
+
+ gdb_xml_use_dtd (parser, "xinclude.dtd");
+
+ if (gdb_xml_parse (parser, text) == 0)
+ {
+ obstack_1grow (&data->obstack, '\0');
+ result = xstrdup (obstack_finish (&data->obstack));
+
+ if (depth == 0)
+ gdb_xml_debug (parser, _("XInclude processing succeeded."));
+ }
+ else
+ result = NULL;
+
+ do_cleanups (back_to);
+ return result;
+}