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