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