Add inclusive range support for Rust
[deliverable/binutils-gdb.git] / gdb / xml-support.c
CommitLineData
fd79ecee
DJ
1/* Helper routines for parsing XML using Expat.
2
e2882c85 3 Copyright (C) 2006-2018 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 22#include "xml-support.h"
614c279d 23#include "filestuff.h"
05a4558a 24#include "safe-ctype.h"
a7fc9b61 25#include <vector>
bd8a901f 26#include <string>
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{
a7fc9b61
PA
47 explicit scope_level (const gdb_xml_element *elements_ = NULL)
48 : elements (elements_),
49 element (NULL),
bd8a901f 50 seen (0)
a7fc9b61
PA
51 {}
52
e776119f
DJ
53 /* Elements we allow at this level. */
54 const struct gdb_xml_element *elements;
55
56 /* The element which we are within. */
57 const struct gdb_xml_element *element;
58
59 /* Mask of which elements we've seen at this level (used for
60 optional and repeatable checking). */
61 unsigned int seen;
62
bd8a901f
PA
63 /* Body text accumulation. */
64 std::string body;
e776119f 65};
e776119f
DJ
66
67/* The parser itself, and our additional state. */
68struct gdb_xml_parser
69{
010151c9
PA
70 gdb_xml_parser (const char *name,
71 const gdb_xml_element *elements,
72 void *user_data);
73 ~gdb_xml_parser();
74
4895cde2
PA
75 /* Associate DTD_NAME, which must be the name of a compiled-in DTD,
76 with the parser. */
77 void use_dtd (const char *dtd_name);
78
79 /* Return the name of the expected / default DTD, if specified. */
80 const char *dtd_name ()
81 { return m_dtd_name; }
82
83 /* Invoke the parser on BUFFER. BUFFER is the data to parse, which
84 should be NUL-terminated.
85
86 The return value is 0 for success or -1 for error. It may throw,
87 but only if something unexpected goes wrong during parsing; parse
88 errors will be caught, warned about, and reported as failure. */
89 int parse (const char *buffer);
90
91 /* Issue a debugging message. */
92 void vdebug (const char *format, va_list ap)
93 ATTRIBUTE_PRINTF (2, 0);
94
95 /* Issue an error message, and stop parsing. */
96 void verror (const char *format, va_list ap)
97 ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 0);
98
99 void body_text (const XML_Char *text, int length);
100 void start_element (const XML_Char *name, const XML_Char **attrs);
101 void end_element (const XML_Char *name);
102
103 /* Return the name of this parser. */
104 const char *name ()
105 { return m_name; }
106
107 /* Return the user's callback data, for handlers. */
108 void *user_data ()
109 { return m_user_data; };
110
111 /* Are we the special <xi:include> parser? */
112 void set_is_xinclude (bool is_xinclude)
113 { m_is_xinclude = is_xinclude; }
114
115 /* A thrown error, if any. */
116 void set_error (gdb_exception error)
117 {
118 m_error = error;
119#ifdef HAVE_XML_STOPPARSER
120 XML_StopParser (m_expat_parser, XML_FALSE);
121#endif
122 }
123
124 /* Return the underlying expat parser. */
125 XML_Parser expat_parser ()
126 { return m_expat_parser; }
127
128private:
129 /* The underlying expat parser. */
130 XML_Parser m_expat_parser;
131
132 /* Name of this parser. */
133 const char *m_name;
e776119f 134
4895cde2
PA
135 /* The user's callback data, for handlers. */
136 void *m_user_data;
e776119f 137
a7fc9b61 138 /* Scoping stack. */
4895cde2 139 std::vector<scope_level> m_scopes;
e776119f 140
4895cde2
PA
141/* A thrown error, if any. */
142 struct gdb_exception m_error;
108546a0 143
4895cde2
PA
144 /* The line of the thrown error, or 0. */
145 int m_last_line;
146
147 /* The name of the expected / default DTD, if specified. */
148 const char *m_dtd_name;
149
150 /* Are we the special <xi:include> parser? */
151 bool m_is_xinclude;
e776119f
DJ
152};
153
154/* Process some body text. We accumulate the text for later use; it's
155 wrong to do anything with it immediately, because a single block of
156 text might be broken up into multiple calls to this function. */
157
4895cde2
PA
158void
159gdb_xml_parser::body_text (const XML_Char *text, int length)
160{
161 if (m_error.reason < 0)
162 return;
163
164 scope_level &scope = m_scopes.back ();
165 scope.body.append (text, length);
166}
167
e776119f
DJ
168static void
169gdb_xml_body_text (void *data, const XML_Char *text, int length)
170{
19ba03f4 171 struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
e776119f 172
4895cde2 173 parser->body_text (text, length);
e776119f 174}
fd79ecee 175
e776119f 176/* Issue a debugging message from one of PARSER's handlers. */
fd79ecee 177
e776119f 178void
4895cde2 179gdb_xml_parser::vdebug (const char *format, va_list ap)
e776119f 180{
4895cde2 181 int line = XML_GetCurrentLineNumber (m_expat_parser);
e776119f
DJ
182 char *message;
183
e776119f
DJ
184 message = xstrvprintf (format, ap);
185 if (line)
186 fprintf_unfiltered (gdb_stderr, "%s (line %d): %s\n",
4895cde2 187 m_name, line, message);
e776119f
DJ
188 else
189 fprintf_unfiltered (gdb_stderr, "%s: %s\n",
4895cde2 190 m_name, message);
e776119f
DJ
191 xfree (message);
192}
193
4895cde2
PA
194void
195gdb_xml_debug (struct gdb_xml_parser *parser, const char *format, ...)
196{
197 if (!debug_xml)
198 return;
199
200 va_list ap;
201 va_start (ap, format);
202 parser->vdebug (format, ap);
203 va_end (ap);
204}
205
e776119f
DJ
206/* Issue an error message from one of PARSER's handlers, and stop
207 parsing. */
208
4895cde2
PA
209void
210gdb_xml_parser::verror (const char *format, va_list ap)
211{
212 int line = XML_GetCurrentLineNumber (m_expat_parser);
213
214 m_last_line = line;
215 throw_verror (XML_PARSE_ERROR, format, ap);
216}
217
e776119f
DJ
218void
219gdb_xml_error (struct gdb_xml_parser *parser, const char *format, ...)
220{
e776119f 221 va_list ap;
e776119f 222 va_start (ap, format);
4895cde2
PA
223 parser->verror (format, ap);
224 va_end (ap);
e776119f
DJ
225}
226
3d2c1d41
PA
227/* Find the attribute named NAME in the set of parsed attributes
228 ATTRIBUTES. Returns NULL if not found. */
229
230struct gdb_xml_value *
4d0fdd9b
SM
231xml_find_attribute (std::vector<gdb_xml_value> &attributes,
232 const char *name)
3d2c1d41 233{
4d0fdd9b
SM
234 for (gdb_xml_value &value : attributes)
235 if (strcmp (value.name, name) == 0)
236 return &value;
3d2c1d41
PA
237
238 return NULL;
239}
240
4895cde2
PA
241/* Handle the start of an element. NAME is the element, and ATTRS are
242 the names and values of this element's attributes. */
e776119f 243
4895cde2
PA
244void
245gdb_xml_parser::start_element (const XML_Char *name,
246 const XML_Char **attrs)
fd79ecee 247{
4895cde2
PA
248 if (m_error.reason < 0)
249 return;
250
e776119f
DJ
251 const struct gdb_xml_element *element;
252 const struct gdb_xml_attribute *attribute;
e776119f 253 unsigned int seen;
e776119f 254
e776119f
DJ
255 /* Push an error scope. If we return or throw an exception before
256 filling this in, it will tell us to ignore children of this
a7fc9b61
PA
257 element. Note we don't take a reference to the element yet
258 because further below we'll process the element which may recurse
259 back here and push more elements to the vector. When the
260 recursion unrolls all such elements will have been popped back
261 already, but if one of those pushes reallocates the vector,
262 previous element references will be invalidated. */
4895cde2 263 m_scopes.emplace_back ();
a7fc9b61
PA
264
265 /* Get a reference to the current scope. */
4895cde2 266 scope_level &scope = m_scopes[m_scopes.size () - 2];
e776119f 267
4895cde2 268 gdb_xml_debug (this, _("Entering element <%s>"), name);
e776119f
DJ
269
270 /* Find this element in the list of the current scope's allowed
271 children. Record that we've seen it. */
272
273 seen = 1;
a7fc9b61 274 for (element = scope.elements; element && element->name;
e776119f
DJ
275 element++, seen <<= 1)
276 if (strcmp (element->name, name) == 0)
277 break;
278
279 if (element == NULL || element->name == NULL)
280 {
108546a0
DJ
281 /* If we're working on XInclude, <xi:include> can be the child
282 of absolutely anything. Copy the previous scope's element
283 list into the new scope even if there was no match. */
4895cde2 284 if (m_is_xinclude)
108546a0 285 {
4895cde2 286 XML_DefaultCurrent (m_expat_parser);
108546a0 287
4895cde2 288 scope_level &unknown_scope = m_scopes.back ();
a7fc9b61 289 unknown_scope.elements = scope.elements;
108546a0
DJ
290 return;
291 }
292
4895cde2 293 gdb_xml_debug (this, _("Element <%s> unknown"), name);
e776119f
DJ
294 return;
295 }
296
a7fc9b61 297 if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope.seen))
4895cde2 298 gdb_xml_error (this, _("Element <%s> only expected once"), name);
e776119f 299
a7fc9b61 300 scope.seen |= seen;
e776119f 301
4d0fdd9b 302 std::vector<gdb_xml_value> attributes;
108546a0 303
e776119f
DJ
304 for (attribute = element->attributes;
305 attribute != NULL && attribute->name != NULL;
306 attribute++)
307 {
308 const char *val = NULL;
309 const XML_Char **p;
310 void *parsed_value;
e776119f
DJ
311
312 for (p = attrs; *p != NULL; p += 2)
313 if (!strcmp (attribute->name, p[0]))
314 {
315 val = p[1];
316 break;
317 }
318
319 if (*p != NULL && val == NULL)
320 {
4895cde2 321 gdb_xml_debug (this, _("Attribute \"%s\" missing a value"),
e776119f
DJ
322 attribute->name);
323 continue;
324 }
325
326 if (*p == NULL && !(attribute->flags & GDB_XML_AF_OPTIONAL))
327 {
4895cde2 328 gdb_xml_error (this, _("Required attribute \"%s\" of "
e776119f
DJ
329 "<%s> not specified"),
330 attribute->name, element->name);
331 continue;
332 }
333
334 if (*p == NULL)
335 continue;
336
4895cde2 337 gdb_xml_debug (this, _("Parsing attribute %s=\"%s\""),
e776119f
DJ
338 attribute->name, val);
339
340 if (attribute->handler)
4895cde2 341 parsed_value = attribute->handler (this, attribute, val);
e776119f
DJ
342 else
343 parsed_value = xstrdup (val);
344
4d0fdd9b 345 attributes.emplace_back (attribute->name, parsed_value);
e776119f
DJ
346 }
347
348 /* Check for unrecognized attributes. */
349 if (debug_xml)
fd79ecee 350 {
e776119f
DJ
351 const XML_Char **p;
352
353 for (p = attrs; *p != NULL; p += 2)
354 {
355 for (attribute = element->attributes;
356 attribute != NULL && attribute->name != NULL;
357 attribute++)
358 if (strcmp (attribute->name, *p) == 0)
359 break;
360
361 if (attribute == NULL || attribute->name == NULL)
4895cde2 362 gdb_xml_debug (this, _("Ignoring unknown attribute %s"), *p);
e776119f
DJ
363 }
364 }
365
366 /* Call the element handler if there is one. */
367 if (element->start_handler)
4895cde2 368 element->start_handler (this, element, m_user_data, attributes);
e776119f 369
a7fc9b61
PA
370 /* Fill in a new scope level. Note that we must delay getting a
371 back reference till here because above we might have recursed,
372 which may have reallocated the vector which invalidates
373 iterators/pointers/references. */
4895cde2 374 scope_level &new_scope = m_scopes.back ();
a7fc9b61
PA
375 new_scope.element = element;
376 new_scope.elements = element->children;
e776119f
DJ
377}
378
379/* Wrapper for gdb_xml_start_element, to prevent throwing exceptions
380 through expat. */
381
382static void
383gdb_xml_start_element_wrapper (void *data, const XML_Char *name,
384 const XML_Char **attrs)
385{
19ba03f4 386 struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
e776119f 387
492d29ea 388 TRY
e776119f 389 {
4895cde2 390 parser->start_element (name, attrs);
e776119f 391 }
492d29ea 392 CATCH (ex, RETURN_MASK_ALL)
e776119f 393 {
4895cde2 394 parser->set_error (ex);
fd79ecee 395 }
492d29ea 396 END_CATCH
e776119f
DJ
397}
398
4895cde2 399/* Handle the end of an element. NAME is the current element. */
e776119f 400
4895cde2
PA
401void
402gdb_xml_parser::end_element (const XML_Char *name)
e776119f 403{
4895cde2
PA
404 if (m_error.reason < 0)
405 return;
406
407 struct scope_level *scope = &m_scopes.back ();
e776119f
DJ
408 const struct gdb_xml_element *element;
409 unsigned int seen;
e776119f 410
4895cde2 411 gdb_xml_debug (this, _("Leaving element <%s>"), name);
e776119f
DJ
412
413 for (element = scope->elements, seen = 1;
414 element != NULL && element->name != NULL;
415 element++, seen <<= 1)
416 if ((scope->seen & seen) == 0
417 && (element->flags & GDB_XML_EF_OPTIONAL) == 0)
4895cde2 418 gdb_xml_error (this, _("Required element <%s> is missing"),
e776119f
DJ
419 element->name);
420
581e13c1 421 /* Call the element processor. */
108546a0 422 if (scope->element != NULL && scope->element->end_handler)
e776119f 423 {
bd8a901f 424 const char *body;
e776119f 425
bd8a901f
PA
426 if (scope->body.empty ())
427 body = "";
108546a0
DJ
428 else
429 {
430 int length;
e776119f 431
bd8a901f
PA
432 length = scope->body.size ();
433 body = scope->body.c_str ();
e776119f 434
108546a0 435 /* Strip leading and trailing whitespace. */
bd8a901f
PA
436 while (length > 0 && ISSPACE (body[length - 1]))
437 length--;
438 scope->body.erase (length);
108546a0
DJ
439 while (*body && ISSPACE (*body))
440 body++;
441 }
442
4895cde2
PA
443 scope->element->end_handler (this, scope->element,
444 m_user_data, body);
108546a0
DJ
445 }
446 else if (scope->element == NULL)
4895cde2 447 XML_DefaultCurrent (m_expat_parser);
e776119f
DJ
448
449 /* Pop the scope level. */
4895cde2 450 m_scopes.pop_back ();
e776119f
DJ
451}
452
453/* Wrapper for gdb_xml_end_element, to prevent throwing exceptions
454 through expat. */
455
456static void
457gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
458{
19ba03f4 459 struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
e776119f 460
492d29ea 461 TRY
e776119f 462 {
4895cde2 463 parser->end_element (name);
e776119f 464 }
492d29ea 465 CATCH (ex, RETURN_MASK_ALL)
e776119f 466 {
4895cde2 467 parser->set_error (ex);
e776119f 468 }
492d29ea 469 END_CATCH
e776119f
DJ
470}
471
472/* Free a parser and all its associated state. */
473
010151c9 474gdb_xml_parser::~gdb_xml_parser ()
e776119f 475{
4895cde2 476 XML_ParserFree (m_expat_parser);
e776119f
DJ
477}
478
010151c9
PA
479/* Initialize a parser. */
480
4895cde2 481gdb_xml_parser::gdb_xml_parser (const char *name,
010151c9 482 const gdb_xml_element *elements,
4895cde2
PA
483 void *user_data)
484 : m_name (name),
485 m_user_data (user_data),
486 m_error (exception_none),
487 m_last_line (0),
488 m_dtd_name (NULL),
489 m_is_xinclude (false)
490{
491 m_expat_parser = XML_ParserCreateNS (NULL, '!');
492 if (m_expat_parser == NULL)
010151c9 493 malloc_failure (0);
e776119f 494
4895cde2 495 XML_SetUserData (m_expat_parser, this);
e776119f
DJ
496
497 /* Set the callbacks. */
4895cde2 498 XML_SetElementHandler (m_expat_parser, gdb_xml_start_element_wrapper,
e776119f 499 gdb_xml_end_element_wrapper);
4895cde2 500 XML_SetCharacterDataHandler (m_expat_parser, gdb_xml_body_text);
e776119f
DJ
501
502 /* Initialize the outer scope. */
4895cde2 503 m_scopes.emplace_back (elements);
efc0eabd
PA
504}
505
108546a0
DJ
506/* External entity handler. The only external entities we support
507 are those compiled into GDB (we do not fetch entities from the
508 target). */
509
510static int XMLCALL
511gdb_xml_fetch_external_entity (XML_Parser expat_parser,
512 const XML_Char *context,
513 const XML_Char *base,
514 const XML_Char *systemId,
515 const XML_Char *publicId)
516{
108546a0
DJ
517 XML_Parser entity_parser;
518 const char *text;
519 enum XML_Status status;
520
521 if (systemId == NULL)
522 {
4895cde2
PA
523 gdb_xml_parser *parser
524 = (gdb_xml_parser *) XML_GetUserData (expat_parser);
525
526 text = fetch_xml_builtin (parser->dtd_name ());
108546a0 527 if (text == NULL)
9b20d036
MS
528 internal_error (__FILE__, __LINE__,
529 _("could not locate built-in DTD %s"),
4895cde2 530 parser->dtd_name ());
108546a0
DJ
531 }
532 else
533 {
534 text = fetch_xml_builtin (systemId);
535 if (text == NULL)
536 return XML_STATUS_ERROR;
537 }
538
4895cde2
PA
539 entity_parser = XML_ExternalEntityParserCreate (expat_parser,
540 context, NULL);
108546a0
DJ
541
542 /* Don't use our handlers for the contents of the DTD. Just let expat
543 process it. */
544 XML_SetElementHandler (entity_parser, NULL, NULL);
545 XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
546 XML_SetXmlDeclHandler (entity_parser, NULL);
547 XML_SetDefaultHandler (entity_parser, NULL);
548 XML_SetUserData (entity_parser, NULL);
549
550 status = XML_Parse (entity_parser, text, strlen (text), 1);
551
552 XML_ParserFree (entity_parser);
553 return status;
554}
555
108546a0 556void
4895cde2 557gdb_xml_parser::use_dtd (const char *dtd_name)
108546a0
DJ
558{
559 enum XML_Error err;
560
4895cde2 561 m_dtd_name = dtd_name;
108546a0 562
4895cde2 563 XML_SetParamEntityParsing (m_expat_parser,
108546a0 564 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
4895cde2 565 XML_SetExternalEntityRefHandler (m_expat_parser,
108546a0
DJ
566 gdb_xml_fetch_external_entity);
567
568 /* Even if no DTD is provided, use the built-in DTD anyway. */
4895cde2 569 err = XML_UseForeignDTD (m_expat_parser, XML_TRUE);
108546a0
DJ
570 if (err != XML_ERROR_NONE)
571 internal_error (__FILE__, __LINE__,
9b20d036
MS
572 _("XML_UseForeignDTD failed: %s"),
573 XML_ErrorString (err));
108546a0
DJ
574}
575
e776119f
DJ
576/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
577 should be NUL-terminated.
578
579 The return value is 0 for success or -1 for error. It may throw,
580 but only if something unexpected goes wrong during parsing; parse
581 errors will be caught, warned about, and reported as failure. */
582
583int
4895cde2 584gdb_xml_parser::parse (const char *buffer)
e776119f
DJ
585{
586 enum XML_Status status;
587 const char *error_string;
588
4895cde2 589 gdb_xml_debug (this, _("Starting:\n%s"), buffer);
de584861 590
4895cde2 591 status = XML_Parse (m_expat_parser, buffer, strlen (buffer), 1);
e776119f 592
4895cde2 593 if (status == XML_STATUS_OK && m_error.reason == 0)
e776119f
DJ
594 return 0;
595
4895cde2
PA
596 if (m_error.reason == RETURN_ERROR
597 && m_error.error == XML_PARSE_ERROR)
e776119f 598 {
4895cde2
PA
599 gdb_assert (m_error.message != NULL);
600 error_string = m_error.message;
e776119f
DJ
601 }
602 else if (status == XML_STATUS_ERROR)
603 {
4895cde2 604 enum XML_Error err = XML_GetErrorCode (m_expat_parser);
a109c7c1 605
e776119f
DJ
606 error_string = XML_ErrorString (err);
607 }
608 else
609 {
4895cde2
PA
610 gdb_assert (m_error.reason < 0);
611 throw_exception (m_error);
e776119f
DJ
612 }
613
4895cde2
PA
614 if (m_last_line != 0)
615 warning (_("while parsing %s (at line %d): %s"), m_name,
616 m_last_line, error_string);
e776119f 617 else
4895cde2 618 warning (_("while parsing %s: %s"), m_name, error_string);
e776119f
DJ
619
620 return -1;
fd79ecee
DJ
621}
622
efc0eabd
PA
623int
624gdb_xml_parse_quick (const char *name, const char *dtd_name,
625 const struct gdb_xml_element *elements,
626 const char *document, void *user_data)
627{
010151c9 628 gdb_xml_parser parser (name, elements, user_data);
efc0eabd 629 if (dtd_name != NULL)
4895cde2
PA
630 parser.use_dtd (dtd_name);
631 return parser.parse (document);
efc0eabd
PA
632}
633
fd79ecee
DJ
634/* Parse a field VALSTR that we expect to contain an integer value.
635 The integer is returned in *VALP. The string is parsed with an
636 equivalent to strtoul.
637
638 Returns 0 for success, -1 for error. */
639
640static int
641xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
642{
643 const char *endptr;
644 ULONGEST result;
645
646 if (*valstr == '\0')
647 return -1;
648
649 result = strtoulst (valstr, &endptr, 0);
650 if (*endptr != '\0')
651 return -1;
652
653 *valp = result;
654 return 0;
655}
656
e776119f
DJ
657/* Parse an integer string into a ULONGEST and return it, or call
658 gdb_xml_error if it could not be parsed. */
fd79ecee
DJ
659
660ULONGEST
e776119f 661gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
fd79ecee
DJ
662{
663 ULONGEST result;
fd79ecee
DJ
664
665 if (xml_parse_unsigned_integer (value, &result) != 0)
e776119f
DJ
666 gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
667
fd79ecee
DJ
668 return result;
669}
670
e776119f
DJ
671/* Parse an integer attribute into a ULONGEST. */
672
673void *
674gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
675 const struct gdb_xml_attribute *attribute,
676 const char *value)
677{
678 ULONGEST result;
679 void *ret;
fd79ecee 680
e776119f
DJ
681 if (xml_parse_unsigned_integer (value, &result) != 0)
682 gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
683 attribute->name, value);
fd79ecee 684
8d749320 685 ret = XNEW (ULONGEST);
e776119f
DJ
686 memcpy (ret, &result, sizeof (result));
687 return ret;
688}
689
123dc839
DJ
690/* A handler_data for yes/no boolean values. */
691
692const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
693 { "yes", 1 },
694 { "no", 0 },
695 { NULL, 0 }
696};
697
e776119f
DJ
698/* Map NAME to VALUE. A struct gdb_xml_enum * should be saved as the
699 value of handler_data when using gdb_xml_parse_attr_enum to parse a
700 fixed list of possible strings. The list is terminated by an entry
701 with NAME == NULL. */
702
703void *
704gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
705 const struct gdb_xml_attribute *attribute,
706 const char *value)
fd79ecee 707{
19ba03f4
SM
708 const struct gdb_xml_enum *enums
709 = (const struct gdb_xml_enum *) attribute->handler_data;
e776119f 710 void *ret;
fd79ecee 711
19ba03f4
SM
712 for (enums = (const struct gdb_xml_enum *) attribute->handler_data;
713 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{
bd8a901f
PA
751 xinclude_parsing_data (std::string &output_,
752 xml_fetch_another fetcher_, void *fetcher_baton_,
010151c9 753 int include_depth_)
bd8a901f
PA
754 : output (output_),
755 skip_depth (0),
010151c9
PA
756 include_depth (include_depth_),
757 fetcher (fetcher_),
758 fetcher_baton (fetcher_baton_)
bd8a901f 759 {}
010151c9 760
bd8a901f
PA
761 /* Where the output goes. */
762 std::string &output;
108546a0
DJ
763
764 /* A count indicating whether we are in an element whose
765 children should not be copied to the output, and if so,
766 how deep we are nested. This is used for anything inside
767 an xi:include, and for the DTD. */
768 int skip_depth;
769
770 /* The number of <xi:include> elements currently being processed,
771 to detect loops. */
772 int include_depth;
773
774 /* A function to call to obtain additional features, and its
775 baton. */
776 xml_fetch_another fetcher;
777 void *fetcher_baton;
778};
779
780static void
781xinclude_start_include (struct gdb_xml_parser *parser,
782 const struct gdb_xml_element *element,
4d0fdd9b
SM
783 void *user_data,
784 std::vector<gdb_xml_value> &attributes)
108546a0 785{
19ba03f4
SM
786 struct xinclude_parsing_data *data
787 = (struct xinclude_parsing_data *) user_data;
4d0fdd9b 788 char *href = (char *) xml_find_attribute (attributes, "href")->value.get ();
108546a0
DJ
789
790 gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
791
792 if (data->include_depth > MAX_XINCLUDE_DEPTH)
793 gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
794 MAX_XINCLUDE_DEPTH);
795
9018be22
SM
796 gdb::optional<gdb::char_vector> text
797 = data->fetcher (href, data->fetcher_baton);
798 if (!text)
108546a0 799 gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
108546a0 800
4895cde2 801 if (!xml_process_xincludes (data->output, parser->name (),
9018be22 802 text->data (), data->fetcher,
bd8a901f
PA
803 data->fetcher_baton,
804 data->include_depth + 1))
108546a0
DJ
805 gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
806
108546a0
DJ
807 data->skip_depth++;
808}
809
810static void
811xinclude_end_include (struct gdb_xml_parser *parser,
812 const struct gdb_xml_element *element,
813 void *user_data, const char *body_text)
814{
19ba03f4
SM
815 struct xinclude_parsing_data *data
816 = (struct xinclude_parsing_data *) user_data;
108546a0
DJ
817
818 data->skip_depth--;
819}
820
821static void XMLCALL
822xml_xinclude_default (void *data_, const XML_Char *s, int len)
823{
19ba03f4 824 struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
4895cde2 825 xinclude_parsing_data *data = (xinclude_parsing_data *) parser->user_data ();
108546a0
DJ
826
827 /* If we are inside of e.g. xi:include or the DTD, don't save this
828 string. */
829 if (data->skip_depth)
830 return;
831
832 /* Otherwise just add it to the end of the document we're building
833 up. */
bd8a901f 834 data->output.append (s, len);
108546a0
DJ
835}
836
837static void XMLCALL
838xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
839 const XML_Char *sysid, const XML_Char *pubid,
840 int has_internal_subset)
841{
19ba03f4 842 struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
4895cde2 843 xinclude_parsing_data *data = (xinclude_parsing_data *) parser->user_data ();
108546a0
DJ
844
845 /* Don't print out the doctype, or the contents of the DTD internal
846 subset, if any. */
847 data->skip_depth++;
848}
849
850static void XMLCALL
851xml_xinclude_end_doctype (void *data_)
852{
19ba03f4 853 struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data_;
4895cde2 854 xinclude_parsing_data *data = (xinclude_parsing_data *) parser->user_data ();
108546a0
DJ
855
856 data->skip_depth--;
857}
858
859static void XMLCALL
860xml_xinclude_xml_decl (void *data_, const XML_Char *version,
861 const XML_Char *encoding, int standalone)
862{
863 /* Do nothing - this function prevents the default handler from
864 being called, thus suppressing the XML declaration from the
865 output. */
866}
867
108546a0
DJ
868const struct gdb_xml_attribute xinclude_attributes[] = {
869 { "href", GDB_XML_AF_NONE, NULL, NULL },
870 { NULL, GDB_XML_AF_NONE, NULL, NULL }
871};
872
873const struct gdb_xml_element xinclude_elements[] = {
874 { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
875 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
876 xinclude_start_include, xinclude_end_include },
877 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
878};
879
880/* The main entry point for <xi:include> processing. */
881
bd8a901f
PA
882bool
883xml_process_xincludes (std::string &result,
884 const char *name, const char *text,
108546a0
DJ
885 xml_fetch_another fetcher, void *fetcher_baton,
886 int depth)
887{
bd8a901f 888 xinclude_parsing_data data (result, fetcher, fetcher_baton, depth);
108546a0 889
010151c9 890 gdb_xml_parser parser (name, xinclude_elements, &data);
4895cde2 891 parser.set_is_xinclude (true);
108546a0 892
4895cde2
PA
893 XML_SetCharacterDataHandler (parser.expat_parser (), NULL);
894 XML_SetDefaultHandler (parser.expat_parser (), xml_xinclude_default);
108546a0
DJ
895
896 /* Always discard the XML version declarations; the only important
897 thing this provides is encoding, and our result will have been
898 converted to UTF-8. */
4895cde2 899 XML_SetXmlDeclHandler (parser.expat_parser (), xml_xinclude_xml_decl);
108546a0
DJ
900
901 if (depth > 0)
902 /* Discard the doctype for included documents. */
4895cde2 903 XML_SetDoctypeDeclHandler (parser.expat_parser (),
108546a0
DJ
904 xml_xinclude_start_doctype,
905 xml_xinclude_end_doctype);
906
4895cde2 907 parser.use_dtd ("xinclude.dtd");
108546a0 908
4895cde2 909 if (parser.parse (text) == 0)
108546a0 910 {
108546a0 911 if (depth == 0)
010151c9 912 gdb_xml_debug (&parser, _("XInclude processing succeeded."));
bd8a901f 913 return true;
108546a0 914 }
108546a0 915
bd8a901f 916 return false;
108546a0 917}
05a4558a 918#endif /* HAVE_LIBEXPAT */
108546a0
DJ
919\f
920
921/* Return an XML document which was compiled into GDB, from
922 the given FILENAME, or NULL if the file was not compiled in. */
923
924const char *
925fetch_xml_builtin (const char *filename)
926{
927 const char *(*p)[2];
928
929 for (p = xml_builtin; (*p)[0]; p++)
930 if (strcmp ((*p)[0], filename) == 0)
931 return (*p)[1];
932
933 return NULL;
934}
fd79ecee 935
05a4558a
DJ
936/* A to_xfer_partial helper function which reads XML files which were
937 compiled into GDB. The target may call this function from its own
938 to_xfer_partial handler, after converting object and annex to the
939 appropriate filename. */
940
941LONGEST
942xml_builtin_xfer_partial (const char *filename,
943 gdb_byte *readbuf, const gdb_byte *writebuf,
944 ULONGEST offset, LONGEST len)
945{
946 const char *buf;
947 LONGEST len_avail;
948
949 gdb_assert (readbuf != NULL && writebuf == NULL);
950 gdb_assert (filename != NULL);
951
952 buf = fetch_xml_builtin (filename);
953 if (buf == NULL)
954 return -1;
955
956 len_avail = strlen (buf);
957 if (offset >= len_avail)
958 return 0;
959
960 if (len > len_avail - offset)
961 len = len_avail - offset;
962 memcpy (readbuf, buf + offset, len);
963 return len;
964}
965\f
fd79ecee
DJ
966
967static void
e776119f
DJ
968show_debug_xml (struct ui_file *file, int from_tty,
969 struct cmd_list_element *c, const char *value)
fd79ecee 970{
e776119f 971 fprintf_filtered (file, _("XML debugging is %s.\n"), value);
fd79ecee
DJ
972}
973
9018be22 974gdb::optional<gdb::char_vector>
a96d9b2e
SDJ
975xml_fetch_content_from_file (const char *filename, void *baton)
976{
19ba03f4 977 const char *dirname = (const char *) baton;
d419f42d 978 gdb_file_up file;
a96d9b2e
SDJ
979
980 if (dirname && *dirname)
981 {
982 char *fullname = concat (dirname, "/", filename, (char *) NULL);
a109c7c1 983
a96d9b2e 984 if (fullname == NULL)
d26e3629 985 malloc_failure (0);
614c279d 986 file = gdb_fopen_cloexec (fullname, FOPEN_RT);
a96d9b2e
SDJ
987 xfree (fullname);
988 }
989 else
614c279d 990 file = gdb_fopen_cloexec (filename, FOPEN_RT);
a96d9b2e
SDJ
991
992 if (file == NULL)
9018be22 993 return {};
a96d9b2e 994
2edf834e 995 /* Read in the whole file. */
a96d9b2e 996
2edf834e 997 size_t len;
a96d9b2e 998
2edf834e
PA
999 if (fseek (file.get (), 0, SEEK_END) == -1)
1000 perror_with_name (_("seek to end of file"));
1001 len = ftell (file.get ());
1002 rewind (file.get ());
a96d9b2e 1003
9018be22 1004 gdb::char_vector text (len + 1);
a96d9b2e 1005
9018be22 1006 if (fread (text.data (), 1, len, file.get ()) != len
63929e84 1007 || ferror (file.get ()))
2edf834e
PA
1008 {
1009 warning (_("Read error from \"%s\""), filename);
9018be22 1010 return {};
a96d9b2e
SDJ
1011 }
1012
9018be22 1013 text.back () = '\0';
a96d9b2e
SDJ
1014 return text;
1015}
1016
fd79ecee 1017void
e776119f 1018_initialize_xml_support (void)
fd79ecee 1019{
e776119f
DJ
1020 add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
1021 _("Set XML parser debugging."),
1022 _("Show XML parser debugging."),
1023 _("When set, debugging messages for XML parsers "
1024 "are displayed."),
1025 NULL, show_debug_xml,
1026 &setdebuglist, &showdebuglist);
fd79ecee 1027}
This page took 1.839493 seconds and 4 git commands to generate.