xref: /dragonfly/contrib/gdb-7/gdb/xml-support.c (revision dcd37f7d)
1 /* Helper routines for parsing XML using Expat.
2 
3    Copyright (C) 2006, 2007, 2008, 2009 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.  */
29 static 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.  */
45 struct 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 };
60 typedef struct scope_level scope_level_s;
61 DEF_VEC_O(scope_level_s);
62 
63 /* The parser itself, and our additional state.  */
64 struct 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 
85 static void
86 gdb_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 
105 void
106 gdb_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 
129 void
130 gdb_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 
142 static void
143 gdb_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 
158 static void
159 gdb_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 
297 static void
298 gdb_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 
323 static void
324 gdb_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 
381 static void
382 gdb_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 
405 static void
406 gdb_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 
429 struct gdb_xml_parser *
430 gdb_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 
470 static int XMLCALL
471 gdb_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 
515 void
516 gdb_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 
541 int
542 gdb_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 
586 static int
587 xml_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 
606 ULONGEST
607 gdb_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 
619 void *
620 gdb_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 
638 const 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 
649 void *
650 gdb_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 
693 struct 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 
714 static void
715 xinclude_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 
750 static void
751 xinclude_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 
760 static void XMLCALL
761 xml_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 
776 static void XMLCALL
777 xml_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 
789 static void XMLCALL
790 xml_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 
798 static void XMLCALL
799 xml_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 
807 static void
808 xml_xinclude_cleanup (void *data_)
809 {
810   struct xinclude_parsing_data *data = data_;
811 
812   obstack_free (&data->obstack, NULL);
813   xfree (data);
814 }
815 
816 const struct gdb_xml_attribute xinclude_attributes[] = {
817   { "href", GDB_XML_AF_NONE, NULL, NULL },
818   { NULL, GDB_XML_AF_NONE, NULL, NULL }
819 };
820 
821 const 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 
830 char *
831 xml_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 
888 const char *
889 fetch_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 
905 LONGEST
906 xml_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 
931 static void
932 show_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 
941 char *
942 xml_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 
1000 void
1001 obstack_xml_printf (struct obstack *obstack, const char *format, ...)
1002 {
1003   va_list ap;
1004   const char *f;
1005   const char *prev;
1006   int percent = 0;
1007 
1008   va_start (ap, format);
1009 
1010   prev = format;
1011   for (f = format; *f; f++)
1012     {
1013       if (percent)
1014        {
1015          switch (*f)
1016            {
1017            case 's':
1018              {
1019                char *p;
1020                char *a = va_arg (ap, char *);
1021                obstack_grow (obstack, prev, f - prev - 1);
1022                p = xml_escape_text (a);
1023                obstack_grow_str (obstack, p);
1024                xfree (p);
1025                prev = f + 1;
1026              }
1027              break;
1028            }
1029          percent = 0;
1030        }
1031       else if (*f == '%')
1032        percent = 1;
1033     }
1034 
1035   obstack_grow_str (obstack, prev);
1036   va_end (ap);
1037 }
1038 
1039 char *
1040 xml_fetch_content_from_file (const char *filename, void *baton)
1041 {
1042   const char *dirname = baton;
1043   FILE *file;
1044   struct cleanup *back_to;
1045   char *text;
1046   size_t len, offset;
1047 
1048   if (dirname && *dirname)
1049     {
1050       char *fullname = concat (dirname, "/", filename, (char *) NULL);
1051       if (fullname == NULL)
1052 	nomem (0);
1053       file = fopen (fullname, FOPEN_RT);
1054       xfree (fullname);
1055     }
1056   else
1057     file = fopen (filename, FOPEN_RT);
1058 
1059   if (file == NULL)
1060     return NULL;
1061 
1062   back_to = make_cleanup_fclose (file);
1063 
1064   /* Read in the whole file, one chunk at a time.  */
1065   len = 4096;
1066   offset = 0;
1067   text = xmalloc (len);
1068   make_cleanup (free_current_contents, &text);
1069   while (1)
1070     {
1071       size_t bytes_read;
1072 
1073       /* Continue reading where the last read left off.  Leave at least
1074 	 one byte so that we can NUL-terminate the result.  */
1075       bytes_read = fread (text + offset, 1, len - offset - 1, file);
1076       if (ferror (file))
1077 	{
1078 	  warning (_("Read error from \"%s\""), filename);
1079 	  do_cleanups (back_to);
1080 	  return NULL;
1081 	}
1082 
1083       offset += bytes_read;
1084 
1085       if (feof (file))
1086 	break;
1087 
1088       len = len * 2;
1089       text = xrealloc (text, len);
1090     }
1091 
1092   fclose (file);
1093   discard_cleanups (back_to);
1094 
1095   text[offset] = '\0';
1096   return text;
1097 }
1098 
1099 void _initialize_xml_support (void);
1100 
1101 void
1102 _initialize_xml_support (void)
1103 {
1104   add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1105 			   _("Set XML parser debugging."),
1106 			   _("Show XML parser debugging."),
1107 			   _("When set, debugging messages for XML parsers "
1108 			     "are displayed."),
1109 			   NULL, show_debug_xml,
1110 			   &setdebuglist, &showdebuglist);
1111 }
1112