http://sourceware.org/ml/gdb-patches/2010-11/msg00112.html
[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
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
430struct gdb_xml_parser *
431gdb_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
108546a0
DJ
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
471static int XMLCALL
472gdb_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
516void
517gdb_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
e776119f
DJ
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
542int
543gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
544{
545 enum XML_Status status;
546 const char *error_string;
547
de584861
PA
548 gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
549
e776119f
DJ
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);
a109c7c1 564
e776119f
DJ
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;
fd79ecee
DJ
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
588static int
589xml_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
e776119f
DJ
605/* Parse an integer string into a ULONGEST and return it, or call
606 gdb_xml_error if it could not be parsed. */
fd79ecee
DJ
607
608ULONGEST
e776119f 609gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
fd79ecee
DJ
610{
611 ULONGEST result;
fd79ecee
DJ
612
613 if (xml_parse_unsigned_integer (value, &result) != 0)
e776119f
DJ
614 gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
615
fd79ecee
DJ
616 return result;
617}
618
e776119f
DJ
619/* Parse an integer attribute into a ULONGEST. */
620
621void *
622gdb_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;
fd79ecee 628
e776119f
DJ
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);
fd79ecee 632
e776119f
DJ
633 ret = xmalloc (sizeof (result));
634 memcpy (ret, &result, sizeof (result));
635 return ret;
636}
637
123dc839
DJ
638/* A handler_data for yes/no boolean values. */
639
640const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
641 { "yes", 1 },
642 { "no", 0 },
643 { NULL, 0 }
644};
645
e776119f
DJ
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
651void *
652gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
653 const struct gdb_xml_attribute *attribute,
654 const char *value)
fd79ecee 655{
e776119f
DJ
656 const struct gdb_xml_enum *enums = attribute->handler_data;
657 void *ret;
fd79ecee 658
e776119f 659 for (enums = attribute->handler_data; enums->name != NULL; enums++)
123dc839 660 if (strcasecmp (enums->name, value) == 0)
e776119f
DJ
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;
fd79ecee 670}
108546a0
DJ
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
695struct 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
716static void
717xinclude_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;
108546a0
DJ
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
751static void
752xinclude_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
761static void XMLCALL
762xml_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
777static void XMLCALL
778xml_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
790static void XMLCALL
791xml_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
799static void XMLCALL
800xml_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
808static void
809xml_xinclude_cleanup (void *data_)
810{
811 struct xinclude_parsing_data *data = data_;
812
813 obstack_free (&data->obstack, NULL);
814 xfree (data);
815}
816
817const struct gdb_xml_attribute xinclude_attributes[] = {
818 { "href", GDB_XML_AF_NONE, NULL, NULL },
819 { NULL, GDB_XML_AF_NONE, NULL, NULL }
820};
821
822const 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
831char *
832xml_process_xincludes (const char *name, const char *text,
833 xml_fetch_another fetcher, void *fetcher_baton,
834 int depth)
835{
108546a0
DJ
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)
de584861 874 gdb_xml_debug (parser, _("XInclude processing succeeded."));
108546a0
DJ
875 }
876 else
877 result = NULL;
878
879 do_cleanups (back_to);
880 return result;
881}
05a4558a 882#endif /* HAVE_LIBEXPAT */
108546a0
DJ
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
888const char *
889fetch_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}
fd79ecee 899
05a4558a
DJ
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
905LONGEST
906xml_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
fd79ecee
DJ
930
931static void
e776119f
DJ
932show_debug_xml (struct ui_file *file, int from_tty,
933 struct cmd_list_element *c, const char *value)
fd79ecee 934{
e776119f 935 fprintf_filtered (file, _("XML debugging is %s.\n"), value);
fd79ecee
DJ
936}
937
de584861
PA
938/* Return a malloc allocated string with special characters from TEXT
939 replaced by entity references. */
940
941char *
942xml_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
07e059b5
VP
1000void
1001obstack_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 *);
a109c7c1 1021
07e059b5
VP
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
a96d9b2e
SDJ
1040char *
1041xml_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);
a109c7c1 1052
a96d9b2e
SDJ
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
e776119f 1101void _initialize_xml_support (void);
fd79ecee
DJ
1102
1103void
e776119f 1104_initialize_xml_support (void)
fd79ecee 1105{
e776119f
DJ
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);
fd79ecee 1113}
This page took 0.526036 seconds and 4 git commands to generate.