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