xml-support.c revision 1.6
1/* Helper routines for parsing XML using Expat.
2
3   Copyright (C) 2006-2016 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      char *body;
359
360      if (scope->body == NULL)
361	body = "";
362      else
363	{
364	  int length;
365
366	  length = obstack_object_size (scope->body);
367	  obstack_1grow (scope->body, '\0');
368	  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
377      scope->element->end_handler (parser, scope->element, parser->user_data,
378				   body);
379    }
380  else if (scope->element == NULL)
381    XML_DefaultCurrent (parser->expat_parser);
382
383  /* Pop the scope level.  */
384  if (scope->body)
385    {
386      obstack_free (scope->body, NULL);
387      xfree (scope->body);
388    }
389  VEC_pop (scope_level_s, parser->scopes);
390}
391
392/* Wrapper for gdb_xml_end_element, to prevent throwing exceptions
393   through expat.  */
394
395static void
396gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
397{
398  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
399
400  if (parser->error.reason < 0)
401    return;
402
403  TRY
404    {
405      gdb_xml_end_element (data, name);
406    }
407  CATCH (ex, RETURN_MASK_ALL)
408    {
409      parser->error = ex;
410#ifdef HAVE_XML_STOPPARSER
411      XML_StopParser (parser->expat_parser, XML_FALSE);
412#endif
413    }
414  END_CATCH
415}
416
417/* Free a parser and all its associated state.  */
418
419static void
420gdb_xml_cleanup (void *arg)
421{
422  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) arg;
423  struct scope_level *scope;
424  int ix;
425
426  XML_ParserFree (parser->expat_parser);
427
428  /* Clean up the scopes.  */
429  for (ix = 0; VEC_iterate (scope_level_s, parser->scopes, ix, scope); ix++)
430    if (scope->body)
431      {
432	obstack_free (scope->body, NULL);
433	xfree (scope->body);
434      }
435  VEC_free (scope_level_s, parser->scopes);
436
437  xfree (parser);
438}
439
440/* Initialize a parser and store it to *PARSER_RESULT.  Register a
441   cleanup to destroy the parser.  */
442
443static struct cleanup *
444gdb_xml_create_parser_and_cleanup (const char *name,
445				   const struct gdb_xml_element *elements,
446				   void *user_data,
447				   struct gdb_xml_parser **parser_result)
448{
449  struct gdb_xml_parser *parser;
450  struct scope_level start_scope;
451  struct cleanup *result;
452
453  /* Initialize the parser.  */
454  parser = XCNEW (struct gdb_xml_parser);
455  parser->expat_parser = XML_ParserCreateNS (NULL, '!');
456  if (parser->expat_parser == NULL)
457    {
458      xfree (parser);
459      malloc_failure (0);
460    }
461
462  parser->name = name;
463
464  parser->user_data = user_data;
465  XML_SetUserData (parser->expat_parser, parser);
466
467  /* Set the callbacks.  */
468  XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper,
469			 gdb_xml_end_element_wrapper);
470  XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text);
471
472  /* Initialize the outer scope.  */
473  memset (&start_scope, 0, sizeof (start_scope));
474  start_scope.elements = elements;
475  VEC_safe_push (scope_level_s, parser->scopes, &start_scope);
476
477  *parser_result = parser;
478  return make_cleanup (gdb_xml_cleanup, parser);
479}
480
481/* External entity handler.  The only external entities we support
482   are those compiled into GDB (we do not fetch entities from the
483   target).  */
484
485static int XMLCALL
486gdb_xml_fetch_external_entity (XML_Parser expat_parser,
487			       const XML_Char *context,
488			       const XML_Char *base,
489			       const XML_Char *systemId,
490			       const XML_Char *publicId)
491{
492  struct gdb_xml_parser *parser
493    = (struct gdb_xml_parser *) XML_GetUserData (expat_parser);
494  XML_Parser entity_parser;
495  const char *text;
496  enum XML_Status status;
497
498  if (systemId == NULL)
499    {
500      text = fetch_xml_builtin (parser->dtd_name);
501      if (text == NULL)
502	internal_error (__FILE__, __LINE__,
503			_("could not locate built-in DTD %s"),
504			parser->dtd_name);
505    }
506  else
507    {
508      text = fetch_xml_builtin (systemId);
509      if (text == NULL)
510	return XML_STATUS_ERROR;
511    }
512
513  entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
514
515  /* Don't use our handlers for the contents of the DTD.  Just let expat
516     process it.  */
517  XML_SetElementHandler (entity_parser, NULL, NULL);
518  XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
519  XML_SetXmlDeclHandler (entity_parser, NULL);
520  XML_SetDefaultHandler (entity_parser, NULL);
521  XML_SetUserData (entity_parser, NULL);
522
523  status = XML_Parse (entity_parser, text, strlen (text), 1);
524
525  XML_ParserFree (entity_parser);
526  return status;
527}
528
529/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
530   with PARSER.  */
531
532void
533gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
534{
535  enum XML_Error err;
536
537  parser->dtd_name = dtd_name;
538
539  XML_SetParamEntityParsing (parser->expat_parser,
540			     XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
541  XML_SetExternalEntityRefHandler (parser->expat_parser,
542				   gdb_xml_fetch_external_entity);
543
544  /* Even if no DTD is provided, use the built-in DTD anyway.  */
545  err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
546  if (err != XML_ERROR_NONE)
547    internal_error (__FILE__, __LINE__,
548		    _("XML_UseForeignDTD failed: %s"),
549		    XML_ErrorString (err));
550}
551
552/* Invoke PARSER on BUFFER.  BUFFER is the data to parse, which
553   should be NUL-terminated.
554
555   The return value is 0 for success or -1 for error.  It may throw,
556   but only if something unexpected goes wrong during parsing; parse
557   errors will be caught, warned about, and reported as failure.  */
558
559int
560gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
561{
562  enum XML_Status status;
563  const char *error_string;
564
565  gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
566
567  status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
568
569  if (status == XML_STATUS_OK && parser->error.reason == 0)
570    return 0;
571
572  if (parser->error.reason == RETURN_ERROR
573      && parser->error.error == XML_PARSE_ERROR)
574    {
575      gdb_assert (parser->error.message != NULL);
576      error_string = parser->error.message;
577    }
578  else if (status == XML_STATUS_ERROR)
579    {
580      enum XML_Error err = XML_GetErrorCode (parser->expat_parser);
581
582      error_string = XML_ErrorString (err);
583    }
584  else
585    {
586      gdb_assert (parser->error.reason < 0);
587      throw_exception (parser->error);
588    }
589
590  if (parser->last_line != 0)
591    warning (_("while parsing %s (at line %d): %s"), parser->name,
592	     parser->last_line, error_string);
593  else
594    warning (_("while parsing %s: %s"), parser->name, error_string);
595
596  return -1;
597}
598
599int
600gdb_xml_parse_quick (const char *name, const char *dtd_name,
601		     const struct gdb_xml_element *elements,
602		     const char *document, void *user_data)
603{
604  struct gdb_xml_parser *parser;
605  struct cleanup *back_to;
606  int result;
607
608  back_to = gdb_xml_create_parser_and_cleanup (name, elements,
609					       user_data, &parser);
610  if (dtd_name != NULL)
611    gdb_xml_use_dtd (parser, dtd_name);
612  result = gdb_xml_parse (parser, document);
613
614  do_cleanups (back_to);
615
616  return result;
617}
618
619/* Parse a field VALSTR that we expect to contain an integer value.
620   The integer is returned in *VALP.  The string is parsed with an
621   equivalent to strtoul.
622
623   Returns 0 for success, -1 for error.  */
624
625static int
626xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
627{
628  const char *endptr;
629  ULONGEST result;
630
631  if (*valstr == '\0')
632    return -1;
633
634  result = strtoulst (valstr, &endptr, 0);
635  if (*endptr != '\0')
636    return -1;
637
638  *valp = result;
639  return 0;
640}
641
642/* Parse an integer string into a ULONGEST and return it, or call
643   gdb_xml_error if it could not be parsed.  */
644
645ULONGEST
646gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
647{
648  ULONGEST result;
649
650  if (xml_parse_unsigned_integer (value, &result) != 0)
651    gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
652
653  return result;
654}
655
656/* Parse an integer attribute into a ULONGEST.  */
657
658void *
659gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
660			     const struct gdb_xml_attribute *attribute,
661			     const char *value)
662{
663  ULONGEST result;
664  void *ret;
665
666  if (xml_parse_unsigned_integer (value, &result) != 0)
667    gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
668		   attribute->name, value);
669
670  ret = XNEW (ULONGEST);
671  memcpy (ret, &result, sizeof (result));
672  return ret;
673}
674
675/* A handler_data for yes/no boolean values.  */
676
677const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
678  { "yes", 1 },
679  { "no", 0 },
680  { NULL, 0 }
681};
682
683/* Map NAME to VALUE.  A struct gdb_xml_enum * should be saved as the
684   value of handler_data when using gdb_xml_parse_attr_enum to parse a
685   fixed list of possible strings.  The list is terminated by an entry
686   with NAME == NULL.  */
687
688void *
689gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
690			 const struct gdb_xml_attribute *attribute,
691			 const char *value)
692{
693  const struct gdb_xml_enum *enums
694    = (const struct gdb_xml_enum *) attribute->handler_data;
695  void *ret;
696
697  for (enums = (const struct gdb_xml_enum *) attribute->handler_data;
698       enums->name != NULL; enums++)
699    if (strcasecmp (enums->name, value) == 0)
700      break;
701
702  if (enums->name == NULL)
703    gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
704		 attribute->name, value);
705
706  ret = xmalloc (sizeof (enums->value));
707  memcpy (ret, &enums->value, sizeof (enums->value));
708  return ret;
709}
710
711
712/* XInclude processing.  This is done as a separate step from actually
713   parsing the document, so that we can produce a single combined XML
714   document - e.g. to hand to a front end or to simplify comparing two
715   documents.  We make extensive use of XML_DefaultCurrent, to pass
716   input text directly into the output without reformatting or
717   requoting it.
718
719   We output the DOCTYPE declaration for the first document unchanged,
720   if present, and discard DOCTYPEs from included documents.  Only the
721   one we pass through here is used when we feed the result back to
722   expat.  The XInclude standard explicitly does not discuss
723   validation of the result; we choose to apply the same DTD applied
724   to the outermost document.
725
726   We can not simply include the external DTD subset in the document
727   as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
728   only in external subsets.  But if we do not pass the DTD into the
729   output at all, default values will not be filled in.
730
731   We don't pass through any <?xml> declaration because we generate
732   UTF-8, not whatever the input encoding was.  */
733
734struct xinclude_parsing_data
735{
736  /* The obstack to build the output in.  */
737  struct obstack obstack;
738
739  /* A count indicating whether we are in an element whose
740     children should not be copied to the output, and if so,
741     how deep we are nested.  This is used for anything inside
742     an xi:include, and for the DTD.  */
743  int skip_depth;
744
745  /* The number of <xi:include> elements currently being processed,
746     to detect loops.  */
747  int include_depth;
748
749  /* A function to call to obtain additional features, and its
750     baton.  */
751  xml_fetch_another fetcher;
752  void *fetcher_baton;
753};
754
755static void
756xinclude_start_include (struct gdb_xml_parser *parser,
757			const struct gdb_xml_element *element,
758			void *user_data, VEC(gdb_xml_value_s) *attributes)
759{
760  struct xinclude_parsing_data *data
761    = (struct xinclude_parsing_data *) user_data;
762  char *href = (char *) xml_find_attribute (attributes, "href")->value;
763  struct cleanup *back_to;
764  char *text, *output;
765
766  gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
767
768  if (data->include_depth > MAX_XINCLUDE_DEPTH)
769    gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
770		   MAX_XINCLUDE_DEPTH);
771
772  text = data->fetcher (href, data->fetcher_baton);
773  if (text == NULL)
774    gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
775  back_to = make_cleanup (xfree, text);
776
777  output = xml_process_xincludes (parser->name, text, data->fetcher,
778				  data->fetcher_baton,
779				  data->include_depth + 1);
780  if (output == NULL)
781    gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
782
783  obstack_grow (&data->obstack, output, strlen (output));
784  xfree (output);
785
786  do_cleanups (back_to);
787
788  data->skip_depth++;
789}
790
791static void
792xinclude_end_include (struct gdb_xml_parser *parser,
793		      const struct gdb_xml_element *element,
794		      void *user_data, const char *body_text)
795{
796  struct xinclude_parsing_data *data
797    = (struct xinclude_parsing_data *) user_data;
798
799  data->skip_depth--;
800}
801
802static void XMLCALL
803xml_xinclude_default (void *data_, const XML_Char *s, int len)
804{
805  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
806  struct xinclude_parsing_data *data
807    = (struct xinclude_parsing_data *) parser->user_data;
808
809  /* If we are inside of e.g. xi:include or the DTD, don't save this
810     string.  */
811  if (data->skip_depth)
812    return;
813
814  /* Otherwise just add it to the end of the document we're building
815     up.  */
816  obstack_grow (&data->obstack, s, len);
817}
818
819static void XMLCALL
820xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
821			    const XML_Char *sysid, const XML_Char *pubid,
822			    int has_internal_subset)
823{
824  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
825  struct xinclude_parsing_data *data
826    = (struct xinclude_parsing_data *) parser->user_data;
827
828  /* Don't print out the doctype, or the contents of the DTD internal
829     subset, if any.  */
830  data->skip_depth++;
831}
832
833static void XMLCALL
834xml_xinclude_end_doctype (void *data_)
835{
836  struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
837  struct xinclude_parsing_data *data
838    = (struct xinclude_parsing_data *) parser->user_data;
839
840  data->skip_depth--;
841}
842
843static void XMLCALL
844xml_xinclude_xml_decl (void *data_, const XML_Char *version,
845		       const XML_Char *encoding, int standalone)
846{
847  /* Do nothing - this function prevents the default handler from
848     being called, thus suppressing the XML declaration from the
849     output.  */
850}
851
852static void
853xml_xinclude_cleanup (void *data_)
854{
855  struct xinclude_parsing_data *data = (struct xinclude_parsing_data *) data_;
856
857  obstack_free (&data->obstack, NULL);
858  xfree (data);
859}
860
861const struct gdb_xml_attribute xinclude_attributes[] = {
862  { "href", GDB_XML_AF_NONE, NULL, NULL },
863  { NULL, GDB_XML_AF_NONE, NULL, NULL }
864};
865
866const struct gdb_xml_element xinclude_elements[] = {
867  { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
868    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
869    xinclude_start_include, xinclude_end_include },
870  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
871};
872
873/* The main entry point for <xi:include> processing.  */
874
875char *
876xml_process_xincludes (const char *name, const char *text,
877		       xml_fetch_another fetcher, void *fetcher_baton,
878		       int depth)
879{
880  struct gdb_xml_parser *parser;
881  struct xinclude_parsing_data *data;
882  struct cleanup *back_to;
883  char *result = NULL;
884
885  data = XCNEW (struct xinclude_parsing_data);
886  obstack_init (&data->obstack);
887  back_to = make_cleanup (xml_xinclude_cleanup, data);
888
889  gdb_xml_create_parser_and_cleanup (name, xinclude_elements,
890				     data, &parser);
891  parser->is_xinclude = 1;
892
893  data->include_depth = depth;
894  data->fetcher = fetcher;
895  data->fetcher_baton = fetcher_baton;
896
897  XML_SetCharacterDataHandler (parser->expat_parser, NULL);
898  XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
899
900  /* Always discard the XML version declarations; the only important
901     thing this provides is encoding, and our result will have been
902     converted to UTF-8.  */
903  XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
904
905  if (depth > 0)
906    /* Discard the doctype for included documents.  */
907    XML_SetDoctypeDeclHandler (parser->expat_parser,
908			       xml_xinclude_start_doctype,
909			       xml_xinclude_end_doctype);
910
911  gdb_xml_use_dtd (parser, "xinclude.dtd");
912
913  if (gdb_xml_parse (parser, text) == 0)
914    {
915      obstack_1grow (&data->obstack, '\0');
916      result = xstrdup ((const char *) obstack_finish (&data->obstack));
917
918      if (depth == 0)
919	gdb_xml_debug (parser, _("XInclude processing succeeded."));
920    }
921  else
922    result = NULL;
923
924  do_cleanups (back_to);
925  return result;
926}
927#endif /* HAVE_LIBEXPAT */
928
929
930/* Return an XML document which was compiled into GDB, from
931   the given FILENAME, or NULL if the file was not compiled in.  */
932
933const char *
934fetch_xml_builtin (const char *filename)
935{
936  const char *(*p)[2];
937
938  for (p = xml_builtin; (*p)[0]; p++)
939    if (strcmp ((*p)[0], filename) == 0)
940      return (*p)[1];
941
942  return NULL;
943}
944
945/* A to_xfer_partial helper function which reads XML files which were
946   compiled into GDB.  The target may call this function from its own
947   to_xfer_partial handler, after converting object and annex to the
948   appropriate filename.  */
949
950LONGEST
951xml_builtin_xfer_partial (const char *filename,
952			  gdb_byte *readbuf, const gdb_byte *writebuf,
953			  ULONGEST offset, LONGEST len)
954{
955  const char *buf;
956  LONGEST len_avail;
957
958  gdb_assert (readbuf != NULL && writebuf == NULL);
959  gdb_assert (filename != NULL);
960
961  buf = fetch_xml_builtin (filename);
962  if (buf == NULL)
963    return -1;
964
965  len_avail = strlen (buf);
966  if (offset >= len_avail)
967    return 0;
968
969  if (len > len_avail - offset)
970    len = len_avail - offset;
971  memcpy (readbuf, buf + offset, len);
972  return len;
973}
974
975
976static void
977show_debug_xml (struct ui_file *file, int from_tty,
978		struct cmd_list_element *c, const char *value)
979{
980  fprintf_filtered (file, _("XML debugging is %s.\n"), value);
981}
982
983void
984obstack_xml_printf (struct obstack *obstack, const char *format, ...)
985{
986  va_list ap;
987  const char *f;
988  const char *prev;
989  int percent = 0;
990
991  va_start (ap, format);
992
993  prev = format;
994  for (f = format; *f; f++)
995    {
996      if (percent)
997       {
998         switch (*f)
999           {
1000           case 's':
1001             {
1002               char *p;
1003               char *a = va_arg (ap, char *);
1004
1005               obstack_grow (obstack, prev, f - prev - 1);
1006               p = xml_escape_text (a);
1007               obstack_grow_str (obstack, p);
1008               xfree (p);
1009               prev = f + 1;
1010             }
1011             break;
1012           }
1013         percent = 0;
1014       }
1015      else if (*f == '%')
1016       percent = 1;
1017    }
1018
1019  obstack_grow_str (obstack, prev);
1020  va_end (ap);
1021}
1022
1023char *
1024xml_fetch_content_from_file (const char *filename, void *baton)
1025{
1026  const char *dirname = (const char *) baton;
1027  FILE *file;
1028  struct cleanup *back_to;
1029  char *text;
1030  size_t len, offset;
1031
1032  if (dirname && *dirname)
1033    {
1034      char *fullname = concat (dirname, "/", filename, (char *) NULL);
1035
1036      if (fullname == NULL)
1037	malloc_failure (0);
1038      file = gdb_fopen_cloexec (fullname, FOPEN_RT);
1039      xfree (fullname);
1040    }
1041  else
1042    file = gdb_fopen_cloexec (filename, FOPEN_RT);
1043
1044  if (file == NULL)
1045    return NULL;
1046
1047  back_to = make_cleanup_fclose (file);
1048
1049  /* Read in the whole file, one chunk at a time.  */
1050  len = 4096;
1051  offset = 0;
1052  text = (char *) xmalloc (len);
1053  make_cleanup (free_current_contents, &text);
1054  while (1)
1055    {
1056      size_t bytes_read;
1057
1058      /* Continue reading where the last read left off.  Leave at least
1059	 one byte so that we can NUL-terminate the result.  */
1060      bytes_read = fread (text + offset, 1, len - offset - 1, file);
1061      if (ferror (file))
1062	{
1063	  warning (_("Read error from \"%s\""), filename);
1064	  do_cleanups (back_to);
1065	  return NULL;
1066	}
1067
1068      offset += bytes_read;
1069
1070      if (feof (file))
1071	break;
1072
1073      len = len * 2;
1074      text = (char *) xrealloc (text, len);
1075    }
1076
1077  fclose (file);
1078  discard_cleanups (back_to);
1079
1080  text[offset] = '\0';
1081  return text;
1082}
1083
1084void _initialize_xml_support (void);
1085
1086void
1087_initialize_xml_support (void)
1088{
1089  add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1090			   _("Set XML parser debugging."),
1091			   _("Show XML parser debugging."),
1092			   _("When set, debugging messages for XML parsers "
1093			     "are displayed."),
1094			   NULL, show_debug_xml,
1095			   &setdebuglist, &showdebuglist);
1096}
1097