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