run copyright.sh for 2011.
[external/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 struct gdb_xml_parser *
431 gdb_xml_create_parser_and_cleanup (const char *name,
432                                    const struct gdb_xml_element *elements,
433                                    void *user_data)
434 {
435   struct gdb_xml_parser *parser;
436   struct scope_level start_scope;
437
438   /* Initialize the parser.  */
439   parser = XZALLOC (struct gdb_xml_parser);
440   parser->expat_parser = XML_ParserCreateNS (NULL, '!');
441   if (parser->expat_parser == NULL)
442     {
443       xfree (parser);
444       nomem (0);
445     }
446
447   parser->name = name;
448
449   parser->user_data = user_data;
450   XML_SetUserData (parser->expat_parser, parser);
451
452   /* Set the callbacks.  */
453   XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper,
454                          gdb_xml_end_element_wrapper);
455   XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text);
456
457   /* Initialize the outer scope.  */
458   memset (&start_scope, 0, sizeof (start_scope));
459   start_scope.elements = elements;
460   VEC_safe_push (scope_level_s, parser->scopes, &start_scope);
461
462   make_cleanup (gdb_xml_cleanup, parser);
463
464   return parser;
465 }
466
467 /* External entity handler.  The only external entities we support
468    are those compiled into GDB (we do not fetch entities from the
469    target).  */
470
471 static int XMLCALL
472 gdb_xml_fetch_external_entity (XML_Parser expat_parser,
473                                const XML_Char *context,
474                                const XML_Char *base,
475                                const XML_Char *systemId,
476                                const XML_Char *publicId)
477 {
478   struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
479   XML_Parser entity_parser;
480   const char *text;
481   enum XML_Status status;
482
483   if (systemId == NULL)
484     {
485       text = fetch_xml_builtin (parser->dtd_name);
486       if (text == NULL)
487         internal_error (__FILE__, __LINE__, "could not locate built-in DTD %s",
488                         parser->dtd_name);
489     }
490   else
491     {
492       text = fetch_xml_builtin (systemId);
493       if (text == NULL)
494         return XML_STATUS_ERROR;
495     }
496
497   entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
498
499   /* Don't use our handlers for the contents of the DTD.  Just let expat
500      process it.  */
501   XML_SetElementHandler (entity_parser, NULL, NULL);
502   XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
503   XML_SetXmlDeclHandler (entity_parser, NULL);
504   XML_SetDefaultHandler (entity_parser, NULL);
505   XML_SetUserData (entity_parser, NULL);
506
507   status = XML_Parse (entity_parser, text, strlen (text), 1);
508
509   XML_ParserFree (entity_parser);
510   return status;
511 }
512
513 /* Associate DTD_NAME, which must be the name of a compiled-in DTD,
514    with PARSER.  */
515
516 void
517 gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
518 {
519   enum XML_Error err;
520
521   parser->dtd_name = dtd_name;
522
523   XML_SetParamEntityParsing (parser->expat_parser,
524                              XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
525   XML_SetExternalEntityRefHandler (parser->expat_parser,
526                                    gdb_xml_fetch_external_entity);
527
528   /* Even if no DTD is provided, use the built-in DTD anyway.  */
529   err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
530   if (err != XML_ERROR_NONE)
531     internal_error (__FILE__, __LINE__,
532                     "XML_UseForeignDTD failed: %s", XML_ErrorString (err));
533 }
534
535 /* Invoke PARSER on BUFFER.  BUFFER is the data to parse, which
536    should be NUL-terminated.
537
538    The return value is 0 for success or -1 for error.  It may throw,
539    but only if something unexpected goes wrong during parsing; parse
540    errors will be caught, warned about, and reported as failure.  */
541
542 int
543 gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
544 {
545   enum XML_Status status;
546   const char *error_string;
547
548   gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
549
550   status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
551
552   if (status == XML_STATUS_OK && parser->error.reason == 0)
553     return 0;
554
555   if (parser->error.reason == RETURN_ERROR
556       && parser->error.error == XML_PARSE_ERROR)
557     {
558       gdb_assert (parser->error.message != NULL);
559       error_string = parser->error.message;
560     }
561   else if (status == XML_STATUS_ERROR)
562     {
563       enum XML_Error err = XML_GetErrorCode (parser->expat_parser);
564
565       error_string = XML_ErrorString (err);
566     }
567   else
568     {
569       gdb_assert (parser->error.reason < 0);
570       throw_exception (parser->error);
571     }
572
573   if (parser->last_line != 0)
574     warning (_("while parsing %s (at line %d): %s"), parser->name,
575              parser->last_line, error_string);
576   else
577     warning (_("while parsing %s: %s"), parser->name, error_string);
578
579   return -1;
580 }
581
582 /* Parse a field VALSTR that we expect to contain an integer value.
583    The integer is returned in *VALP.  The string is parsed with an
584    equivalent to strtoul.
585
586    Returns 0 for success, -1 for error.  */
587
588 static int
589 xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
590 {
591   const char *endptr;
592   ULONGEST result;
593
594   if (*valstr == '\0')
595     return -1;
596
597   result = strtoulst (valstr, &endptr, 0);
598   if (*endptr != '\0')
599     return -1;
600
601   *valp = result;
602   return 0;
603 }
604
605 /* Parse an integer string into a ULONGEST and return it, or call
606    gdb_xml_error if it could not be parsed.  */
607
608 ULONGEST
609 gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
610 {
611   ULONGEST result;
612
613   if (xml_parse_unsigned_integer (value, &result) != 0)
614     gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
615
616   return result;
617 }
618
619 /* Parse an integer attribute into a ULONGEST.  */
620
621 void *
622 gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
623                              const struct gdb_xml_attribute *attribute,
624                              const char *value)
625 {
626   ULONGEST result;
627   void *ret;
628
629   if (xml_parse_unsigned_integer (value, &result) != 0)
630     gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
631                    attribute->name, value);
632
633   ret = xmalloc (sizeof (result));
634   memcpy (ret, &result, sizeof (result));
635   return ret;
636 }
637
638 /* A handler_data for yes/no boolean values.  */
639
640 const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
641   { "yes", 1 },
642   { "no", 0 },
643   { NULL, 0 }
644 };
645
646 /* Map NAME to VALUE.  A struct gdb_xml_enum * should be saved as the
647    value of handler_data when using gdb_xml_parse_attr_enum to parse a
648    fixed list of possible strings.  The list is terminated by an entry
649    with NAME == NULL.  */
650
651 void *
652 gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
653                          const struct gdb_xml_attribute *attribute,
654                          const char *value)
655 {
656   const struct gdb_xml_enum *enums = attribute->handler_data;
657   void *ret;
658
659   for (enums = attribute->handler_data; enums->name != NULL; enums++)
660     if (strcasecmp (enums->name, value) == 0)
661       break;
662
663   if (enums->name == NULL)
664     gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
665                  attribute->name, value);
666
667   ret = xmalloc (sizeof (enums->value));
668   memcpy (ret, &enums->value, sizeof (enums->value));
669   return ret;
670 }
671 \f
672
673 /* XInclude processing.  This is done as a separate step from actually
674    parsing the document, so that we can produce a single combined XML
675    document - e.g. to hand to a front end or to simplify comparing two
676    documents.  We make extensive use of XML_DefaultCurrent, to pass
677    input text directly into the output without reformatting or
678    requoting it.
679
680    We output the DOCTYPE declaration for the first document unchanged,
681    if present, and discard DOCTYPEs from included documents.  Only the
682    one we pass through here is used when we feed the result back to
683    expat.  The XInclude standard explicitly does not discuss
684    validation of the result; we choose to apply the same DTD applied
685    to the outermost document.
686
687    We can not simply include the external DTD subset in the document
688    as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
689    only in external subsets.  But if we do not pass the DTD into the
690    output at all, default values will not be filled in.
691
692    We don't pass through any <?xml> declaration because we generate
693    UTF-8, not whatever the input encoding was.  */
694
695 struct xinclude_parsing_data
696 {
697   /* The obstack to build the output in.  */
698   struct obstack obstack;
699
700   /* A count indicating whether we are in an element whose
701      children should not be copied to the output, and if so,
702      how deep we are nested.  This is used for anything inside
703      an xi:include, and for the DTD.  */
704   int skip_depth;
705
706   /* The number of <xi:include> elements currently being processed,
707      to detect loops.  */
708   int include_depth;
709
710   /* A function to call to obtain additional features, and its
711      baton.  */
712   xml_fetch_another fetcher;
713   void *fetcher_baton;
714 };
715
716 static void
717 xinclude_start_include (struct gdb_xml_parser *parser,
718                         const struct gdb_xml_element *element,
719                         void *user_data, VEC(gdb_xml_value_s) *attributes)
720 {
721   struct xinclude_parsing_data *data = user_data;
722   char *href = VEC_index (gdb_xml_value_s, attributes, 0)->value;
723   struct cleanup *back_to;
724   char *text, *output;
725
726   gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
727
728   if (data->include_depth > MAX_XINCLUDE_DEPTH)
729     gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
730                    MAX_XINCLUDE_DEPTH);
731
732   text = data->fetcher (href, data->fetcher_baton);
733   if (text == NULL)
734     gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
735   back_to = make_cleanup (xfree, text);
736
737   output = xml_process_xincludes (parser->name, text, data->fetcher,
738                                   data->fetcher_baton,
739                                   data->include_depth + 1);
740   if (output == NULL)
741     gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
742
743   obstack_grow (&data->obstack, output, strlen (output));
744   xfree (output);
745
746   do_cleanups (back_to);
747
748   data->skip_depth++;
749 }
750
751 static void
752 xinclude_end_include (struct gdb_xml_parser *parser,
753                       const struct gdb_xml_element *element,
754                       void *user_data, const char *body_text)
755 {
756   struct xinclude_parsing_data *data = user_data;
757
758   data->skip_depth--;
759 }
760
761 static void XMLCALL
762 xml_xinclude_default (void *data_, const XML_Char *s, int len)
763 {
764   struct gdb_xml_parser *parser = data_;
765   struct xinclude_parsing_data *data = parser->user_data;
766
767   /* If we are inside of e.g. xi:include or the DTD, don't save this
768      string.  */
769   if (data->skip_depth)
770     return;
771
772   /* Otherwise just add it to the end of the document we're building
773      up.  */
774   obstack_grow (&data->obstack, s, len);
775 }
776
777 static void XMLCALL
778 xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
779                             const XML_Char *sysid, const XML_Char *pubid,
780                             int has_internal_subset)
781 {
782   struct gdb_xml_parser *parser = data_;
783   struct xinclude_parsing_data *data = parser->user_data;
784
785   /* Don't print out the doctype, or the contents of the DTD internal
786      subset, if any.  */
787   data->skip_depth++;
788 }
789
790 static void XMLCALL
791 xml_xinclude_end_doctype (void *data_)
792 {
793   struct gdb_xml_parser *parser = data_;
794   struct xinclude_parsing_data *data = parser->user_data;
795
796   data->skip_depth--;
797 }
798
799 static void XMLCALL
800 xml_xinclude_xml_decl (void *data_, const XML_Char *version,
801                        const XML_Char *encoding, int standalone)
802 {
803   /* Do nothing - this function prevents the default handler from
804      being called, thus suppressing the XML declaration from the
805      output.  */
806 }
807
808 static void
809 xml_xinclude_cleanup (void *data_)
810 {
811   struct xinclude_parsing_data *data = data_;
812
813   obstack_free (&data->obstack, NULL);
814   xfree (data);
815 }
816
817 const struct gdb_xml_attribute xinclude_attributes[] = {
818   { "href", GDB_XML_AF_NONE, NULL, NULL },
819   { NULL, GDB_XML_AF_NONE, NULL, NULL }
820 };
821
822 const struct gdb_xml_element xinclude_elements[] = {
823   { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
824     GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
825     xinclude_start_include, xinclude_end_include },
826   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
827 };
828
829 /* The main entry point for <xi:include> processing.  */
830
831 char *
832 xml_process_xincludes (const char *name, const char *text,
833                        xml_fetch_another fetcher, void *fetcher_baton,
834                        int depth)
835 {
836   struct gdb_xml_parser *parser;
837   struct xinclude_parsing_data *data;
838   struct cleanup *back_to;
839   char *result = NULL;
840
841   data = XZALLOC (struct xinclude_parsing_data);
842   obstack_init (&data->obstack);
843   back_to = make_cleanup (xml_xinclude_cleanup, data);
844
845   parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
846   parser->is_xinclude = 1;
847
848   data->include_depth = depth;
849   data->fetcher = fetcher;
850   data->fetcher_baton = fetcher_baton;
851
852   XML_SetCharacterDataHandler (parser->expat_parser, NULL);
853   XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
854
855   /* Always discard the XML version declarations; the only important
856      thing this provides is encoding, and our result will have been
857      converted to UTF-8.  */
858   XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
859
860   if (depth > 0)
861     /* Discard the doctype for included documents.  */
862     XML_SetDoctypeDeclHandler (parser->expat_parser,
863                                xml_xinclude_start_doctype,
864                                xml_xinclude_end_doctype);
865
866   gdb_xml_use_dtd (parser, "xinclude.dtd");
867
868   if (gdb_xml_parse (parser, text) == 0)
869     {
870       obstack_1grow (&data->obstack, '\0');
871       result = xstrdup (obstack_finish (&data->obstack));
872
873       if (depth == 0)
874         gdb_xml_debug (parser, _("XInclude processing succeeded."));
875     }
876   else
877     result = NULL;
878
879   do_cleanups (back_to);
880   return result;
881 }
882 #endif /* HAVE_LIBEXPAT */
883 \f
884
885 /* Return an XML document which was compiled into GDB, from
886    the given FILENAME, or NULL if the file was not compiled in.  */
887
888 const char *
889 fetch_xml_builtin (const char *filename)
890 {
891   const char *(*p)[2];
892
893   for (p = xml_builtin; (*p)[0]; p++)
894     if (strcmp ((*p)[0], filename) == 0)
895       return (*p)[1];
896
897   return NULL;
898 }
899
900 /* A to_xfer_partial helper function which reads XML files which were
901    compiled into GDB.  The target may call this function from its own
902    to_xfer_partial handler, after converting object and annex to the
903    appropriate filename.  */
904
905 LONGEST
906 xml_builtin_xfer_partial (const char *filename,
907                           gdb_byte *readbuf, const gdb_byte *writebuf,
908                           ULONGEST offset, LONGEST len)
909 {
910   const char *buf;
911   LONGEST len_avail;
912
913   gdb_assert (readbuf != NULL && writebuf == NULL);
914   gdb_assert (filename != NULL);
915
916   buf = fetch_xml_builtin (filename);
917   if (buf == NULL)
918     return -1;
919
920   len_avail = strlen (buf);
921   if (offset >= len_avail)
922     return 0;
923
924   if (len > len_avail - offset)
925     len = len_avail - offset;
926   memcpy (readbuf, buf + offset, len);
927   return len;
928 }
929 \f
930
931 static void
932 show_debug_xml (struct ui_file *file, int from_tty,
933                 struct cmd_list_element *c, const char *value)
934 {
935   fprintf_filtered (file, _("XML debugging is %s.\n"), value);
936 }
937
938 /* Return a malloc allocated string with special characters from TEXT
939    replaced by entity references.  */
940
941 char *
942 xml_escape_text (const char *text)
943 {
944   char *result;
945   int i, special;
946
947   /* Compute the length of the result.  */
948   for (i = 0, special = 0; text[i] != '\0'; i++)
949     switch (text[i])
950       {
951       case '\'':
952       case '\"':
953         special += 5;
954         break;
955       case '&':
956         special += 4;
957         break;
958       case '<':
959       case '>':
960         special += 3;
961         break;
962       default:
963         break;
964       }
965
966   /* Expand the result.  */
967   result = xmalloc (i + special + 1);
968   for (i = 0, special = 0; text[i] != '\0'; i++)
969     switch (text[i])
970       {
971       case '\'':
972         strcpy (result + i + special, "&apos;");
973         special += 5;
974         break;
975       case '\"':
976         strcpy (result + i + special, "&quot;");
977         special += 5;
978         break;
979       case '&':
980         strcpy (result + i + special, "&amp;");
981         special += 4;
982         break;
983       case '<':
984         strcpy (result + i + special, "&lt;");
985         special += 3;
986         break;
987       case '>':
988         strcpy (result + i + special, "&gt;");
989         special += 3;
990         break;
991       default:
992         result[i + special] = text[i];
993         break;
994       }
995   result[i + special] = '\0';
996
997   return result;
998 }
999
1000 void
1001 obstack_xml_printf (struct obstack *obstack, const char *format, ...)
1002 {
1003   va_list ap;
1004   const char *f;
1005   const char *prev;
1006   int percent = 0;
1007
1008   va_start (ap, format);
1009
1010   prev = format;
1011   for (f = format; *f; f++)
1012     {
1013       if (percent)
1014        {
1015          switch (*f)
1016            {
1017            case 's':
1018              {
1019                char *p;
1020                char *a = va_arg (ap, char *);
1021
1022                obstack_grow (obstack, prev, f - prev - 1);
1023                p = xml_escape_text (a);
1024                obstack_grow_str (obstack, p);
1025                xfree (p);
1026                prev = f + 1;
1027              }
1028              break;
1029            }
1030          percent = 0;
1031        }
1032       else if (*f == '%')
1033        percent = 1;
1034     }
1035
1036   obstack_grow_str (obstack, prev);
1037   va_end (ap);
1038 }
1039
1040 char *
1041 xml_fetch_content_from_file (const char *filename, void *baton)
1042 {
1043   const char *dirname = baton;
1044   FILE *file;
1045   struct cleanup *back_to;
1046   char *text;
1047   size_t len, offset;
1048
1049   if (dirname && *dirname)
1050     {
1051       char *fullname = concat (dirname, "/", filename, (char *) NULL);
1052
1053       if (fullname == NULL)
1054         nomem (0);
1055       file = fopen (fullname, FOPEN_RT);
1056       xfree (fullname);
1057     }
1058   else
1059     file = fopen (filename, FOPEN_RT);
1060
1061   if (file == NULL)
1062     return NULL;
1063
1064   back_to = make_cleanup_fclose (file);
1065
1066   /* Read in the whole file, one chunk at a time.  */
1067   len = 4096;
1068   offset = 0;
1069   text = xmalloc (len);
1070   make_cleanup (free_current_contents, &text);
1071   while (1)
1072     {
1073       size_t bytes_read;
1074
1075       /* Continue reading where the last read left off.  Leave at least
1076          one byte so that we can NUL-terminate the result.  */
1077       bytes_read = fread (text + offset, 1, len - offset - 1, file);
1078       if (ferror (file))
1079         {
1080           warning (_("Read error from \"%s\""), filename);
1081           do_cleanups (back_to);
1082           return NULL;
1083         }
1084
1085       offset += bytes_read;
1086
1087       if (feof (file))
1088         break;
1089
1090       len = len * 2;
1091       text = xrealloc (text, len);
1092     }
1093
1094   fclose (file);
1095   discard_cleanups (back_to);
1096
1097   text[offset] = '\0';
1098   return text;
1099 }
1100
1101 void _initialize_xml_support (void);
1102
1103 void
1104 _initialize_xml_support (void)
1105 {
1106   add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1107                            _("Set XML parser debugging."),
1108                            _("Show XML parser debugging."),
1109                            _("When set, debugging messages for XML parsers "
1110                              "are displayed."),
1111                            NULL, show_debug_xml,
1112                            &setdebuglist, &showdebuglist);
1113 }