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