xml-support.c revision 1.7
1/* Helper routines for parsing XML using Expat.
2
3   Copyright (C) 2006-2017 Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20#include "defs.h"
21#include "gdbcmd.h"
22#include "xml-support.h"
23#include "filestuff.h"
24#include "safe-ctype.h"
25
26/* Debugging flag.  */
27static int debug_xml;
28
29/* The contents of this file are only useful if XML support is
30   available.  */
31#ifdef HAVE_LIBEXPAT
32
33#include "gdb_expat.h"
34
35/* The maximum depth of <xi:include> nesting.  No need to be miserly,
36   we just want to avoid running out of stack on loops.  */
37#define MAX_XINCLUDE_DEPTH 30
38
39/* Simplified XML parser infrastructure.  */
40
41/* A parsing level -- used to keep track of the current element
42   nesting.  */
43struct scope_level
44{
45  /* Elements we allow at this level.  */
46  const struct gdb_xml_element *elements;
47
48  /* The element which we are within.  */
49  const struct gdb_xml_element *element;
50
51  /* Mask of which elements we've seen at this level (used for
52     optional and repeatable checking).  */
53  unsigned int seen;
54
55  /* Body text accumulation.  */
56  struct obstack *body;
57};
58typedef struct scope_level scope_level_s;
59DEF_VEC_O(scope_level_s);
60
61/* The parser itself, and our additional state.  */
62struct gdb_xml_parser
63{
64  XML_Parser expat_parser;	/* The underlying expat parser.  */
65
66  const char *name;		/* Name of this parser.  */
67  void *user_data;		/* The user's callback data, for handlers.  */
68
69  VEC(scope_level_s) *scopes;	/* Scoping stack.  */
70
71  struct gdb_exception error;	/* A thrown error, if any.  */
72  int last_line;		/* The line of the thrown error, or 0.  */
73
74  const char *dtd_name;		/* The name of the expected / default DTD,
75				   if specified.  */
76  int is_xinclude;		/* Are we the special <xi:include> parser?  */
77};
78
79/* Process some body text.  We accumulate the text for later use; it's
80   wrong to do anything with it immediately, because a single block of
81   text might be broken up into multiple calls to this function.  */
82
83static void
84gdb_xml_body_text (void *data, const XML_Char *text, int length)
85{
86  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
87  struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
88
89  if (parser->error.reason < 0)
90    return;
91
92  if (scope->body == NULL)
93    {
94      scope->body = XCNEW (struct obstack);
95      obstack_init (scope->body);
96    }
97
98  obstack_grow (scope->body, text, length);
99}
100
101/* Issue a debugging message from one of PARSER's handlers.  */
102
103void
104gdb_xml_debug (struct gdb_xml_parser *parser, const char *format, ...)
105{
106  int line = XML_GetCurrentLineNumber (parser->expat_parser);
107  va_list ap;
108  char *message;
109
110  if (!debug_xml)
111    return;
112
113  va_start (ap, format);
114  message = xstrvprintf (format, ap);
115  if (line)
116    fprintf_unfiltered (gdb_stderr, "%s (line %d): %s\n",
117			parser->name, line, message);
118  else
119    fprintf_unfiltered (gdb_stderr, "%s: %s\n",
120			parser->name, message);
121  xfree (message);
122}
123
124/* Issue an error message from one of PARSER's handlers, and stop
125   parsing.  */
126
127void
128gdb_xml_error (struct gdb_xml_parser *parser, const char *format, ...)
129{
130  int line = XML_GetCurrentLineNumber (parser->expat_parser);
131  va_list ap;
132
133  parser->last_line = line;
134  va_start (ap, format);
135  throw_verror (XML_PARSE_ERROR, format, ap);
136}
137
138/* Find the attribute named NAME in the set of parsed attributes
139   ATTRIBUTES.  Returns NULL if not found.  */
140
141struct gdb_xml_value *
142xml_find_attribute (VEC(gdb_xml_value_s) *attributes, const char *name)
143{
144  struct gdb_xml_value *value;
145  int ix;
146
147  for (ix = 0; VEC_iterate (gdb_xml_value_s, attributes, ix, value); ix++)
148    if (strcmp (value->name, name) == 0)
149      return value;
150
151  return NULL;
152}
153
154/* Clean up a vector of parsed attribute values.  */
155
156static void
157gdb_xml_values_cleanup (void *data)
158{
159  VEC(gdb_xml_value_s) **values = (VEC(gdb_xml_value_s) **) data;
160  struct gdb_xml_value *value;
161  int ix;
162
163  for (ix = 0; VEC_iterate (gdb_xml_value_s, *values, ix, value); ix++)
164    xfree (value->value);
165  VEC_free (gdb_xml_value_s, *values);
166}
167
168/* Handle the start of an element.  DATA is our local XML parser, NAME
169   is the element, and ATTRS are the names and values of this
170   element's attributes.  */
171
172static void
173gdb_xml_start_element (void *data, const XML_Char *name,
174		       const XML_Char **attrs)
175{
176  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
177  struct scope_level *scope;
178  struct scope_level new_scope;
179  const struct gdb_xml_element *element;
180  const struct gdb_xml_attribute *attribute;
181  VEC(gdb_xml_value_s) *attributes = NULL;
182  unsigned int seen;
183  struct cleanup *back_to;
184
185  /* Push an error scope.  If we return or throw an exception before
186     filling this in, it will tell us to ignore children of this
187     element.  */
188  VEC_reserve (scope_level_s, parser->scopes, 1);
189  scope = VEC_last (scope_level_s, parser->scopes);
190  memset (&new_scope, 0, sizeof (new_scope));
191  VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
192
193  gdb_xml_debug (parser, _("Entering element <%s>"), name);
194
195  /* Find this element in the list of the current scope's allowed
196     children.  Record that we've seen it.  */
197
198  seen = 1;
199  for (element = scope->elements; element && element->name;
200       element++, seen <<= 1)
201    if (strcmp (element->name, name) == 0)
202      break;
203
204  if (element == NULL || element->name == NULL)
205    {
206      /* If we're working on XInclude, <xi:include> can be the child
207	 of absolutely anything.  Copy the previous scope's element
208	 list into the new scope even if there was no match.  */
209      if (parser->is_xinclude)
210	{
211	  struct scope_level *unknown_scope;
212
213	  XML_DefaultCurrent (parser->expat_parser);
214
215	  unknown_scope = VEC_last (scope_level_s, parser->scopes);
216	  unknown_scope->elements = scope->elements;
217	  return;
218	}
219
220      gdb_xml_debug (parser, _("Element <%s> unknown"), name);
221      return;
222    }
223
224  if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope->seen))
225    gdb_xml_error (parser, _("Element <%s> only expected once"), name);
226
227  scope->seen |= seen;
228
229  back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
230
231  for (attribute = element->attributes;
232       attribute != NULL && attribute->name != NULL;
233       attribute++)
234    {
235      const char *val = NULL;
236      const XML_Char **p;
237      void *parsed_value;
238      struct gdb_xml_value new_value;
239
240      for (p = attrs; *p != NULL; p += 2)
241	if (!strcmp (attribute->name, p[0]))
242	  {
243	    val = p[1];
244	    break;
245	  }
246
247      if (*p != NULL && val == NULL)
248	{
249	  gdb_xml_debug (parser, _("Attribute \"%s\" missing a value"),
250			 attribute->name);
251	  continue;
252	}
253
254      if (*p == NULL && !(attribute->flags & GDB_XML_AF_OPTIONAL))
255	{
256	  gdb_xml_error (parser, _("Required attribute \"%s\" of "
257				   "<%s> not specified"),
258			 attribute->name, element->name);
259	  continue;
260	}
261
262      if (*p == NULL)
263	continue;
264
265      gdb_xml_debug (parser, _("Parsing attribute %s=\"%s\""),
266		     attribute->name, val);
267
268      if (attribute->handler)
269	parsed_value = attribute->handler (parser, attribute, val);
270      else
271	parsed_value = xstrdup (val);
272
273      new_value.name = attribute->name;
274      new_value.value = parsed_value;
275      VEC_safe_push (gdb_xml_value_s, attributes, &new_value);
276    }
277
278  /* Check for unrecognized attributes.  */
279  if (debug_xml)
280    {
281      const XML_Char **p;
282
283      for (p = attrs; *p != NULL; p += 2)
284	{
285	  for (attribute = element->attributes;
286	       attribute != NULL && attribute->name != NULL;
287	       attribute++)
288	    if (strcmp (attribute->name, *p) == 0)
289	      break;
290
291	  if (attribute == NULL || attribute->name == NULL)
292	    gdb_xml_debug (parser, _("Ignoring unknown attribute %s"), *p);
293	}
294    }
295
296  /* Call the element handler if there is one.  */
297  if (element->start_handler)
298    element->start_handler (parser, element, parser->user_data, attributes);
299
300  /* Fill in a new scope level.  */
301  scope = VEC_last (scope_level_s, parser->scopes);
302  scope->element = element;
303  scope->elements = element->children;
304
305  do_cleanups (back_to);
306}
307
308/* Wrapper for gdb_xml_start_element, to prevent throwing exceptions
309   through expat.  */
310
311static void
312gdb_xml_start_element_wrapper (void *data, const XML_Char *name,
313			       const XML_Char **attrs)
314{
315  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
316
317  if (parser->error.reason < 0)
318    return;
319
320  TRY
321    {
322      gdb_xml_start_element (data, name, attrs);
323    }
324  CATCH (ex, RETURN_MASK_ALL)
325    {
326      parser->error = ex;
327#ifdef HAVE_XML_STOPPARSER
328      XML_StopParser (parser->expat_parser, XML_FALSE);
329#endif
330    }
331  END_CATCH
332}
333
334/* Handle the end of an element.  DATA is our local XML parser, and
335   NAME is the current element.  */
336
337static void
338gdb_xml_end_element (void *data, const XML_Char *name)
339{
340  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
341  struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
342  const struct gdb_xml_element *element;
343  unsigned int seen;
344
345  gdb_xml_debug (parser, _("Leaving element <%s>"), name);
346
347  for (element = scope->elements, seen = 1;
348       element != NULL && element->name != NULL;
349       element++, seen <<= 1)
350    if ((scope->seen & seen) == 0
351	&& (element->flags & GDB_XML_EF_OPTIONAL) == 0)
352      gdb_xml_error (parser, _("Required element <%s> is missing"),
353		     element->name);
354
355  /* Call the element processor.  */
356  if (scope->element != NULL && scope->element->end_handler)
357    {
358      const char *scope_body;
359
360      if (scope->body == NULL)
361	scope_body = "";
362      else
363	{
364	  int length;
365
366	  length = obstack_object_size (scope->body);
367	  obstack_1grow (scope->body, '\0');
368	  char *body = (char *) obstack_finish (scope->body);
369
370	  /* Strip leading and trailing whitespace.  */
371	  while (length > 0 && ISSPACE (body[length-1]))
372	    body[--length] = '\0';
373	  while (*body && ISSPACE (*body))
374	    body++;
375
376	  scope_body = body;
377	}
378
379      scope->element->end_handler (parser, scope->element, parser->user_data,
380				   scope_body);
381    }
382  else if (scope->element == NULL)
383    XML_DefaultCurrent (parser->expat_parser);
384
385  /* Pop the scope level.  */
386  if (scope->body)
387    {
388      obstack_free (scope->body, NULL);
389      xfree (scope->body);
390    }
391  VEC_pop (scope_level_s, parser->scopes);
392}
393
394/* Wrapper for gdb_xml_end_element, to prevent throwing exceptions
395   through expat.  */
396
397static void
398gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
399{
400  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
401
402  if (parser->error.reason < 0)
403    return;
404
405  TRY
406    {
407      gdb_xml_end_element (data, name);
408    }
409  CATCH (ex, RETURN_MASK_ALL)
410    {
411      parser->error = ex;
412#ifdef HAVE_XML_STOPPARSER
413      XML_StopParser (parser->expat_parser, XML_FALSE);
414#endif
415    }
416  END_CATCH
417}
418
419/* Free a parser and all its associated state.  */
420
421static void
422gdb_xml_cleanup (void *arg)
423{
424  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) arg;
425  struct scope_level *scope;
426  int ix;
427
428  XML_ParserFree (parser->expat_parser);
429
430  /* Clean up the scopes.  */
431  for (ix = 0; VEC_iterate (scope_level_s, parser->scopes, ix, scope); ix++)
432    if (scope->body)
433      {
434	obstack_free (scope->body, NULL);
435	xfree (scope->body);
436      }
437  VEC_free (scope_level_s, parser->scopes);
438
439  xfree (parser);
440}
441
442/* Initialize a parser and store it to *PARSER_RESULT.  Register a
443   cleanup to destroy the parser.  */
444
445static struct cleanup *
446gdb_xml_create_parser_and_cleanup (const char *name,
447				   const struct gdb_xml_element *elements,
448				   void *user_data,
449				   struct gdb_xml_parser **parser_result)
450{
451  struct gdb_xml_parser *parser;
452  struct scope_level start_scope;
453  struct cleanup *result;
454
455  /* Initialize the parser.  */
456  parser = XCNEW (struct gdb_xml_parser);
457  parser->expat_parser = XML_ParserCreateNS (NULL, '!');
458  if (parser->expat_parser == NULL)
459    {
460      xfree (parser);
461      malloc_failure (0);
462    }
463
464  parser->name = name;
465
466  parser->user_data = user_data;
467  XML_SetUserData (parser->expat_parser, parser);
468
469  /* Set the callbacks.  */
470  XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper,
471			 gdb_xml_end_element_wrapper);
472  XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text);
473
474  /* Initialize the outer scope.  */
475  memset (&start_scope, 0, sizeof (start_scope));
476  start_scope.elements = elements;
477  VEC_safe_push (scope_level_s, parser->scopes, &start_scope);
478
479  *parser_result = parser;
480  return make_cleanup (gdb_xml_cleanup, parser);
481}
482
483/* External entity handler.  The only external entities we support
484   are those compiled into GDB (we do not fetch entities from the
485   target).  */
486
487static int XMLCALL
488gdb_xml_fetch_external_entity (XML_Parser expat_parser,
489			       const XML_Char *context,
490			       const XML_Char *base,
491			       const XML_Char *systemId,
492			       const XML_Char *publicId)
493{
494  struct gdb_xml_parser *parser
495    = (struct gdb_xml_parser *) XML_GetUserData (expat_parser);
496  XML_Parser entity_parser;
497  const char *text;
498  enum XML_Status status;
499
500  if (systemId == NULL)
501    {
502      text = fetch_xml_builtin (parser->dtd_name);
503      if (text == NULL)
504	internal_error (__FILE__, __LINE__,
505			_("could not locate built-in DTD %s"),
506			parser->dtd_name);
507    }
508  else
509    {
510      text = fetch_xml_builtin (systemId);
511      if (text == NULL)
512	return XML_STATUS_ERROR;
513    }
514
515  entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
516
517  /* Don't use our handlers for the contents of the DTD.  Just let expat
518     process it.  */
519  XML_SetElementHandler (entity_parser, NULL, NULL);
520  XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
521  XML_SetXmlDeclHandler (entity_parser, NULL);
522  XML_SetDefaultHandler (entity_parser, NULL);
523  XML_SetUserData (entity_parser, NULL);
524
525  status = XML_Parse (entity_parser, text, strlen (text), 1);
526
527  XML_ParserFree (entity_parser);
528  return status;
529}
530
531/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
532   with PARSER.  */
533
534void
535gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
536{
537  enum XML_Error err;
538
539  parser->dtd_name = dtd_name;
540
541  XML_SetParamEntityParsing (parser->expat_parser,
542			     XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
543  XML_SetExternalEntityRefHandler (parser->expat_parser,
544				   gdb_xml_fetch_external_entity);
545
546  /* Even if no DTD is provided, use the built-in DTD anyway.  */
547  err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
548  if (err != XML_ERROR_NONE)
549    internal_error (__FILE__, __LINE__,
550		    _("XML_UseForeignDTD failed: %s"),
551		    XML_ErrorString (err));
552}
553
554/* Invoke PARSER on BUFFER.  BUFFER is the data to parse, which
555   should be NUL-terminated.
556
557   The return value is 0 for success or -1 for error.  It may throw,
558   but only if something unexpected goes wrong during parsing; parse
559   errors will be caught, warned about, and reported as failure.  */
560
561int
562gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
563{
564  enum XML_Status status;
565  const char *error_string;
566
567  gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
568
569  status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
570
571  if (status == XML_STATUS_OK && parser->error.reason == 0)
572    return 0;
573
574  if (parser->error.reason == RETURN_ERROR
575      && parser->error.error == XML_PARSE_ERROR)
576    {
577      gdb_assert (parser->error.message != NULL);
578      error_string = parser->error.message;
579    }
580  else if (status == XML_STATUS_ERROR)
581    {
582      enum XML_Error err = XML_GetErrorCode (parser->expat_parser);
583
584      error_string = XML_ErrorString (err);
585    }
586  else
587    {
588      gdb_assert (parser->error.reason < 0);
589      throw_exception (parser->error);
590    }
591
592  if (parser->last_line != 0)
593    warning (_("while parsing %s (at line %d): %s"), parser->name,
594	     parser->last_line, error_string);
595  else
596    warning (_("while parsing %s: %s"), parser->name, error_string);
597
598  return -1;
599}
600
601int
602gdb_xml_parse_quick (const char *name, const char *dtd_name,
603		     const struct gdb_xml_element *elements,
604		     const char *document, void *user_data)
605{
606  struct gdb_xml_parser *parser;
607  struct cleanup *back_to;
608  int result;
609
610  back_to = gdb_xml_create_parser_and_cleanup (name, elements,
611					       user_data, &parser);
612  if (dtd_name != NULL)
613    gdb_xml_use_dtd (parser, dtd_name);
614  result = gdb_xml_parse (parser, document);
615
616  do_cleanups (back_to);
617
618  return result;
619}
620
621/* Parse a field VALSTR that we expect to contain an integer value.
622   The integer is returned in *VALP.  The string is parsed with an
623   equivalent to strtoul.
624
625   Returns 0 for success, -1 for error.  */
626
627static int
628xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
629{
630  const char *endptr;
631  ULONGEST result;
632
633  if (*valstr == '\0')
634    return -1;
635
636  result = strtoulst (valstr, &endptr, 0);
637  if (*endptr != '\0')
638    return -1;
639
640  *valp = result;
641  return 0;
642}
643
644/* Parse an integer string into a ULONGEST and return it, or call
645   gdb_xml_error if it could not be parsed.  */
646
647ULONGEST
648gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
649{
650  ULONGEST result;
651
652  if (xml_parse_unsigned_integer (value, &result) != 0)
653    gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
654
655  return result;
656}
657
658/* Parse an integer attribute into a ULONGEST.  */
659
660void *
661gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
662			     const struct gdb_xml_attribute *attribute,
663			     const char *value)
664{
665  ULONGEST result;
666  void *ret;
667
668  if (xml_parse_unsigned_integer (value, &result) != 0)
669    gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
670		   attribute->name, value);
671
672  ret = XNEW (ULONGEST);
673  memcpy (ret, &result, sizeof (result));
674  return ret;
675}
676
677/* A handler_data for yes/no boolean values.  */
678
679const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
680  { "yes", 1 },
681  { "no", 0 },
682  { NULL, 0 }
683};
684
685/* Map NAME to VALUE.  A struct gdb_xml_enum * should be saved as the
686   value of handler_data when using gdb_xml_parse_attr_enum to parse a
687   fixed list of possible strings.  The list is terminated by an entry
688   with NAME == NULL.  */
689
690void *
691gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
692			 const struct gdb_xml_attribute *attribute,
693			 const char *value)
694{
695  const struct gdb_xml_enum *enums
696    = (const struct gdb_xml_enum *) attribute->handler_data;
697  void *ret;
698
699  for (enums = (const struct gdb_xml_enum *) attribute->handler_data;
700       enums->name != NULL; enums++)
701    if (strcasecmp (enums->name, value) == 0)
702      break;
703
704  if (enums->name == NULL)
705    gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
706		 attribute->name, value);
707
708  ret = xmalloc (sizeof (enums->value));
709  memcpy (ret, &enums->value, sizeof (enums->value));
710  return ret;
711}
712
713
714/* XInclude processing.  This is done as a separate step from actually
715   parsing the document, so that we can produce a single combined XML
716   document - e.g. to hand to a front end or to simplify comparing two
717   documents.  We make extensive use of XML_DefaultCurrent, to pass
718   input text directly into the output without reformatting or
719   requoting it.
720
721   We output the DOCTYPE declaration for the first document unchanged,
722   if present, and discard DOCTYPEs from included documents.  Only the
723   one we pass through here is used when we feed the result back to
724   expat.  The XInclude standard explicitly does not discuss
725   validation of the result; we choose to apply the same DTD applied
726   to the outermost document.
727
728   We can not simply include the external DTD subset in the document
729   as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
730   only in external subsets.  But if we do not pass the DTD into the
731   output at all, default values will not be filled in.
732
733   We don't pass through any <?xml> declaration because we generate
734   UTF-8, not whatever the input encoding was.  */
735
736struct xinclude_parsing_data
737{
738  /* The obstack to build the output in.  */
739  struct obstack obstack;
740
741  /* A count indicating whether we are in an element whose
742     children should not be copied to the output, and if so,
743     how deep we are nested.  This is used for anything inside
744     an xi:include, and for the DTD.  */
745  int skip_depth;
746
747  /* The number of <xi:include> elements currently being processed,
748     to detect loops.  */
749  int include_depth;
750
751  /* A function to call to obtain additional features, and its
752     baton.  */
753  xml_fetch_another fetcher;
754  void *fetcher_baton;
755};
756
757static void
758xinclude_start_include (struct gdb_xml_parser *parser,
759			const struct gdb_xml_element *element,
760			void *user_data, VEC(gdb_xml_value_s) *attributes)
761{
762  struct xinclude_parsing_data *data
763    = (struct xinclude_parsing_data *) user_data;
764  char *href = (char *) xml_find_attribute (attributes, "href")->value;
765  struct cleanup *back_to;
766  char *text, *output;
767
768  gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
769
770  if (data->include_depth > MAX_XINCLUDE_DEPTH)
771    gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
772		   MAX_XINCLUDE_DEPTH);
773
774  text = data->fetcher (href, data->fetcher_baton);
775  if (text == NULL)
776    gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
777  back_to = make_cleanup (xfree, text);
778
779  output = xml_process_xincludes (parser->name, text, data->fetcher,
780				  data->fetcher_baton,
781				  data->include_depth + 1);
782  if (output == NULL)
783    gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
784
785  obstack_grow (&data->obstack, output, strlen (output));
786  xfree (output);
787
788  do_cleanups (back_to);
789
790  data->skip_depth++;
791}
792
793static void
794xinclude_end_include (struct gdb_xml_parser *parser,
795		      const struct gdb_xml_element *element,
796		      void *user_data, const char *body_text)
797{
798  struct xinclude_parsing_data *data
799    = (struct xinclude_parsing_data *) user_data;
800
801  data->skip_depth--;
802}
803
804static void XMLCALL
805xml_xinclude_default (void *data_, const XML_Char *s, int len)
806{
807  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
808  struct xinclude_parsing_data *data
809    = (struct xinclude_parsing_data *) parser->user_data;
810
811  /* If we are inside of e.g. xi:include or the DTD, don't save this
812     string.  */
813  if (data->skip_depth)
814    return;
815
816  /* Otherwise just add it to the end of the document we're building
817     up.  */
818  obstack_grow (&data->obstack, s, len);
819}
820
821static void XMLCALL
822xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
823			    const XML_Char *sysid, const XML_Char *pubid,
824			    int has_internal_subset)
825{
826  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
827  struct xinclude_parsing_data *data
828    = (struct xinclude_parsing_data *) parser->user_data;
829
830  /* Don't print out the doctype, or the contents of the DTD internal
831     subset, if any.  */
832  data->skip_depth++;
833}
834
835static void XMLCALL
836xml_xinclude_end_doctype (void *data_)
837{
838  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
839  struct xinclude_parsing_data *data
840    = (struct xinclude_parsing_data *) parser->user_data;
841
842  data->skip_depth--;
843}
844
845static void XMLCALL
846xml_xinclude_xml_decl (void *data_, const XML_Char *version,
847		       const XML_Char *encoding, int standalone)
848{
849  /* Do nothing - this function prevents the default handler from
850     being called, thus suppressing the XML declaration from the
851     output.  */
852}
853
854static void
855xml_xinclude_cleanup (void *data_)
856{
857  struct xinclude_parsing_data *data = (struct xinclude_parsing_data *) data_;
858
859  obstack_free (&data->obstack, NULL);
860  xfree (data);
861}
862
863const struct gdb_xml_attribute xinclude_attributes[] = {
864  { "href", GDB_XML_AF_NONE, NULL, NULL },
865  { NULL, GDB_XML_AF_NONE, NULL, NULL }
866};
867
868const struct gdb_xml_element xinclude_elements[] = {
869  { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
870    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
871    xinclude_start_include, xinclude_end_include },
872  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
873};
874
875/* The main entry point for <xi:include> processing.  */
876
877char *
878xml_process_xincludes (const char *name, const char *text,
879		       xml_fetch_another fetcher, void *fetcher_baton,
880		       int depth)
881{
882  struct gdb_xml_parser *parser;
883  struct xinclude_parsing_data *data;
884  struct cleanup *back_to;
885  char *result = NULL;
886
887  data = XCNEW (struct xinclude_parsing_data);
888  obstack_init (&data->obstack);
889  back_to = make_cleanup (xml_xinclude_cleanup, data);
890
891  gdb_xml_create_parser_and_cleanup (name, xinclude_elements,
892				     data, &parser);
893  parser->is_xinclude = 1;
894
895  data->include_depth = depth;
896  data->fetcher = fetcher;
897  data->fetcher_baton = fetcher_baton;
898
899  XML_SetCharacterDataHandler (parser->expat_parser, NULL);
900  XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
901
902  /* Always discard the XML version declarations; the only important
903     thing this provides is encoding, and our result will have been
904     converted to UTF-8.  */
905  XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
906
907  if (depth > 0)
908    /* Discard the doctype for included documents.  */
909    XML_SetDoctypeDeclHandler (parser->expat_parser,
910			       xml_xinclude_start_doctype,
911			       xml_xinclude_end_doctype);
912
913  gdb_xml_use_dtd (parser, "xinclude.dtd");
914
915  if (gdb_xml_parse (parser, text) == 0)
916    {
917      obstack_1grow (&data->obstack, '\0');
918      result = xstrdup ((const char *) obstack_finish (&data->obstack));
919
920      if (depth == 0)
921	gdb_xml_debug (parser, _("XInclude processing succeeded."));
922    }
923  else
924    result = NULL;
925
926  do_cleanups (back_to);
927  return result;
928}
929#endif /* HAVE_LIBEXPAT */
930
931
932/* Return an XML document which was compiled into GDB, from
933   the given FILENAME, or NULL if the file was not compiled in.  */
934
935const char *
936fetch_xml_builtin (const char *filename)
937{
938  const char *(*p)[2];
939
940  for (p = xml_builtin; (*p)[0]; p++)
941    if (strcmp ((*p)[0], filename) == 0)
942      return (*p)[1];
943
944  return NULL;
945}
946
947/* A to_xfer_partial helper function which reads XML files which were
948   compiled into GDB.  The target may call this function from its own
949   to_xfer_partial handler, after converting object and annex to the
950   appropriate filename.  */
951
952LONGEST
953xml_builtin_xfer_partial (const char *filename,
954			  gdb_byte *readbuf, const gdb_byte *writebuf,
955			  ULONGEST offset, LONGEST len)
956{
957  const char *buf;
958  LONGEST len_avail;
959
960  gdb_assert (readbuf != NULL && writebuf == NULL);
961  gdb_assert (filename != NULL);
962
963  buf = fetch_xml_builtin (filename);
964  if (buf == NULL)
965    return -1;
966
967  len_avail = strlen (buf);
968  if (offset >= len_avail)
969    return 0;
970
971  if (len > len_avail - offset)
972    len = len_avail - offset;
973  memcpy (readbuf, buf + offset, len);
974  return len;
975}
976
977
978static void
979show_debug_xml (struct ui_file *file, int from_tty,
980		struct cmd_list_element *c, const char *value)
981{
982  fprintf_filtered (file, _("XML debugging is %s.\n"), value);
983}
984
985void
986obstack_xml_printf (struct obstack *obstack, const char *format, ...)
987{
988  va_list ap;
989  const char *f;
990  const char *prev;
991  int percent = 0;
992
993  va_start (ap, format);
994
995  prev = format;
996  for (f = format; *f; f++)
997    {
998      if (percent)
999       {
1000         switch (*f)
1001           {
1002           case 's':
1003             {
1004               char *p;
1005               char *a = va_arg (ap, char *);
1006
1007               obstack_grow (obstack, prev, f - prev - 1);
1008               p = xml_escape_text (a);
1009               obstack_grow_str (obstack, p);
1010               xfree (p);
1011               prev = f + 1;
1012             }
1013             break;
1014           }
1015         percent = 0;
1016       }
1017      else if (*f == '%')
1018       percent = 1;
1019    }
1020
1021  obstack_grow_str (obstack, prev);
1022  va_end (ap);
1023}
1024
1025char *
1026xml_fetch_content_from_file (const char *filename, void *baton)
1027{
1028  const char *dirname = (const char *) baton;
1029  FILE *file;
1030  struct cleanup *back_to;
1031  char *text;
1032  size_t len, offset;
1033
1034  if (dirname && *dirname)
1035    {
1036      char *fullname = concat (dirname, "/", filename, (char *) NULL);
1037
1038      if (fullname == NULL)
1039	malloc_failure (0);
1040      file = gdb_fopen_cloexec (fullname, FOPEN_RT);
1041      xfree (fullname);
1042    }
1043  else
1044    file = gdb_fopen_cloexec (filename, FOPEN_RT);
1045
1046  if (file == NULL)
1047    return NULL;
1048
1049  back_to = make_cleanup_fclose (file);
1050
1051  /* Read in the whole file, one chunk at a time.  */
1052  len = 4096;
1053  offset = 0;
1054  text = (char *) xmalloc (len);
1055  make_cleanup (free_current_contents, &text);
1056  while (1)
1057    {
1058      size_t bytes_read;
1059
1060      /* Continue reading where the last read left off.  Leave at least
1061	 one byte so that we can NUL-terminate the result.  */
1062      bytes_read = fread (text + offset, 1, len - offset - 1, file);
1063      if (ferror (file))
1064	{
1065	  warning (_("Read error from \"%s\""), filename);
1066	  do_cleanups (back_to);
1067	  return NULL;
1068	}
1069
1070      offset += bytes_read;
1071
1072      if (feof (file))
1073	break;
1074
1075      len = len * 2;
1076      text = (char *) xrealloc (text, len);
1077    }
1078
1079  fclose (file);
1080  discard_cleanups (back_to);
1081
1082  text[offset] = '\0';
1083  return text;
1084}
1085
1086void _initialize_xml_support (void);
1087
1088void
1089_initialize_xml_support (void)
1090{
1091  add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1092			   _("Set XML parser debugging."),
1093			   _("Show XML parser debugging."),
1094			   _("When set, debugging messages for XML parsers "
1095			     "are displayed."),
1096			   NULL, show_debug_xml,
1097			   &setdebuglist, &showdebuglist);
1098}
1099