gdb/
[deliverable/binutils-gdb.git] / gdb / xml-support.c
CommitLineData
fd79ecee
DJ
1/* Helper routines for parsing XML using Expat.
2
7b6bb8da
JB
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
fd79ecee
DJ
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
fd79ecee
DJ
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
fd79ecee
DJ
20
21#include "defs.h"
e776119f 22#include "gdbcmd.h"
05a4558a
DJ
23#include "exceptions.h"
24#include "xml-support.h"
25
26#include "gdb_string.h"
27#include "safe-ctype.h"
e776119f
DJ
28
29/* Debugging flag. */
30static int debug_xml;
fd79ecee
DJ
31
32/* The contents of this file are only useful if XML support is
33 available. */
34#ifdef HAVE_LIBEXPAT
35
dbc981de 36#include "gdb_expat.h"
e776119f 37
108546a0
DJ
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
123dc839
DJ
42/* Simplified XML parser infrastructure. */
43
e776119f
DJ
44/* A parsing level -- used to keep track of the current element
45 nesting. */
46struct 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};
61typedef struct scope_level scope_level_s;
62DEF_VEC_O(scope_level_s);
63
64/* The parser itself, and our additional state. */
65struct 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. */
108546a0
DJ
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? */
e776119f
DJ
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
86static void
87gdb_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
ca4ca11e
DJ
92 if (parser->error.reason < 0)
93 return;
94
e776119f
DJ
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}
fd79ecee 103
e776119f 104/* Issue a debugging message from one of PARSER's handlers. */
fd79ecee 105
e776119f
DJ
106void
107gdb_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
130void
131gdb_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
143static void
144gdb_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
159static void
160gdb_xml_start_element (void *data, const XML_Char *name,
161 const XML_Char **attrs)
fd79ecee 162{
e776119f 163 struct gdb_xml_parser *parser = data;
108546a0 164 struct scope_level *scope;
e776119f
DJ
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
e776119f
DJ
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. */
108546a0
DJ
175 VEC_reserve (scope_level_s, parser->scopes, 1);
176 scope = VEC_last (scope_level_s, parser->scopes);
e776119f 177 memset (&new_scope, 0, sizeof (new_scope));
108546a0 178 VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
e776119f
DJ
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 {
108546a0
DJ
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
e776119f 207 gdb_xml_debug (parser, _("Element <%s> unknown"), name);
e776119f
DJ
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
108546a0
DJ
216 back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
217
e776119f
DJ
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)
fd79ecee 267 {
e776119f
DJ
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
298static void
299gdb_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;
fd79ecee 307
e776119f
DJ
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;
ca4ca11e 315#ifdef HAVE_XML_STOPPARSER
e776119f 316 XML_StopParser (parser->expat_parser, XML_FALSE);
ca4ca11e 317#endif
fd79ecee 318 }
e776119f
DJ
319}
320
321/* Handle the end of an element. DATA is our local XML parser, and
322 NAME is the current element. */
323
324static void
325gdb_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;
e776119f
DJ
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)
d097fa3e 339 gdb_xml_error (parser, _("Required element <%s> is missing"),
e776119f
DJ
340 element->name);
341
581e13c1 342 /* Call the element processor. */
108546a0 343 if (scope->element != NULL && scope->element->end_handler)
e776119f 344 {
108546a0 345 char *body;
e776119f 346
108546a0
DJ
347 if (scope->body == NULL)
348 body = "";
349 else
350 {
351 int length;
e776119f 352
108546a0
DJ
353 length = obstack_object_size (scope->body);
354 obstack_1grow (scope->body, '\0');
355 body = obstack_finish (scope->body);
e776119f 356
108546a0
DJ
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);
e776119f
DJ
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
382static void
383gdb_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;
ca4ca11e 398#ifdef HAVE_XML_STOPPARSER
e776119f 399 XML_StopParser (parser->expat_parser, XML_FALSE);
ca4ca11e 400#endif
e776119f
DJ
401 }
402}
403
404/* Free a parser and all its associated state. */
405
406static void
407gdb_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
efc0eabd
PA
430static struct gdb_xml_parser *
431gdb_xml_create_parser_and_cleanup_1 (const char *name,
432 const struct gdb_xml_element *elements,
433 void *user_data, struct cleanup **old_chain)
e776119f
DJ
434{
435 struct gdb_xml_parser *parser;
436 struct scope_level start_scope;
efc0eabd 437 struct cleanup *dummy;
e776119f
DJ
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
efc0eabd
PA
463 if (old_chain == NULL)
464 old_chain = &dummy;
e776119f 465
efc0eabd 466 *old_chain = make_cleanup (gdb_xml_cleanup, parser);
e776119f
DJ
467 return parser;
468}
469
efc0eabd
PA
470/* Initialize and return a parser. Register a cleanup to destroy the
471 parser. */
472
473struct gdb_xml_parser *
474gdb_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
108546a0
DJ
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
488static int XMLCALL
489gdb_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)
9b20d036
MS
504 internal_error (__FILE__, __LINE__,
505 _("could not locate built-in DTD %s"),
108546a0
DJ
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
534void
535gdb_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__,
9b20d036
MS
550 _("XML_UseForeignDTD failed: %s"),
551 XML_ErrorString (err));
108546a0
DJ
552}
553
e776119f
DJ
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
561int
562gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
563{
564 enum XML_Status status;
565 const char *error_string;
566
de584861
PA
567 gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
568
e776119f
DJ
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);
a109c7c1 583
e776119f
DJ
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;
fd79ecee
DJ
599}
600
efc0eabd
PA
601int
602gdb_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
fd79ecee
DJ
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
627static int
628xml_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
e776119f
DJ
644/* Parse an integer string into a ULONGEST and return it, or call
645 gdb_xml_error if it could not be parsed. */
fd79ecee
DJ
646
647ULONGEST
e776119f 648gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
fd79ecee
DJ
649{
650 ULONGEST result;
fd79ecee
DJ
651
652 if (xml_parse_unsigned_integer (value, &result) != 0)
e776119f
DJ
653 gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
654
fd79ecee
DJ
655 return result;
656}
657
e776119f
DJ
658/* Parse an integer attribute into a ULONGEST. */
659
660void *
661gdb_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;
fd79ecee 667
e776119f
DJ
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);
fd79ecee 671
e776119f
DJ
672 ret = xmalloc (sizeof (result));
673 memcpy (ret, &result, sizeof (result));
674 return ret;
675}
676
123dc839
DJ
677/* A handler_data for yes/no boolean values. */
678
679const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
680 { "yes", 1 },
681 { "no", 0 },
682 { NULL, 0 }
683};
684
e776119f
DJ
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
690void *
691gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
692 const struct gdb_xml_attribute *attribute,
693 const char *value)
fd79ecee 694{
e776119f
DJ
695 const struct gdb_xml_enum *enums = attribute->handler_data;
696 void *ret;
fd79ecee 697
e776119f 698 for (enums = attribute->handler_data; enums->name != NULL; enums++)
123dc839 699 if (strcasecmp (enums->name, value) == 0)
e776119f
DJ
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;
fd79ecee 709}
108546a0
DJ
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
734struct 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
755static void
756xinclude_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;
108546a0
DJ
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
790static void
791xinclude_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
800static void XMLCALL
801xml_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
816static void XMLCALL
817xml_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
829static void XMLCALL
830xml_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
838static void XMLCALL
839xml_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
847static void
848xml_xinclude_cleanup (void *data_)
849{
850 struct xinclude_parsing_data *data = data_;
851
852 obstack_free (&data->obstack, NULL);
853 xfree (data);
854}
855
856const struct gdb_xml_attribute xinclude_attributes[] = {
857 { "href", GDB_XML_AF_NONE, NULL, NULL },
858 { NULL, GDB_XML_AF_NONE, NULL, NULL }
859};
860
861const 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
870char *
871xml_process_xincludes (const char *name, const char *text,
872 xml_fetch_another fetcher, void *fetcher_baton,
873 int depth)
874{
108546a0
DJ
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)
de584861 913 gdb_xml_debug (parser, _("XInclude processing succeeded."));
108546a0
DJ
914 }
915 else
916 result = NULL;
917
918 do_cleanups (back_to);
919 return result;
920}
05a4558a 921#endif /* HAVE_LIBEXPAT */
108546a0
DJ
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
927const char *
928fetch_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}
fd79ecee 938
05a4558a
DJ
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
944LONGEST
945xml_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
fd79ecee
DJ
969
970static void
e776119f
DJ
971show_debug_xml (struct ui_file *file, int from_tty,
972 struct cmd_list_element *c, const char *value)
fd79ecee 973{
e776119f 974 fprintf_filtered (file, _("XML debugging is %s.\n"), value);
fd79ecee
DJ
975}
976
de584861
PA
977/* Return a malloc allocated string with special characters from TEXT
978 replaced by entity references. */
979
980char *
981xml_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
07e059b5
VP
1039void
1040obstack_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 *);
a109c7c1 1060
07e059b5
VP
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
a96d9b2e
SDJ
1079char *
1080xml_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);
a109c7c1 1091
a96d9b2e
SDJ
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
e776119f 1140void _initialize_xml_support (void);
fd79ecee
DJ
1141
1142void
e776119f 1143_initialize_xml_support (void)
fd79ecee 1144{
e776119f
DJ
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);
fd79ecee 1152}
This page took 1.159487 seconds and 4 git commands to generate.