GDB (API)
|
00001 /* Helper routines for parsing XML using Expat. 00002 00003 Copyright (C) 2006-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "gdbcmd.h" 00022 #include "exceptions.h" 00023 #include "xml-support.h" 00024 #include "filestuff.h" 00025 00026 #include "gdb_string.h" 00027 #include "safe-ctype.h" 00028 00029 /* Debugging flag. */ 00030 static int debug_xml; 00031 00032 /* The contents of this file are only useful if XML support is 00033 available. */ 00034 #ifdef HAVE_LIBEXPAT 00035 00036 #include "gdb_expat.h" 00037 00038 /* The maximum depth of <xi:include> nesting. No need to be miserly, 00039 we just want to avoid running out of stack on loops. */ 00040 #define MAX_XINCLUDE_DEPTH 30 00041 00042 /* Simplified XML parser infrastructure. */ 00043 00044 /* A parsing level -- used to keep track of the current element 00045 nesting. */ 00046 struct scope_level 00047 { 00048 /* Elements we allow at this level. */ 00049 const struct gdb_xml_element *elements; 00050 00051 /* The element which we are within. */ 00052 const struct gdb_xml_element *element; 00053 00054 /* Mask of which elements we've seen at this level (used for 00055 optional and repeatable checking). */ 00056 unsigned int seen; 00057 00058 /* Body text accumulation. */ 00059 struct obstack *body; 00060 }; 00061 typedef struct scope_level scope_level_s; 00062 DEF_VEC_O(scope_level_s); 00063 00064 /* The parser itself, and our additional state. */ 00065 struct gdb_xml_parser 00066 { 00067 XML_Parser expat_parser; /* The underlying expat parser. */ 00068 00069 const char *name; /* Name of this parser. */ 00070 void *user_data; /* The user's callback data, for handlers. */ 00071 00072 VEC(scope_level_s) *scopes; /* Scoping stack. */ 00073 00074 struct gdb_exception error; /* A thrown error, if any. */ 00075 int last_line; /* The line of the thrown error, or 0. */ 00076 00077 const char *dtd_name; /* The name of the expected / default DTD, 00078 if specified. */ 00079 int is_xinclude; /* Are we the special <xi:include> parser? */ 00080 }; 00081 00082 /* Process some body text. We accumulate the text for later use; it's 00083 wrong to do anything with it immediately, because a single block of 00084 text might be broken up into multiple calls to this function. */ 00085 00086 static void 00087 gdb_xml_body_text (void *data, const XML_Char *text, int length) 00088 { 00089 struct gdb_xml_parser *parser = data; 00090 struct scope_level *scope = VEC_last (scope_level_s, parser->scopes); 00091 00092 if (parser->error.reason < 0) 00093 return; 00094 00095 if (scope->body == NULL) 00096 { 00097 scope->body = XZALLOC (struct obstack); 00098 obstack_init (scope->body); 00099 } 00100 00101 obstack_grow (scope->body, text, length); 00102 } 00103 00104 /* Issue a debugging message from one of PARSER's handlers. */ 00105 00106 void 00107 gdb_xml_debug (struct gdb_xml_parser *parser, const char *format, ...) 00108 { 00109 int line = XML_GetCurrentLineNumber (parser->expat_parser); 00110 va_list ap; 00111 char *message; 00112 00113 if (!debug_xml) 00114 return; 00115 00116 va_start (ap, format); 00117 message = xstrvprintf (format, ap); 00118 if (line) 00119 fprintf_unfiltered (gdb_stderr, "%s (line %d): %s\n", 00120 parser->name, line, message); 00121 else 00122 fprintf_unfiltered (gdb_stderr, "%s: %s\n", 00123 parser->name, message); 00124 xfree (message); 00125 } 00126 00127 /* Issue an error message from one of PARSER's handlers, and stop 00128 parsing. */ 00129 00130 void 00131 gdb_xml_error (struct gdb_xml_parser *parser, const char *format, ...) 00132 { 00133 int line = XML_GetCurrentLineNumber (parser->expat_parser); 00134 va_list ap; 00135 00136 parser->last_line = line; 00137 va_start (ap, format); 00138 throw_verror (XML_PARSE_ERROR, format, ap); 00139 } 00140 00141 /* Find the attribute named NAME in the set of parsed attributes 00142 ATTRIBUTES. Returns NULL if not found. */ 00143 00144 struct gdb_xml_value * 00145 xml_find_attribute (VEC(gdb_xml_value_s) *attributes, const char *name) 00146 { 00147 struct gdb_xml_value *value; 00148 int ix; 00149 00150 for (ix = 0; VEC_iterate (gdb_xml_value_s, attributes, ix, value); ix++) 00151 if (strcmp (value->name, name) == 0) 00152 return value; 00153 00154 return NULL; 00155 } 00156 00157 /* Clean up a vector of parsed attribute values. */ 00158 00159 static void 00160 gdb_xml_values_cleanup (void *data) 00161 { 00162 VEC(gdb_xml_value_s) **values = data; 00163 struct gdb_xml_value *value; 00164 int ix; 00165 00166 for (ix = 0; VEC_iterate (gdb_xml_value_s, *values, ix, value); ix++) 00167 xfree (value->value); 00168 VEC_free (gdb_xml_value_s, *values); 00169 } 00170 00171 /* Handle the start of an element. DATA is our local XML parser, NAME 00172 is the element, and ATTRS are the names and values of this 00173 element's attributes. */ 00174 00175 static void 00176 gdb_xml_start_element (void *data, const XML_Char *name, 00177 const XML_Char **attrs) 00178 { 00179 struct gdb_xml_parser *parser = data; 00180 struct scope_level *scope; 00181 struct scope_level new_scope; 00182 const struct gdb_xml_element *element; 00183 const struct gdb_xml_attribute *attribute; 00184 VEC(gdb_xml_value_s) *attributes = NULL; 00185 unsigned int seen; 00186 struct cleanup *back_to; 00187 00188 /* Push an error scope. If we return or throw an exception before 00189 filling this in, it will tell us to ignore children of this 00190 element. */ 00191 VEC_reserve (scope_level_s, parser->scopes, 1); 00192 scope = VEC_last (scope_level_s, parser->scopes); 00193 memset (&new_scope, 0, sizeof (new_scope)); 00194 VEC_quick_push (scope_level_s, parser->scopes, &new_scope); 00195 00196 gdb_xml_debug (parser, _("Entering element <%s>"), name); 00197 00198 /* Find this element in the list of the current scope's allowed 00199 children. Record that we've seen it. */ 00200 00201 seen = 1; 00202 for (element = scope->elements; element && element->name; 00203 element++, seen <<= 1) 00204 if (strcmp (element->name, name) == 0) 00205 break; 00206 00207 if (element == NULL || element->name == NULL) 00208 { 00209 /* If we're working on XInclude, <xi:include> can be the child 00210 of absolutely anything. Copy the previous scope's element 00211 list into the new scope even if there was no match. */ 00212 if (parser->is_xinclude) 00213 { 00214 struct scope_level *unknown_scope; 00215 00216 XML_DefaultCurrent (parser->expat_parser); 00217 00218 unknown_scope = VEC_last (scope_level_s, parser->scopes); 00219 unknown_scope->elements = scope->elements; 00220 return; 00221 } 00222 00223 gdb_xml_debug (parser, _("Element <%s> unknown"), name); 00224 return; 00225 } 00226 00227 if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope->seen)) 00228 gdb_xml_error (parser, _("Element <%s> only expected once"), name); 00229 00230 scope->seen |= seen; 00231 00232 back_to = make_cleanup (gdb_xml_values_cleanup, &attributes); 00233 00234 for (attribute = element->attributes; 00235 attribute != NULL && attribute->name != NULL; 00236 attribute++) 00237 { 00238 const char *val = NULL; 00239 const XML_Char **p; 00240 void *parsed_value; 00241 struct gdb_xml_value new_value; 00242 00243 for (p = attrs; *p != NULL; p += 2) 00244 if (!strcmp (attribute->name, p[0])) 00245 { 00246 val = p[1]; 00247 break; 00248 } 00249 00250 if (*p != NULL && val == NULL) 00251 { 00252 gdb_xml_debug (parser, _("Attribute \"%s\" missing a value"), 00253 attribute->name); 00254 continue; 00255 } 00256 00257 if (*p == NULL && !(attribute->flags & GDB_XML_AF_OPTIONAL)) 00258 { 00259 gdb_xml_error (parser, _("Required attribute \"%s\" of " 00260 "<%s> not specified"), 00261 attribute->name, element->name); 00262 continue; 00263 } 00264 00265 if (*p == NULL) 00266 continue; 00267 00268 gdb_xml_debug (parser, _("Parsing attribute %s=\"%s\""), 00269 attribute->name, val); 00270 00271 if (attribute->handler) 00272 parsed_value = attribute->handler (parser, attribute, val); 00273 else 00274 parsed_value = xstrdup (val); 00275 00276 new_value.name = attribute->name; 00277 new_value.value = parsed_value; 00278 VEC_safe_push (gdb_xml_value_s, attributes, &new_value); 00279 } 00280 00281 /* Check for unrecognized attributes. */ 00282 if (debug_xml) 00283 { 00284 const XML_Char **p; 00285 00286 for (p = attrs; *p != NULL; p += 2) 00287 { 00288 for (attribute = element->attributes; 00289 attribute != NULL && attribute->name != NULL; 00290 attribute++) 00291 if (strcmp (attribute->name, *p) == 0) 00292 break; 00293 00294 if (attribute == NULL || attribute->name == NULL) 00295 gdb_xml_debug (parser, _("Ignoring unknown attribute %s"), *p); 00296 } 00297 } 00298 00299 /* Call the element handler if there is one. */ 00300 if (element->start_handler) 00301 element->start_handler (parser, element, parser->user_data, attributes); 00302 00303 /* Fill in a new scope level. */ 00304 scope = VEC_last (scope_level_s, parser->scopes); 00305 scope->element = element; 00306 scope->elements = element->children; 00307 00308 do_cleanups (back_to); 00309 } 00310 00311 /* Wrapper for gdb_xml_start_element, to prevent throwing exceptions 00312 through expat. */ 00313 00314 static void 00315 gdb_xml_start_element_wrapper (void *data, const XML_Char *name, 00316 const XML_Char **attrs) 00317 { 00318 struct gdb_xml_parser *parser = data; 00319 volatile struct gdb_exception ex; 00320 00321 if (parser->error.reason < 0) 00322 return; 00323 00324 TRY_CATCH (ex, RETURN_MASK_ALL) 00325 { 00326 gdb_xml_start_element (data, name, attrs); 00327 } 00328 if (ex.reason < 0) 00329 { 00330 parser->error = ex; 00331 #ifdef HAVE_XML_STOPPARSER 00332 XML_StopParser (parser->expat_parser, XML_FALSE); 00333 #endif 00334 } 00335 } 00336 00337 /* Handle the end of an element. DATA is our local XML parser, and 00338 NAME is the current element. */ 00339 00340 static void 00341 gdb_xml_end_element (void *data, const XML_Char *name) 00342 { 00343 struct gdb_xml_parser *parser = data; 00344 struct scope_level *scope = VEC_last (scope_level_s, parser->scopes); 00345 const struct gdb_xml_element *element; 00346 unsigned int seen; 00347 00348 gdb_xml_debug (parser, _("Leaving element <%s>"), name); 00349 00350 for (element = scope->elements, seen = 1; 00351 element != NULL && element->name != NULL; 00352 element++, seen <<= 1) 00353 if ((scope->seen & seen) == 0 00354 && (element->flags & GDB_XML_EF_OPTIONAL) == 0) 00355 gdb_xml_error (parser, _("Required element <%s> is missing"), 00356 element->name); 00357 00358 /* Call the element processor. */ 00359 if (scope->element != NULL && scope->element->end_handler) 00360 { 00361 char *body; 00362 00363 if (scope->body == NULL) 00364 body = ""; 00365 else 00366 { 00367 int length; 00368 00369 length = obstack_object_size (scope->body); 00370 obstack_1grow (scope->body, '\0'); 00371 body = obstack_finish (scope->body); 00372 00373 /* Strip leading and trailing whitespace. */ 00374 while (length > 0 && ISSPACE (body[length-1])) 00375 body[--length] = '\0'; 00376 while (*body && ISSPACE (*body)) 00377 body++; 00378 } 00379 00380 scope->element->end_handler (parser, scope->element, parser->user_data, 00381 body); 00382 } 00383 else if (scope->element == NULL) 00384 XML_DefaultCurrent (parser->expat_parser); 00385 00386 /* Pop the scope level. */ 00387 if (scope->body) 00388 { 00389 obstack_free (scope->body, NULL); 00390 xfree (scope->body); 00391 } 00392 VEC_pop (scope_level_s, parser->scopes); 00393 } 00394 00395 /* Wrapper for gdb_xml_end_element, to prevent throwing exceptions 00396 through expat. */ 00397 00398 static void 00399 gdb_xml_end_element_wrapper (void *data, const XML_Char *name) 00400 { 00401 struct gdb_xml_parser *parser = data; 00402 volatile struct gdb_exception ex; 00403 00404 if (parser->error.reason < 0) 00405 return; 00406 00407 TRY_CATCH (ex, RETURN_MASK_ALL) 00408 { 00409 gdb_xml_end_element (data, name); 00410 } 00411 if (ex.reason < 0) 00412 { 00413 parser->error = ex; 00414 #ifdef HAVE_XML_STOPPARSER 00415 XML_StopParser (parser->expat_parser, XML_FALSE); 00416 #endif 00417 } 00418 } 00419 00420 /* Free a parser and all its associated state. */ 00421 00422 static void 00423 gdb_xml_cleanup (void *arg) 00424 { 00425 struct gdb_xml_parser *parser = arg; 00426 struct scope_level *scope; 00427 int ix; 00428 00429 XML_ParserFree (parser->expat_parser); 00430 00431 /* Clean up the scopes. */ 00432 for (ix = 0; VEC_iterate (scope_level_s, parser->scopes, ix, scope); ix++) 00433 if (scope->body) 00434 { 00435 obstack_free (scope->body, NULL); 00436 xfree (scope->body); 00437 } 00438 VEC_free (scope_level_s, parser->scopes); 00439 00440 xfree (parser); 00441 } 00442 00443 /* Initialize a parser and store it to *PARSER_RESULT. Register a 00444 cleanup to destroy the parser. */ 00445 00446 static struct cleanup * 00447 gdb_xml_create_parser_and_cleanup (const char *name, 00448 const struct gdb_xml_element *elements, 00449 void *user_data, 00450 struct gdb_xml_parser **parser_result) 00451 { 00452 struct gdb_xml_parser *parser; 00453 struct scope_level start_scope; 00454 struct cleanup *result; 00455 00456 /* Initialize the parser. */ 00457 parser = XZALLOC (struct gdb_xml_parser); 00458 parser->expat_parser = XML_ParserCreateNS (NULL, '!'); 00459 if (parser->expat_parser == NULL) 00460 { 00461 xfree (parser); 00462 malloc_failure (0); 00463 } 00464 00465 parser->name = name; 00466 00467 parser->user_data = user_data; 00468 XML_SetUserData (parser->expat_parser, parser); 00469 00470 /* Set the callbacks. */ 00471 XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper, 00472 gdb_xml_end_element_wrapper); 00473 XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text); 00474 00475 /* Initialize the outer scope. */ 00476 memset (&start_scope, 0, sizeof (start_scope)); 00477 start_scope.elements = elements; 00478 VEC_safe_push (scope_level_s, parser->scopes, &start_scope); 00479 00480 *parser_result = parser; 00481 return make_cleanup (gdb_xml_cleanup, parser); 00482 } 00483 00484 /* External entity handler. The only external entities we support 00485 are those compiled into GDB (we do not fetch entities from the 00486 target). */ 00487 00488 static int XMLCALL 00489 gdb_xml_fetch_external_entity (XML_Parser expat_parser, 00490 const XML_Char *context, 00491 const XML_Char *base, 00492 const XML_Char *systemId, 00493 const XML_Char *publicId) 00494 { 00495 struct gdb_xml_parser *parser = XML_GetUserData (expat_parser); 00496 XML_Parser entity_parser; 00497 const char *text; 00498 enum XML_Status status; 00499 00500 if (systemId == NULL) 00501 { 00502 text = fetch_xml_builtin (parser->dtd_name); 00503 if (text == NULL) 00504 internal_error (__FILE__, __LINE__, 00505 _("could not locate built-in DTD %s"), 00506 parser->dtd_name); 00507 } 00508 else 00509 { 00510 text = fetch_xml_builtin (systemId); 00511 if (text == NULL) 00512 return XML_STATUS_ERROR; 00513 } 00514 00515 entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL); 00516 00517 /* Don't use our handlers for the contents of the DTD. Just let expat 00518 process it. */ 00519 XML_SetElementHandler (entity_parser, NULL, NULL); 00520 XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL); 00521 XML_SetXmlDeclHandler (entity_parser, NULL); 00522 XML_SetDefaultHandler (entity_parser, NULL); 00523 XML_SetUserData (entity_parser, NULL); 00524 00525 status = XML_Parse (entity_parser, text, strlen (text), 1); 00526 00527 XML_ParserFree (entity_parser); 00528 return status; 00529 } 00530 00531 /* Associate DTD_NAME, which must be the name of a compiled-in DTD, 00532 with PARSER. */ 00533 00534 void 00535 gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name) 00536 { 00537 enum XML_Error err; 00538 00539 parser->dtd_name = dtd_name; 00540 00541 XML_SetParamEntityParsing (parser->expat_parser, 00542 XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); 00543 XML_SetExternalEntityRefHandler (parser->expat_parser, 00544 gdb_xml_fetch_external_entity); 00545 00546 /* Even if no DTD is provided, use the built-in DTD anyway. */ 00547 err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE); 00548 if (err != XML_ERROR_NONE) 00549 internal_error (__FILE__, __LINE__, 00550 _("XML_UseForeignDTD failed: %s"), 00551 XML_ErrorString (err)); 00552 } 00553 00554 /* Invoke PARSER on BUFFER. BUFFER is the data to parse, which 00555 should be NUL-terminated. 00556 00557 The return value is 0 for success or -1 for error. It may throw, 00558 but only if something unexpected goes wrong during parsing; parse 00559 errors will be caught, warned about, and reported as failure. */ 00560 00561 int 00562 gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer) 00563 { 00564 enum XML_Status status; 00565 const char *error_string; 00566 00567 gdb_xml_debug (parser, _("Starting:\n%s"), buffer); 00568 00569 status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1); 00570 00571 if (status == XML_STATUS_OK && parser->error.reason == 0) 00572 return 0; 00573 00574 if (parser->error.reason == RETURN_ERROR 00575 && parser->error.error == XML_PARSE_ERROR) 00576 { 00577 gdb_assert (parser->error.message != NULL); 00578 error_string = parser->error.message; 00579 } 00580 else if (status == XML_STATUS_ERROR) 00581 { 00582 enum XML_Error err = XML_GetErrorCode (parser->expat_parser); 00583 00584 error_string = XML_ErrorString (err); 00585 } 00586 else 00587 { 00588 gdb_assert (parser->error.reason < 0); 00589 throw_exception (parser->error); 00590 } 00591 00592 if (parser->last_line != 0) 00593 warning (_("while parsing %s (at line %d): %s"), parser->name, 00594 parser->last_line, error_string); 00595 else 00596 warning (_("while parsing %s: %s"), parser->name, error_string); 00597 00598 return -1; 00599 } 00600 00601 int 00602 gdb_xml_parse_quick (const char *name, const char *dtd_name, 00603 const struct gdb_xml_element *elements, 00604 const char *document, void *user_data) 00605 { 00606 struct gdb_xml_parser *parser; 00607 struct cleanup *back_to; 00608 int result; 00609 00610 back_to = gdb_xml_create_parser_and_cleanup (name, elements, 00611 user_data, &parser); 00612 if (dtd_name != NULL) 00613 gdb_xml_use_dtd (parser, dtd_name); 00614 result = gdb_xml_parse (parser, document); 00615 00616 do_cleanups (back_to); 00617 00618 return result; 00619 } 00620 00621 /* Parse a field VALSTR that we expect to contain an integer value. 00622 The integer is returned in *VALP. The string is parsed with an 00623 equivalent to strtoul. 00624 00625 Returns 0 for success, -1 for error. */ 00626 00627 static int 00628 xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp) 00629 { 00630 const char *endptr; 00631 ULONGEST result; 00632 00633 if (*valstr == '\0') 00634 return -1; 00635 00636 result = strtoulst (valstr, &endptr, 0); 00637 if (*endptr != '\0') 00638 return -1; 00639 00640 *valp = result; 00641 return 0; 00642 } 00643 00644 /* Parse an integer string into a ULONGEST and return it, or call 00645 gdb_xml_error if it could not be parsed. */ 00646 00647 ULONGEST 00648 gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value) 00649 { 00650 ULONGEST result; 00651 00652 if (xml_parse_unsigned_integer (value, &result) != 0) 00653 gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value); 00654 00655 return result; 00656 } 00657 00658 /* Parse an integer attribute into a ULONGEST. */ 00659 00660 void * 00661 gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser, 00662 const struct gdb_xml_attribute *attribute, 00663 const char *value) 00664 { 00665 ULONGEST result; 00666 void *ret; 00667 00668 if (xml_parse_unsigned_integer (value, &result) != 0) 00669 gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"), 00670 attribute->name, value); 00671 00672 ret = xmalloc (sizeof (result)); 00673 memcpy (ret, &result, sizeof (result)); 00674 return ret; 00675 } 00676 00677 /* A handler_data for yes/no boolean values. */ 00678 00679 const struct gdb_xml_enum gdb_xml_enums_boolean[] = { 00680 { "yes", 1 }, 00681 { "no", 0 }, 00682 { NULL, 0 } 00683 }; 00684 00685 /* Map NAME to VALUE. A struct gdb_xml_enum * should be saved as the 00686 value of handler_data when using gdb_xml_parse_attr_enum to parse a 00687 fixed list of possible strings. The list is terminated by an entry 00688 with NAME == NULL. */ 00689 00690 void * 00691 gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser, 00692 const struct gdb_xml_attribute *attribute, 00693 const char *value) 00694 { 00695 const struct gdb_xml_enum *enums = attribute->handler_data; 00696 void *ret; 00697 00698 for (enums = attribute->handler_data; enums->name != NULL; enums++) 00699 if (strcasecmp (enums->name, value) == 0) 00700 break; 00701 00702 if (enums->name == NULL) 00703 gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""), 00704 attribute->name, value); 00705 00706 ret = xmalloc (sizeof (enums->value)); 00707 memcpy (ret, &enums->value, sizeof (enums->value)); 00708 return ret; 00709 } 00710 00711 00712 /* XInclude processing. This is done as a separate step from actually 00713 parsing the document, so that we can produce a single combined XML 00714 document - e.g. to hand to a front end or to simplify comparing two 00715 documents. We make extensive use of XML_DefaultCurrent, to pass 00716 input text directly into the output without reformatting or 00717 requoting it. 00718 00719 We output the DOCTYPE declaration for the first document unchanged, 00720 if present, and discard DOCTYPEs from included documents. Only the 00721 one we pass through here is used when we feed the result back to 00722 expat. The XInclude standard explicitly does not discuss 00723 validation of the result; we choose to apply the same DTD applied 00724 to the outermost document. 00725 00726 We can not simply include the external DTD subset in the document 00727 as an internal subset, because <!IGNORE> and <!INCLUDE> are valid 00728 only in external subsets. But if we do not pass the DTD into the 00729 output at all, default values will not be filled in. 00730 00731 We don't pass through any <?xml> declaration because we generate 00732 UTF-8, not whatever the input encoding was. */ 00733 00734 struct xinclude_parsing_data 00735 { 00736 /* The obstack to build the output in. */ 00737 struct obstack obstack; 00738 00739 /* A count indicating whether we are in an element whose 00740 children should not be copied to the output, and if so, 00741 how deep we are nested. This is used for anything inside 00742 an xi:include, and for the DTD. */ 00743 int skip_depth; 00744 00745 /* The number of <xi:include> elements currently being processed, 00746 to detect loops. */ 00747 int include_depth; 00748 00749 /* A function to call to obtain additional features, and its 00750 baton. */ 00751 xml_fetch_another fetcher; 00752 void *fetcher_baton; 00753 }; 00754 00755 static void 00756 xinclude_start_include (struct gdb_xml_parser *parser, 00757 const struct gdb_xml_element *element, 00758 void *user_data, VEC(gdb_xml_value_s) *attributes) 00759 { 00760 struct xinclude_parsing_data *data = user_data; 00761 char *href = xml_find_attribute (attributes, "href")->value; 00762 struct cleanup *back_to; 00763 char *text, *output; 00764 00765 gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href); 00766 00767 if (data->include_depth > MAX_XINCLUDE_DEPTH) 00768 gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"), 00769 MAX_XINCLUDE_DEPTH); 00770 00771 text = data->fetcher (href, data->fetcher_baton); 00772 if (text == NULL) 00773 gdb_xml_error (parser, _("Could not load XML document \"%s\""), href); 00774 back_to = make_cleanup (xfree, text); 00775 00776 output = xml_process_xincludes (parser->name, text, data->fetcher, 00777 data->fetcher_baton, 00778 data->include_depth + 1); 00779 if (output == NULL) 00780 gdb_xml_error (parser, _("Parsing \"%s\" failed"), href); 00781 00782 obstack_grow (&data->obstack, output, strlen (output)); 00783 xfree (output); 00784 00785 do_cleanups (back_to); 00786 00787 data->skip_depth++; 00788 } 00789 00790 static void 00791 xinclude_end_include (struct gdb_xml_parser *parser, 00792 const struct gdb_xml_element *element, 00793 void *user_data, const char *body_text) 00794 { 00795 struct xinclude_parsing_data *data = user_data; 00796 00797 data->skip_depth--; 00798 } 00799 00800 static void XMLCALL 00801 xml_xinclude_default (void *data_, const XML_Char *s, int len) 00802 { 00803 struct gdb_xml_parser *parser = data_; 00804 struct xinclude_parsing_data *data = parser->user_data; 00805 00806 /* If we are inside of e.g. xi:include or the DTD, don't save this 00807 string. */ 00808 if (data->skip_depth) 00809 return; 00810 00811 /* Otherwise just add it to the end of the document we're building 00812 up. */ 00813 obstack_grow (&data->obstack, s, len); 00814 } 00815 00816 static void XMLCALL 00817 xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName, 00818 const XML_Char *sysid, const XML_Char *pubid, 00819 int has_internal_subset) 00820 { 00821 struct gdb_xml_parser *parser = data_; 00822 struct xinclude_parsing_data *data = parser->user_data; 00823 00824 /* Don't print out the doctype, or the contents of the DTD internal 00825 subset, if any. */ 00826 data->skip_depth++; 00827 } 00828 00829 static void XMLCALL 00830 xml_xinclude_end_doctype (void *data_) 00831 { 00832 struct gdb_xml_parser *parser = data_; 00833 struct xinclude_parsing_data *data = parser->user_data; 00834 00835 data->skip_depth--; 00836 } 00837 00838 static void XMLCALL 00839 xml_xinclude_xml_decl (void *data_, const XML_Char *version, 00840 const XML_Char *encoding, int standalone) 00841 { 00842 /* Do nothing - this function prevents the default handler from 00843 being called, thus suppressing the XML declaration from the 00844 output. */ 00845 } 00846 00847 static void 00848 xml_xinclude_cleanup (void *data_) 00849 { 00850 struct xinclude_parsing_data *data = data_; 00851 00852 obstack_free (&data->obstack, NULL); 00853 xfree (data); 00854 } 00855 00856 const struct gdb_xml_attribute xinclude_attributes[] = { 00857 { "href", GDB_XML_AF_NONE, NULL, NULL }, 00858 { NULL, GDB_XML_AF_NONE, NULL, NULL } 00859 }; 00860 00861 const struct gdb_xml_element xinclude_elements[] = { 00862 { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL, 00863 GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE, 00864 xinclude_start_include, xinclude_end_include }, 00865 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 00866 }; 00867 00868 /* The main entry point for <xi:include> processing. */ 00869 00870 char * 00871 xml_process_xincludes (const char *name, const char *text, 00872 xml_fetch_another fetcher, void *fetcher_baton, 00873 int depth) 00874 { 00875 struct gdb_xml_parser *parser; 00876 struct xinclude_parsing_data *data; 00877 struct cleanup *back_to; 00878 char *result = NULL; 00879 00880 data = XZALLOC (struct xinclude_parsing_data); 00881 obstack_init (&data->obstack); 00882 back_to = make_cleanup (xml_xinclude_cleanup, data); 00883 00884 gdb_xml_create_parser_and_cleanup (name, xinclude_elements, 00885 data, &parser); 00886 parser->is_xinclude = 1; 00887 00888 data->include_depth = depth; 00889 data->fetcher = fetcher; 00890 data->fetcher_baton = fetcher_baton; 00891 00892 XML_SetCharacterDataHandler (parser->expat_parser, NULL); 00893 XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default); 00894 00895 /* Always discard the XML version declarations; the only important 00896 thing this provides is encoding, and our result will have been 00897 converted to UTF-8. */ 00898 XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl); 00899 00900 if (depth > 0) 00901 /* Discard the doctype for included documents. */ 00902 XML_SetDoctypeDeclHandler (parser->expat_parser, 00903 xml_xinclude_start_doctype, 00904 xml_xinclude_end_doctype); 00905 00906 gdb_xml_use_dtd (parser, "xinclude.dtd"); 00907 00908 if (gdb_xml_parse (parser, text) == 0) 00909 { 00910 obstack_1grow (&data->obstack, '\0'); 00911 result = xstrdup (obstack_finish (&data->obstack)); 00912 00913 if (depth == 0) 00914 gdb_xml_debug (parser, _("XInclude processing succeeded.")); 00915 } 00916 else 00917 result = NULL; 00918 00919 do_cleanups (back_to); 00920 return result; 00921 } 00922 #endif /* HAVE_LIBEXPAT */ 00923 00924 00925 /* Return an XML document which was compiled into GDB, from 00926 the given FILENAME, or NULL if the file was not compiled in. */ 00927 00928 const char * 00929 fetch_xml_builtin (const char *filename) 00930 { 00931 const char *(*p)[2]; 00932 00933 for (p = xml_builtin; (*p)[0]; p++) 00934 if (strcmp ((*p)[0], filename) == 0) 00935 return (*p)[1]; 00936 00937 return NULL; 00938 } 00939 00940 /* A to_xfer_partial helper function which reads XML files which were 00941 compiled into GDB. The target may call this function from its own 00942 to_xfer_partial handler, after converting object and annex to the 00943 appropriate filename. */ 00944 00945 LONGEST 00946 xml_builtin_xfer_partial (const char *filename, 00947 gdb_byte *readbuf, const gdb_byte *writebuf, 00948 ULONGEST offset, LONGEST len) 00949 { 00950 const char *buf; 00951 LONGEST len_avail; 00952 00953 gdb_assert (readbuf != NULL && writebuf == NULL); 00954 gdb_assert (filename != NULL); 00955 00956 buf = fetch_xml_builtin (filename); 00957 if (buf == NULL) 00958 return -1; 00959 00960 len_avail = strlen (buf); 00961 if (offset >= len_avail) 00962 return 0; 00963 00964 if (len > len_avail - offset) 00965 len = len_avail - offset; 00966 memcpy (readbuf, buf + offset, len); 00967 return len; 00968 } 00969 00970 00971 static void 00972 show_debug_xml (struct ui_file *file, int from_tty, 00973 struct cmd_list_element *c, const char *value) 00974 { 00975 fprintf_filtered (file, _("XML debugging is %s.\n"), value); 00976 } 00977 00978 void 00979 obstack_xml_printf (struct obstack *obstack, const char *format, ...) 00980 { 00981 va_list ap; 00982 const char *f; 00983 const char *prev; 00984 int percent = 0; 00985 00986 va_start (ap, format); 00987 00988 prev = format; 00989 for (f = format; *f; f++) 00990 { 00991 if (percent) 00992 { 00993 switch (*f) 00994 { 00995 case 's': 00996 { 00997 char *p; 00998 char *a = va_arg (ap, char *); 00999 01000 obstack_grow (obstack, prev, f - prev - 1); 01001 p = xml_escape_text (a); 01002 obstack_grow_str (obstack, p); 01003 xfree (p); 01004 prev = f + 1; 01005 } 01006 break; 01007 } 01008 percent = 0; 01009 } 01010 else if (*f == '%') 01011 percent = 1; 01012 } 01013 01014 obstack_grow_str (obstack, prev); 01015 va_end (ap); 01016 } 01017 01018 char * 01019 xml_fetch_content_from_file (const char *filename, void *baton) 01020 { 01021 const char *dirname = baton; 01022 FILE *file; 01023 struct cleanup *back_to; 01024 char *text; 01025 size_t len, offset; 01026 01027 if (dirname && *dirname) 01028 { 01029 char *fullname = concat (dirname, "/", filename, (char *) NULL); 01030 01031 if (fullname == NULL) 01032 malloc_failure (0); 01033 file = gdb_fopen_cloexec (fullname, FOPEN_RT); 01034 xfree (fullname); 01035 } 01036 else 01037 file = gdb_fopen_cloexec (filename, FOPEN_RT); 01038 01039 if (file == NULL) 01040 return NULL; 01041 01042 back_to = make_cleanup_fclose (file); 01043 01044 /* Read in the whole file, one chunk at a time. */ 01045 len = 4096; 01046 offset = 0; 01047 text = xmalloc (len); 01048 make_cleanup (free_current_contents, &text); 01049 while (1) 01050 { 01051 size_t bytes_read; 01052 01053 /* Continue reading where the last read left off. Leave at least 01054 one byte so that we can NUL-terminate the result. */ 01055 bytes_read = fread (text + offset, 1, len - offset - 1, file); 01056 if (ferror (file)) 01057 { 01058 warning (_("Read error from \"%s\""), filename); 01059 do_cleanups (back_to); 01060 return NULL; 01061 } 01062 01063 offset += bytes_read; 01064 01065 if (feof (file)) 01066 break; 01067 01068 len = len * 2; 01069 text = xrealloc (text, len); 01070 } 01071 01072 fclose (file); 01073 discard_cleanups (back_to); 01074 01075 text[offset] = '\0'; 01076 return text; 01077 } 01078 01079 void _initialize_xml_support (void); 01080 01081 void 01082 _initialize_xml_support (void) 01083 { 01084 add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml, 01085 _("Set XML parser debugging."), 01086 _("Show XML parser debugging."), 01087 _("When set, debugging messages for XML parsers " 01088 "are displayed."), 01089 NULL, show_debug_xml, 01090 &setdebuglist, &showdebuglist); 01091 }