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