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