+\f
+
+/* XInclude processing. This is done as a separate step from actually
+ parsing the document, so that we can produce a single combined XML
+ document - e.g. to hand to a front end or to simplify comparing two
+ documents. We make extensive use of XML_DefaultCurrent, to pass
+ input text directly into the output without reformatting or
+ requoting it.
+
+ We output the DOCTYPE declaration for the first document unchanged,
+ if present, and discard DOCTYPEs from included documents. Only the
+ one we pass through here is used when we feed the result back to
+ expat. The XInclude standard explicitly does not discuss
+ validation of the result; we choose to apply the same DTD applied
+ to the outermost document.
+
+ We can not simply include the external DTD subset in the document
+ as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
+ only in external subsets. But if we do not pass the DTD into the
+ output at all, default values will not be filled in.
+
+ We don't pass through any <?xml> declaration because we generate
+ UTF-8, not whatever the input encoding was. */
+
+struct xinclude_parsing_data
+{
+ xinclude_parsing_data (std::string &output_,
+ xml_fetch_another fetcher_,
+ int include_depth_)
+ : output (output_),
+ skip_depth (0),
+ include_depth (include_depth_),
+ fetcher (fetcher_)
+ {}
+
+ /* Where the output goes. */
+ std::string &output;
+
+ /* A count indicating whether we are in an element whose
+ children should not be copied to the output, and if so,
+ how deep we are nested. This is used for anything inside
+ an xi:include, and for the DTD. */
+ int skip_depth;
+
+ /* The number of <xi:include> elements currently being processed,
+ to detect loops. */
+ int include_depth;
+
+ /* A function to call to obtain additional features, and its
+ baton. */
+ xml_fetch_another fetcher;
+};
+
+static void
+xinclude_start_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data,
+ std::vector<gdb_xml_value> &attributes)
+{
+ struct xinclude_parsing_data *data
+ = (struct xinclude_parsing_data *) user_data;
+ char *href = (char *) xml_find_attribute (attributes, "href")->value.get ();
+
+ gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
+
+ if (data->include_depth > MAX_XINCLUDE_DEPTH)
+ gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
+ MAX_XINCLUDE_DEPTH);
+
+ gdb::optional<gdb::char_vector> text = data->fetcher (href);
+ if (!text)
+ gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
+
+ if (!xml_process_xincludes (data->output, parser->name (),
+ text->data (), data->fetcher,
+ data->include_depth + 1))
+ gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
+
+ data->skip_depth++;
+}
+
+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
+ = (struct xinclude_parsing_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 = (struct gdb_xml_parser *) data_;
+ xinclude_parsing_data *data = (xinclude_parsing_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;