]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/xml-support.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / gdb / xml-support.c
CommitLineData
fd79ecee
DJ
1/* Helper routines for parsing XML using Expat.
2
8acc9f48 3 Copyright (C) 2006-2013 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
3d2c1d41
PA
140/* Find the attribute named NAME in the set of parsed attributes
141 ATTRIBUTES. Returns NULL if not found. */
142
143struct gdb_xml_value *
144xml_find_attribute (VEC(gdb_xml_value_s) *attributes, const char *name)
145{
146 struct gdb_xml_value *value;
147 int ix;
148
149 for (ix = 0; VEC_iterate (gdb_xml_value_s, attributes, ix, value); ix++)
150 if (strcmp (value->name, name) == 0)
151 return value;
152
153 return NULL;
154}
155
e776119f
DJ
156/* Clean up a vector of parsed attribute values. */
157
158static void
159gdb_xml_values_cleanup (void *data)
160{
161 VEC(gdb_xml_value_s) **values = data;
162 struct gdb_xml_value *value;
163 int ix;
164
165 for (ix = 0; VEC_iterate (gdb_xml_value_s, *values, ix, value); ix++)
166 xfree (value->value);
167 VEC_free (gdb_xml_value_s, *values);
168}
169
170/* Handle the start of an element. DATA is our local XML parser, NAME
171 is the element, and ATTRS are the names and values of this
172 element's attributes. */
173
174static void
175gdb_xml_start_element (void *data, const XML_Char *name,
176 const XML_Char **attrs)
fd79ecee 177{
e776119f 178 struct gdb_xml_parser *parser = data;
108546a0 179 struct scope_level *scope;
e776119f
DJ
180 struct scope_level new_scope;
181 const struct gdb_xml_element *element;
182 const struct gdb_xml_attribute *attribute;
183 VEC(gdb_xml_value_s) *attributes = NULL;
184 unsigned int seen;
185 struct cleanup *back_to;
186
e776119f
DJ
187 /* Push an error scope. If we return or throw an exception before
188 filling this in, it will tell us to ignore children of this
189 element. */
108546a0
DJ
190 VEC_reserve (scope_level_s, parser->scopes, 1);
191 scope = VEC_last (scope_level_s, parser->scopes);
e776119f 192 memset (&new_scope, 0, sizeof (new_scope));
108546a0 193 VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
e776119f
DJ
194
195 gdb_xml_debug (parser, _("Entering element <%s>"), name);
196
197 /* Find this element in the list of the current scope's allowed
198 children. Record that we've seen it. */
199
200 seen = 1;
201 for (element = scope->elements; element && element->name;
202 element++, seen <<= 1)
203 if (strcmp (element->name, name) == 0)
204 break;
205
206 if (element == NULL || element->name == NULL)
207 {
108546a0
DJ
208 /* If we're working on XInclude, <xi:include> can be the child
209 of absolutely anything. Copy the previous scope's element
210 list into the new scope even if there was no match. */
211 if (parser->is_xinclude)
212 {
213 struct scope_level *unknown_scope;
214
215 XML_DefaultCurrent (parser->expat_parser);
216
217 unknown_scope = VEC_last (scope_level_s, parser->scopes);
218 unknown_scope->elements = scope->elements;
219 return;
220 }
221
e776119f 222 gdb_xml_debug (parser, _("Element <%s> unknown"), name);
e776119f
DJ
223 return;
224 }
225
226 if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope->seen))
227 gdb_xml_error (parser, _("Element <%s> only expected once"), name);
228
229 scope->seen |= seen;
230
108546a0
DJ
231 back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
232
e776119f
DJ
233 for (attribute = element->attributes;
234 attribute != NULL && attribute->name != NULL;
235 attribute++)
236 {
237 const char *val = NULL;
238 const XML_Char **p;
239 void *parsed_value;
240 struct gdb_xml_value new_value;
241
242 for (p = attrs; *p != NULL; p += 2)
243 if (!strcmp (attribute->name, p[0]))
244 {
245 val = p[1];
246 break;
247 }
248
249 if (*p != NULL && val == NULL)
250 {
251 gdb_xml_debug (parser, _("Attribute \"%s\" missing a value"),
252 attribute->name);
253 continue;
254 }
255
256 if (*p == NULL && !(attribute->flags & GDB_XML_AF_OPTIONAL))
257 {
258 gdb_xml_error (parser, _("Required attribute \"%s\" of "
259 "<%s> not specified"),
260 attribute->name, element->name);
261 continue;
262 }
263
264 if (*p == NULL)
265 continue;
266
267 gdb_xml_debug (parser, _("Parsing attribute %s=\"%s\""),
268 attribute->name, val);
269
270 if (attribute->handler)
271 parsed_value = attribute->handler (parser, attribute, val);
272 else
273 parsed_value = xstrdup (val);
274
275 new_value.name = attribute->name;
276 new_value.value = parsed_value;
277 VEC_safe_push (gdb_xml_value_s, attributes, &new_value);
278 }
279
280 /* Check for unrecognized attributes. */
281 if (debug_xml)
fd79ecee 282 {
e776119f
DJ
283 const XML_Char **p;
284
285 for (p = attrs; *p != NULL; p += 2)
286 {
287 for (attribute = element->attributes;
288 attribute != NULL && attribute->name != NULL;
289 attribute++)
290 if (strcmp (attribute->name, *p) == 0)
291 break;
292
293 if (attribute == NULL || attribute->name == NULL)
294 gdb_xml_debug (parser, _("Ignoring unknown attribute %s"), *p);
295 }
296 }
297
298 /* Call the element handler if there is one. */
299 if (element->start_handler)
300 element->start_handler (parser, element, parser->user_data, attributes);
301
302 /* Fill in a new scope level. */
303 scope = VEC_last (scope_level_s, parser->scopes);
304 scope->element = element;
305 scope->elements = element->children;
306
307 do_cleanups (back_to);
308}
309
310/* Wrapper for gdb_xml_start_element, to prevent throwing exceptions
311 through expat. */
312
313static void
314gdb_xml_start_element_wrapper (void *data, const XML_Char *name,
315 const XML_Char **attrs)
316{
317 struct gdb_xml_parser *parser = data;
318 volatile struct gdb_exception ex;
319
320 if (parser->error.reason < 0)
321 return;
fd79ecee 322
e776119f
DJ
323 TRY_CATCH (ex, RETURN_MASK_ALL)
324 {
325 gdb_xml_start_element (data, name, attrs);
326 }
327 if (ex.reason < 0)
328 {
329 parser->error = ex;
ca4ca11e 330#ifdef HAVE_XML_STOPPARSER
e776119f 331 XML_StopParser (parser->expat_parser, XML_FALSE);
ca4ca11e 332#endif
fd79ecee 333 }
e776119f
DJ
334}
335
336/* Handle the end of an element. DATA is our local XML parser, and
337 NAME is the current element. */
338
339static void
340gdb_xml_end_element (void *data, const XML_Char *name)
341{
342 struct gdb_xml_parser *parser = data;
343 struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
344 const struct gdb_xml_element *element;
345 unsigned int seen;
e776119f
DJ
346
347 gdb_xml_debug (parser, _("Leaving element <%s>"), name);
348
349 for (element = scope->elements, seen = 1;
350 element != NULL && element->name != NULL;
351 element++, seen <<= 1)
352 if ((scope->seen & seen) == 0
353 && (element->flags & GDB_XML_EF_OPTIONAL) == 0)
d097fa3e 354 gdb_xml_error (parser, _("Required element <%s> is missing"),
e776119f
DJ
355 element->name);
356
581e13c1 357 /* Call the element processor. */
108546a0 358 if (scope->element != NULL && scope->element->end_handler)
e776119f 359 {
108546a0 360 char *body;
e776119f 361
108546a0
DJ
362 if (scope->body == NULL)
363 body = "";
364 else
365 {
366 int length;
e776119f 367
108546a0
DJ
368 length = obstack_object_size (scope->body);
369 obstack_1grow (scope->body, '\0');
370 body = obstack_finish (scope->body);
e776119f 371
108546a0
DJ
372 /* Strip leading and trailing whitespace. */
373 while (length > 0 && ISSPACE (body[length-1]))
374 body[--length] = '\0';
375 while (*body && ISSPACE (*body))
376 body++;
377 }
378
379 scope->element->end_handler (parser, scope->element, parser->user_data,
380 body);
381 }
382 else if (scope->element == NULL)
383 XML_DefaultCurrent (parser->expat_parser);
e776119f
DJ
384
385 /* Pop the scope level. */
386 if (scope->body)
387 {
388 obstack_free (scope->body, NULL);
389 xfree (scope->body);
390 }
391 VEC_pop (scope_level_s, parser->scopes);
392}
393
394/* Wrapper for gdb_xml_end_element, to prevent throwing exceptions
395 through expat. */
396
397static void
398gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
399{
400 struct gdb_xml_parser *parser = data;
401 volatile struct gdb_exception ex;
402
403 if (parser->error.reason < 0)
404 return;
405
406 TRY_CATCH (ex, RETURN_MASK_ALL)
407 {
408 gdb_xml_end_element (data, name);
409 }
410 if (ex.reason < 0)
411 {
412 parser->error = ex;
ca4ca11e 413#ifdef HAVE_XML_STOPPARSER
e776119f 414 XML_StopParser (parser->expat_parser, XML_FALSE);
ca4ca11e 415#endif
e776119f
DJ
416 }
417}
418
419/* Free a parser and all its associated state. */
420
421static void
422gdb_xml_cleanup (void *arg)
423{
424 struct gdb_xml_parser *parser = arg;
425 struct scope_level *scope;
426 int ix;
427
428 XML_ParserFree (parser->expat_parser);
429
430 /* Clean up the scopes. */
431 for (ix = 0; VEC_iterate (scope_level_s, parser->scopes, ix, scope); ix++)
432 if (scope->body)
433 {
434 obstack_free (scope->body, NULL);
435 xfree (scope->body);
436 }
437 VEC_free (scope_level_s, parser->scopes);
438
439 xfree (parser);
440}
441
442/* Initialize and return a parser. Register a cleanup to destroy the
443 parser. */
444
efc0eabd
PA
445static struct gdb_xml_parser *
446gdb_xml_create_parser_and_cleanup_1 (const char *name,
447 const struct gdb_xml_element *elements,
448 void *user_data, struct cleanup **old_chain)
e776119f
DJ
449{
450 struct gdb_xml_parser *parser;
451 struct scope_level start_scope;
efc0eabd 452 struct cleanup *dummy;
e776119f
DJ
453
454 /* Initialize the parser. */
455 parser = XZALLOC (struct gdb_xml_parser);
456 parser->expat_parser = XML_ParserCreateNS (NULL, '!');
457 if (parser->expat_parser == NULL)
458 {
459 xfree (parser);
d26e3629 460 malloc_failure (0);
e776119f
DJ
461 }
462
463 parser->name = name;
464
465 parser->user_data = user_data;
466 XML_SetUserData (parser->expat_parser, parser);
467
468 /* Set the callbacks. */
469 XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper,
470 gdb_xml_end_element_wrapper);
471 XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text);
472
473 /* Initialize the outer scope. */
474 memset (&start_scope, 0, sizeof (start_scope));
475 start_scope.elements = elements;
476 VEC_safe_push (scope_level_s, parser->scopes, &start_scope);
477
efc0eabd
PA
478 if (old_chain == NULL)
479 old_chain = &dummy;
e776119f 480
efc0eabd 481 *old_chain = make_cleanup (gdb_xml_cleanup, parser);
e776119f
DJ
482 return parser;
483}
484
efc0eabd
PA
485/* Initialize and return a parser. Register a cleanup to destroy the
486 parser. */
487
488struct gdb_xml_parser *
489gdb_xml_create_parser_and_cleanup (const char *name,
490 const struct gdb_xml_element *elements,
491 void *user_data)
492{
493 struct cleanup *old_chain;
494
495 return gdb_xml_create_parser_and_cleanup_1 (name, elements, user_data,
496 &old_chain);
497}
498
108546a0
DJ
499/* External entity handler. The only external entities we support
500 are those compiled into GDB (we do not fetch entities from the
501 target). */
502
503static int XMLCALL
504gdb_xml_fetch_external_entity (XML_Parser expat_parser,
505 const XML_Char *context,
506 const XML_Char *base,
507 const XML_Char *systemId,
508 const XML_Char *publicId)
509{
510 struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
511 XML_Parser entity_parser;
512 const char *text;
513 enum XML_Status status;
514
515 if (systemId == NULL)
516 {
517 text = fetch_xml_builtin (parser->dtd_name);
518 if (text == NULL)
9b20d036
MS
519 internal_error (__FILE__, __LINE__,
520 _("could not locate built-in DTD %s"),
108546a0
DJ
521 parser->dtd_name);
522 }
523 else
524 {
525 text = fetch_xml_builtin (systemId);
526 if (text == NULL)
527 return XML_STATUS_ERROR;
528 }
529
530 entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
531
532 /* Don't use our handlers for the contents of the DTD. Just let expat
533 process it. */
534 XML_SetElementHandler (entity_parser, NULL, NULL);
535 XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
536 XML_SetXmlDeclHandler (entity_parser, NULL);
537 XML_SetDefaultHandler (entity_parser, NULL);
538 XML_SetUserData (entity_parser, NULL);
539
540 status = XML_Parse (entity_parser, text, strlen (text), 1);
541
542 XML_ParserFree (entity_parser);
543 return status;
544}
545
546/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
547 with PARSER. */
548
549void
550gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
551{
552 enum XML_Error err;
553
554 parser->dtd_name = dtd_name;
555
556 XML_SetParamEntityParsing (parser->expat_parser,
557 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
558 XML_SetExternalEntityRefHandler (parser->expat_parser,
559 gdb_xml_fetch_external_entity);
560
561 /* Even if no DTD is provided, use the built-in DTD anyway. */
562 err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
563 if (err != XML_ERROR_NONE)
564 internal_error (__FILE__, __LINE__,
9b20d036
MS
565 _("XML_UseForeignDTD failed: %s"),
566 XML_ErrorString (err));
108546a0
DJ
567}
568
e776119f
DJ
569/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
570 should be NUL-terminated.
571
572 The return value is 0 for success or -1 for error. It may throw,
573 but only if something unexpected goes wrong during parsing; parse
574 errors will be caught, warned about, and reported as failure. */
575
576int
577gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
578{
579 enum XML_Status status;
580 const char *error_string;
581
de584861
PA
582 gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
583
e776119f
DJ
584 status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
585
586 if (status == XML_STATUS_OK && parser->error.reason == 0)
587 return 0;
588
589 if (parser->error.reason == RETURN_ERROR
590 && parser->error.error == XML_PARSE_ERROR)
591 {
592 gdb_assert (parser->error.message != NULL);
593 error_string = parser->error.message;
594 }
595 else if (status == XML_STATUS_ERROR)
596 {
597 enum XML_Error err = XML_GetErrorCode (parser->expat_parser);
a109c7c1 598
e776119f
DJ
599 error_string = XML_ErrorString (err);
600 }
601 else
602 {
603 gdb_assert (parser->error.reason < 0);
604 throw_exception (parser->error);
605 }
606
607 if (parser->last_line != 0)
608 warning (_("while parsing %s (at line %d): %s"), parser->name,
609 parser->last_line, error_string);
610 else
611 warning (_("while parsing %s: %s"), parser->name, error_string);
612
613 return -1;
fd79ecee
DJ
614}
615
efc0eabd
PA
616int
617gdb_xml_parse_quick (const char *name, const char *dtd_name,
618 const struct gdb_xml_element *elements,
619 const char *document, void *user_data)
620{
621 struct gdb_xml_parser *parser;
622 struct cleanup *back_to;
623 int result;
624
625 parser = gdb_xml_create_parser_and_cleanup_1 (name, elements,
626 user_data, &back_to);
627 if (dtd_name != NULL)
628 gdb_xml_use_dtd (parser, dtd_name);
629 result = gdb_xml_parse (parser, document);
630
631 do_cleanups (back_to);
632
633 return result;
634}
635
fd79ecee
DJ
636/* Parse a field VALSTR that we expect to contain an integer value.
637 The integer is returned in *VALP. The string is parsed with an
638 equivalent to strtoul.
639
640 Returns 0 for success, -1 for error. */
641
642static int
643xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
644{
645 const char *endptr;
646 ULONGEST result;
647
648 if (*valstr == '\0')
649 return -1;
650
651 result = strtoulst (valstr, &endptr, 0);
652 if (*endptr != '\0')
653 return -1;
654
655 *valp = result;
656 return 0;
657}
658
e776119f
DJ
659/* Parse an integer string into a ULONGEST and return it, or call
660 gdb_xml_error if it could not be parsed. */
fd79ecee
DJ
661
662ULONGEST
e776119f 663gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
fd79ecee
DJ
664{
665 ULONGEST result;
fd79ecee
DJ
666
667 if (xml_parse_unsigned_integer (value, &result) != 0)
e776119f
DJ
668 gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
669
fd79ecee
DJ
670 return result;
671}
672
e776119f
DJ
673/* Parse an integer attribute into a ULONGEST. */
674
675void *
676gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
677 const struct gdb_xml_attribute *attribute,
678 const char *value)
679{
680 ULONGEST result;
681 void *ret;
fd79ecee 682
e776119f
DJ
683 if (xml_parse_unsigned_integer (value, &result) != 0)
684 gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
685 attribute->name, value);
fd79ecee 686
e776119f
DJ
687 ret = xmalloc (sizeof (result));
688 memcpy (ret, &result, sizeof (result));
689 return ret;
690}
691
123dc839
DJ
692/* A handler_data for yes/no boolean values. */
693
694const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
695 { "yes", 1 },
696 { "no", 0 },
697 { NULL, 0 }
698};
699
e776119f
DJ
700/* Map NAME to VALUE. A struct gdb_xml_enum * should be saved as the
701 value of handler_data when using gdb_xml_parse_attr_enum to parse a
702 fixed list of possible strings. The list is terminated by an entry
703 with NAME == NULL. */
704
705void *
706gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
707 const struct gdb_xml_attribute *attribute,
708 const char *value)
fd79ecee 709{
e776119f
DJ
710 const struct gdb_xml_enum *enums = attribute->handler_data;
711 void *ret;
fd79ecee 712
e776119f 713 for (enums = attribute->handler_data; enums->name != NULL; enums++)
123dc839 714 if (strcasecmp (enums->name, value) == 0)
e776119f
DJ
715 break;
716
717 if (enums->name == NULL)
718 gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
719 attribute->name, value);
720
721 ret = xmalloc (sizeof (enums->value));
722 memcpy (ret, &enums->value, sizeof (enums->value));
723 return ret;
fd79ecee 724}
108546a0
DJ
725\f
726
727/* XInclude processing. This is done as a separate step from actually
728 parsing the document, so that we can produce a single combined XML
729 document - e.g. to hand to a front end or to simplify comparing two
730 documents. We make extensive use of XML_DefaultCurrent, to pass
731 input text directly into the output without reformatting or
732 requoting it.
733
734 We output the DOCTYPE declaration for the first document unchanged,
735 if present, and discard DOCTYPEs from included documents. Only the
736 one we pass through here is used when we feed the result back to
737 expat. The XInclude standard explicitly does not discuss
738 validation of the result; we choose to apply the same DTD applied
739 to the outermost document.
740
741 We can not simply include the external DTD subset in the document
742 as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
743 only in external subsets. But if we do not pass the DTD into the
744 output at all, default values will not be filled in.
745
746 We don't pass through any <?xml> declaration because we generate
747 UTF-8, not whatever the input encoding was. */
748
749struct xinclude_parsing_data
750{
751 /* The obstack to build the output in. */
752 struct obstack obstack;
753
754 /* A count indicating whether we are in an element whose
755 children should not be copied to the output, and if so,
756 how deep we are nested. This is used for anything inside
757 an xi:include, and for the DTD. */
758 int skip_depth;
759
760 /* The number of <xi:include> elements currently being processed,
761 to detect loops. */
762 int include_depth;
763
764 /* A function to call to obtain additional features, and its
765 baton. */
766 xml_fetch_another fetcher;
767 void *fetcher_baton;
768};
769
770static void
771xinclude_start_include (struct gdb_xml_parser *parser,
772 const struct gdb_xml_element *element,
773 void *user_data, VEC(gdb_xml_value_s) *attributes)
774{
775 struct xinclude_parsing_data *data = user_data;
3d2c1d41 776 char *href = xml_find_attribute (attributes, "href")->value;
108546a0
DJ
777 struct cleanup *back_to;
778 char *text, *output;
108546a0
DJ
779
780 gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
781
782 if (data->include_depth > MAX_XINCLUDE_DEPTH)
783 gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
784 MAX_XINCLUDE_DEPTH);
785
786 text = data->fetcher (href, data->fetcher_baton);
787 if (text == NULL)
788 gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
789 back_to = make_cleanup (xfree, text);
790
791 output = xml_process_xincludes (parser->name, text, data->fetcher,
792 data->fetcher_baton,
793 data->include_depth + 1);
794 if (output == NULL)
795 gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
796
797 obstack_grow (&data->obstack, output, strlen (output));
798 xfree (output);
799
800 do_cleanups (back_to);
801
802 data->skip_depth++;
803}
804
805static void
806xinclude_end_include (struct gdb_xml_parser *parser,
807 const struct gdb_xml_element *element,
808 void *user_data, const char *body_text)
809{
810 struct xinclude_parsing_data *data = user_data;
811
812 data->skip_depth--;
813}
814
815static void XMLCALL
816xml_xinclude_default (void *data_, const XML_Char *s, int len)
817{
818 struct gdb_xml_parser *parser = data_;
819 struct xinclude_parsing_data *data = parser->user_data;
820
821 /* If we are inside of e.g. xi:include or the DTD, don't save this
822 string. */
823 if (data->skip_depth)
824 return;
825
826 /* Otherwise just add it to the end of the document we're building
827 up. */
828 obstack_grow (&data->obstack, s, len);
829}
830
831static void XMLCALL
832xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
833 const XML_Char *sysid, const XML_Char *pubid,
834 int has_internal_subset)
835{
836 struct gdb_xml_parser *parser = data_;
837 struct xinclude_parsing_data *data = parser->user_data;
838
839 /* Don't print out the doctype, or the contents of the DTD internal
840 subset, if any. */
841 data->skip_depth++;
842}
843
844static void XMLCALL
845xml_xinclude_end_doctype (void *data_)
846{
847 struct gdb_xml_parser *parser = data_;
848 struct xinclude_parsing_data *data = parser->user_data;
849
850 data->skip_depth--;
851}
852
853static void XMLCALL
854xml_xinclude_xml_decl (void *data_, const XML_Char *version,
855 const XML_Char *encoding, int standalone)
856{
857 /* Do nothing - this function prevents the default handler from
858 being called, thus suppressing the XML declaration from the
859 output. */
860}
861
862static void
863xml_xinclude_cleanup (void *data_)
864{
865 struct xinclude_parsing_data *data = data_;
866
867 obstack_free (&data->obstack, NULL);
868 xfree (data);
869}
870
871const struct gdb_xml_attribute xinclude_attributes[] = {
872 { "href", GDB_XML_AF_NONE, NULL, NULL },
873 { NULL, GDB_XML_AF_NONE, NULL, NULL }
874};
875
876const struct gdb_xml_element xinclude_elements[] = {
877 { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
878 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
879 xinclude_start_include, xinclude_end_include },
880 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
881};
882
883/* The main entry point for <xi:include> processing. */
884
885char *
886xml_process_xincludes (const char *name, const char *text,
887 xml_fetch_another fetcher, void *fetcher_baton,
888 int depth)
889{
108546a0
DJ
890 struct gdb_xml_parser *parser;
891 struct xinclude_parsing_data *data;
892 struct cleanup *back_to;
893 char *result = NULL;
894
895 data = XZALLOC (struct xinclude_parsing_data);
896 obstack_init (&data->obstack);
897 back_to = make_cleanup (xml_xinclude_cleanup, data);
898
899 parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
900 parser->is_xinclude = 1;
901
902 data->include_depth = depth;
903 data->fetcher = fetcher;
904 data->fetcher_baton = fetcher_baton;
905
906 XML_SetCharacterDataHandler (parser->expat_parser, NULL);
907 XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
908
909 /* Always discard the XML version declarations; the only important
910 thing this provides is encoding, and our result will have been
911 converted to UTF-8. */
912 XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
913
914 if (depth > 0)
915 /* Discard the doctype for included documents. */
916 XML_SetDoctypeDeclHandler (parser->expat_parser,
917 xml_xinclude_start_doctype,
918 xml_xinclude_end_doctype);
919
920 gdb_xml_use_dtd (parser, "xinclude.dtd");
921
922 if (gdb_xml_parse (parser, text) == 0)
923 {
924 obstack_1grow (&data->obstack, '\0');
925 result = xstrdup (obstack_finish (&data->obstack));
926
927 if (depth == 0)
de584861 928 gdb_xml_debug (parser, _("XInclude processing succeeded."));
108546a0
DJ
929 }
930 else
931 result = NULL;
932
933 do_cleanups (back_to);
934 return result;
935}
05a4558a 936#endif /* HAVE_LIBEXPAT */
108546a0
DJ
937\f
938
939/* Return an XML document which was compiled into GDB, from
940 the given FILENAME, or NULL if the file was not compiled in. */
941
942const char *
943fetch_xml_builtin (const char *filename)
944{
945 const char *(*p)[2];
946
947 for (p = xml_builtin; (*p)[0]; p++)
948 if (strcmp ((*p)[0], filename) == 0)
949 return (*p)[1];
950
951 return NULL;
952}
fd79ecee 953
05a4558a
DJ
954/* A to_xfer_partial helper function which reads XML files which were
955 compiled into GDB. The target may call this function from its own
956 to_xfer_partial handler, after converting object and annex to the
957 appropriate filename. */
958
959LONGEST
960xml_builtin_xfer_partial (const char *filename,
961 gdb_byte *readbuf, const gdb_byte *writebuf,
962 ULONGEST offset, LONGEST len)
963{
964 const char *buf;
965 LONGEST len_avail;
966
967 gdb_assert (readbuf != NULL && writebuf == NULL);
968 gdb_assert (filename != NULL);
969
970 buf = fetch_xml_builtin (filename);
971 if (buf == NULL)
972 return -1;
973
974 len_avail = strlen (buf);
975 if (offset >= len_avail)
976 return 0;
977
978 if (len > len_avail - offset)
979 len = len_avail - offset;
980 memcpy (readbuf, buf + offset, len);
981 return len;
982}
983\f
fd79ecee
DJ
984
985static void
e776119f
DJ
986show_debug_xml (struct ui_file *file, int from_tty,
987 struct cmd_list_element *c, const char *value)
fd79ecee 988{
e776119f 989 fprintf_filtered (file, _("XML debugging is %s.\n"), value);
fd79ecee
DJ
990}
991
07e059b5
VP
992void
993obstack_xml_printf (struct obstack *obstack, const char *format, ...)
994{
995 va_list ap;
996 const char *f;
997 const char *prev;
998 int percent = 0;
999
1000 va_start (ap, format);
1001
1002 prev = format;
1003 for (f = format; *f; f++)
1004 {
1005 if (percent)
1006 {
1007 switch (*f)
1008 {
1009 case 's':
1010 {
1011 char *p;
1012 char *a = va_arg (ap, char *);
a109c7c1 1013
07e059b5
VP
1014 obstack_grow (obstack, prev, f - prev - 1);
1015 p = xml_escape_text (a);
1016 obstack_grow_str (obstack, p);
1017 xfree (p);
1018 prev = f + 1;
1019 }
1020 break;
1021 }
1022 percent = 0;
1023 }
1024 else if (*f == '%')
1025 percent = 1;
1026 }
1027
1028 obstack_grow_str (obstack, prev);
1029 va_end (ap);
1030}
1031
a96d9b2e
SDJ
1032char *
1033xml_fetch_content_from_file (const char *filename, void *baton)
1034{
1035 const char *dirname = baton;
1036 FILE *file;
1037 struct cleanup *back_to;
1038 char *text;
1039 size_t len, offset;
1040
1041 if (dirname && *dirname)
1042 {
1043 char *fullname = concat (dirname, "/", filename, (char *) NULL);
a109c7c1 1044
a96d9b2e 1045 if (fullname == NULL)
d26e3629 1046 malloc_failure (0);
a96d9b2e
SDJ
1047 file = fopen (fullname, FOPEN_RT);
1048 xfree (fullname);
1049 }
1050 else
1051 file = fopen (filename, FOPEN_RT);
1052
1053 if (file == NULL)
1054 return NULL;
1055
1056 back_to = make_cleanup_fclose (file);
1057
1058 /* Read in the whole file, one chunk at a time. */
1059 len = 4096;
1060 offset = 0;
1061 text = xmalloc (len);
1062 make_cleanup (free_current_contents, &text);
1063 while (1)
1064 {
1065 size_t bytes_read;
1066
1067 /* Continue reading where the last read left off. Leave at least
1068 one byte so that we can NUL-terminate the result. */
1069 bytes_read = fread (text + offset, 1, len - offset - 1, file);
1070 if (ferror (file))
1071 {
1072 warning (_("Read error from \"%s\""), filename);
1073 do_cleanups (back_to);
1074 return NULL;
1075 }
1076
1077 offset += bytes_read;
1078
1079 if (feof (file))
1080 break;
1081
1082 len = len * 2;
1083 text = xrealloc (text, len);
1084 }
1085
1086 fclose (file);
1087 discard_cleanups (back_to);
1088
1089 text[offset] = '\0';
1090 return text;
1091}
1092
e776119f 1093void _initialize_xml_support (void);
fd79ecee
DJ
1094
1095void
e776119f 1096_initialize_xml_support (void)
fd79ecee 1097{
e776119f
DJ
1098 add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1099 _("Set XML parser debugging."),
1100 _("Show XML parser debugging."),
1101 _("When set, debugging messages for XML parsers "
1102 "are displayed."),
1103 NULL, show_debug_xml,
1104 &setdebuglist, &showdebuglist);
fd79ecee 1105}