xref: /dragonfly/contrib/gdb-7/gdb/xml-support.c (revision 678e8cc6)
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.  */
30 static 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.  */
46 struct 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 };
61 typedef struct scope_level scope_level_s;
62 DEF_VEC_O(scope_level_s);
63 
64 /* The parser itself, and our additional state.  */
65 struct 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 
86 static void
87 gdb_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 
106 void
107 gdb_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 
130 void
131 gdb_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 
144 struct gdb_xml_value *
145 xml_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 
159 static void
160 gdb_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 
175 static void
176 gdb_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 
314 static void
315 gdb_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 
340 static void
341 gdb_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 
398 static void
399 gdb_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 
422 static void
423 gdb_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 
446 static struct gdb_xml_parser *
447 gdb_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 
489 struct gdb_xml_parser *
490 gdb_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 
504 static int XMLCALL
505 gdb_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 
550 void
551 gdb_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 
577 int
578 gdb_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 
617 int
618 gdb_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 
643 static int
644 xml_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 
663 ULONGEST
664 gdb_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 
676 void *
677 gdb_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 
695 const 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 
706 void *
707 gdb_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 
750 struct 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 
771 static void
772 xinclude_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 
806 static void
807 xinclude_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 
816 static void XMLCALL
817 xml_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 
832 static void XMLCALL
833 xml_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 
845 static void XMLCALL
846 xml_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 
854 static void XMLCALL
855 xml_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 
863 static void
864 xml_xinclude_cleanup (void *data_)
865 {
866   struct xinclude_parsing_data *data = data_;
867 
868   obstack_free (&data->obstack, NULL);
869   xfree (data);
870 }
871 
872 const struct gdb_xml_attribute xinclude_attributes[] = {
873   { "href", GDB_XML_AF_NONE, NULL, NULL },
874   { NULL, GDB_XML_AF_NONE, NULL, NULL }
875 };
876 
877 const 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 
886 char *
887 xml_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 
943 const char *
944 fetch_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 
960 LONGEST
961 xml_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 
986 static void
987 show_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 
996 char *
997 xml_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 
1055 void
1056 obstack_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 
1095 char *
1096 xml_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 
1156 void _initialize_xml_support (void);
1157 
1158 void
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