GDB (API)
/home/stan/gdb/src/gdb/xml-support.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines