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