gdb/xml-support.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "gdbcmd.h"
- #include "xml-support.h"
- #include "filestuff.h"
- #include "safe-ctype.h"
- static int debug_xml;
- #ifdef HAVE_LIBEXPAT
- #include "gdb_expat.h"
- #define MAX_XINCLUDE_DEPTH 30
- struct scope_level
- {
-
- const struct gdb_xml_element *elements;
-
- const struct gdb_xml_element *element;
-
- unsigned int seen;
-
- struct obstack *body;
- };
- typedef struct scope_level scope_level_s;
- DEF_VEC_O(scope_level_s);
- struct gdb_xml_parser
- {
- XML_Parser expat_parser;
- const char *name;
- void *user_data;
- VEC(scope_level_s) *scopes;
- struct gdb_exception error;
- int last_line;
- const char *dtd_name;
- int is_xinclude;
- };
- static void
- gdb_xml_body_text (void *data, const XML_Char *text, int length)
- {
- struct gdb_xml_parser *parser = data;
- struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
- if (parser->error.reason < 0)
- return;
- if (scope->body == NULL)
- {
- scope->body = XCNEW (struct obstack);
- obstack_init (scope->body);
- }
- obstack_grow (scope->body, text, length);
- }
- void
- gdb_xml_debug (struct gdb_xml_parser *parser, const char *format, ...)
- {
- int line = XML_GetCurrentLineNumber (parser->expat_parser);
- va_list ap;
- char *message;
- if (!debug_xml)
- return;
- va_start (ap, format);
- message = xstrvprintf (format, ap);
- if (line)
- fprintf_unfiltered (gdb_stderr, "%s (line %d): %s\n",
- parser->name, line, message);
- else
- fprintf_unfiltered (gdb_stderr, "%s: %s\n",
- parser->name, message);
- xfree (message);
- }
- void
- gdb_xml_error (struct gdb_xml_parser *parser, const char *format, ...)
- {
- int line = XML_GetCurrentLineNumber (parser->expat_parser);
- va_list ap;
- parser->last_line = line;
- va_start (ap, format);
- throw_verror (XML_PARSE_ERROR, format, ap);
- }
- struct gdb_xml_value *
- xml_find_attribute (VEC(gdb_xml_value_s) *attributes, const char *name)
- {
- struct gdb_xml_value *value;
- int ix;
- for (ix = 0; VEC_iterate (gdb_xml_value_s, attributes, ix, value); ix++)
- if (strcmp (value->name, name) == 0)
- return value;
- return NULL;
- }
- static void
- gdb_xml_values_cleanup (void *data)
- {
- VEC(gdb_xml_value_s) **values = data;
- struct gdb_xml_value *value;
- int ix;
- for (ix = 0; VEC_iterate (gdb_xml_value_s, *values, ix, value); ix++)
- xfree (value->value);
- VEC_free (gdb_xml_value_s, *values);
- }
- static void
- gdb_xml_start_element (void *data, const XML_Char *name,
- const XML_Char **attrs)
- {
- struct gdb_xml_parser *parser = data;
- struct scope_level *scope;
- struct scope_level new_scope;
- const struct gdb_xml_element *element;
- const struct gdb_xml_attribute *attribute;
- VEC(gdb_xml_value_s) *attributes = NULL;
- unsigned int seen;
- struct cleanup *back_to;
-
- VEC_reserve (scope_level_s, parser->scopes, 1);
- scope = VEC_last (scope_level_s, parser->scopes);
- memset (&new_scope, 0, sizeof (new_scope));
- VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
- gdb_xml_debug (parser, _("Entering element <%s>"), name);
-
- seen = 1;
- for (element = scope->elements; element && element->name;
- element++, seen <<= 1)
- if (strcmp (element->name, name) == 0)
- break;
- if (element == NULL || element->name == NULL)
- {
-
- if (parser->is_xinclude)
- {
- struct scope_level *unknown_scope;
- XML_DefaultCurrent (parser->expat_parser);
- unknown_scope = VEC_last (scope_level_s, parser->scopes);
- unknown_scope->elements = scope->elements;
- return;
- }
- gdb_xml_debug (parser, _("Element <%s> unknown"), name);
- return;
- }
- if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope->seen))
- gdb_xml_error (parser, _("Element <%s> only expected once"), name);
- scope->seen |= seen;
- back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
- for (attribute = element->attributes;
- attribute != NULL && attribute->name != NULL;
- attribute++)
- {
- const char *val = NULL;
- const XML_Char **p;
- void *parsed_value;
- struct gdb_xml_value new_value;
- for (p = attrs; *p != NULL; p += 2)
- if (!strcmp (attribute->name, p[0]))
- {
- val = p[1];
- break;
- }
- if (*p != NULL && val == NULL)
- {
- gdb_xml_debug (parser, _("Attribute \"%s\" missing a value"),
- attribute->name);
- continue;
- }
- if (*p == NULL && !(attribute->flags & GDB_XML_AF_OPTIONAL))
- {
- gdb_xml_error (parser, _("Required attribute \"%s\" of "
- "<%s> not specified"),
- attribute->name, element->name);
- continue;
- }
- if (*p == NULL)
- continue;
- gdb_xml_debug (parser, _("Parsing attribute %s=\"%s\""),
- attribute->name, val);
- if (attribute->handler)
- parsed_value = attribute->handler (parser, attribute, val);
- else
- parsed_value = xstrdup (val);
- new_value.name = attribute->name;
- new_value.value = parsed_value;
- VEC_safe_push (gdb_xml_value_s, attributes, &new_value);
- }
-
- if (debug_xml)
- {
- const XML_Char **p;
- for (p = attrs; *p != NULL; p += 2)
- {
- for (attribute = element->attributes;
- attribute != NULL && attribute->name != NULL;
- attribute++)
- if (strcmp (attribute->name, *p) == 0)
- break;
- if (attribute == NULL || attribute->name == NULL)
- gdb_xml_debug (parser, _("Ignoring unknown attribute %s"), *p);
- }
- }
-
- if (element->start_handler)
- element->start_handler (parser, element, parser->user_data, attributes);
-
- scope = VEC_last (scope_level_s, parser->scopes);
- scope->element = element;
- scope->elements = element->children;
- do_cleanups (back_to);
- }
- static void
- gdb_xml_start_element_wrapper (void *data, const XML_Char *name,
- const XML_Char **attrs)
- {
- struct gdb_xml_parser *parser = data;
- volatile struct gdb_exception ex;
- if (parser->error.reason < 0)
- return;
- TRY_CATCH (ex, RETURN_MASK_ALL)
- {
- gdb_xml_start_element (data, name, attrs);
- }
- if (ex.reason < 0)
- {
- parser->error = ex;
- #ifdef HAVE_XML_STOPPARSER
- XML_StopParser (parser->expat_parser, XML_FALSE);
- #endif
- }
- }
- static void
- gdb_xml_end_element (void *data, const XML_Char *name)
- {
- struct gdb_xml_parser *parser = data;
- struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
- const struct gdb_xml_element *element;
- unsigned int seen;
- gdb_xml_debug (parser, _("Leaving element <%s>"), name);
- for (element = scope->elements, seen = 1;
- element != NULL && element->name != NULL;
- element++, seen <<= 1)
- if ((scope->seen & seen) == 0
- && (element->flags & GDB_XML_EF_OPTIONAL) == 0)
- gdb_xml_error (parser, _("Required element <%s> is missing"),
- element->name);
-
- if (scope->element != NULL && scope->element->end_handler)
- {
- char *body;
- if (scope->body == NULL)
- body = "";
- else
- {
- int length;
- length = obstack_object_size (scope->body);
- obstack_1grow (scope->body, '\0');
- body = obstack_finish (scope->body);
-
- while (length > 0 && ISSPACE (body[length-1]))
- body[--length] = '\0';
- while (*body && ISSPACE (*body))
- body++;
- }
- scope->element->end_handler (parser, scope->element, parser->user_data,
- body);
- }
- else if (scope->element == NULL)
- XML_DefaultCurrent (parser->expat_parser);
-
- if (scope->body)
- {
- obstack_free (scope->body, NULL);
- xfree (scope->body);
- }
- VEC_pop (scope_level_s, parser->scopes);
- }
- static void
- gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
- {
- struct gdb_xml_parser *parser = data;
- volatile struct gdb_exception ex;
- if (parser->error.reason < 0)
- return;
- TRY_CATCH (ex, RETURN_MASK_ALL)
- {
- gdb_xml_end_element (data, name);
- }
- if (ex.reason < 0)
- {
- parser->error = ex;
- #ifdef HAVE_XML_STOPPARSER
- XML_StopParser (parser->expat_parser, XML_FALSE);
- #endif
- }
- }
- static void
- gdb_xml_cleanup (void *arg)
- {
- struct gdb_xml_parser *parser = arg;
- struct scope_level *scope;
- int ix;
- XML_ParserFree (parser->expat_parser);
-
- for (ix = 0; VEC_iterate (scope_level_s, parser->scopes, ix, scope); ix++)
- if (scope->body)
- {
- obstack_free (scope->body, NULL);
- xfree (scope->body);
- }
- VEC_free (scope_level_s, parser->scopes);
- xfree (parser);
- }
- static struct cleanup *
- gdb_xml_create_parser_and_cleanup (const char *name,
- const struct gdb_xml_element *elements,
- void *user_data,
- struct gdb_xml_parser **parser_result)
- {
- struct gdb_xml_parser *parser;
- struct scope_level start_scope;
- struct cleanup *result;
-
- parser = XCNEW (struct gdb_xml_parser);
- parser->expat_parser = XML_ParserCreateNS (NULL, '!');
- if (parser->expat_parser == NULL)
- {
- xfree (parser);
- malloc_failure (0);
- }
- parser->name = name;
- parser->user_data = user_data;
- XML_SetUserData (parser->expat_parser, parser);
-
- XML_SetElementHandler (parser->expat_parser, gdb_xml_start_element_wrapper,
- gdb_xml_end_element_wrapper);
- XML_SetCharacterDataHandler (parser->expat_parser, gdb_xml_body_text);
-
- memset (&start_scope, 0, sizeof (start_scope));
- start_scope.elements = elements;
- VEC_safe_push (scope_level_s, parser->scopes, &start_scope);
- *parser_result = parser;
- return make_cleanup (gdb_xml_cleanup, parser);
- }
- static int XMLCALL
- gdb_xml_fetch_external_entity (XML_Parser expat_parser,
- const XML_Char *context,
- const XML_Char *base,
- const XML_Char *systemId,
- const XML_Char *publicId)
- {
- struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
- XML_Parser entity_parser;
- const char *text;
- enum XML_Status status;
- if (systemId == NULL)
- {
- text = fetch_xml_builtin (parser->dtd_name);
- if (text == NULL)
- internal_error (__FILE__, __LINE__,
- _("could not locate built-in DTD %s"),
- parser->dtd_name);
- }
- else
- {
- text = fetch_xml_builtin (systemId);
- if (text == NULL)
- return XML_STATUS_ERROR;
- }
- entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
-
- XML_SetElementHandler (entity_parser, NULL, NULL);
- XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
- XML_SetXmlDeclHandler (entity_parser, NULL);
- XML_SetDefaultHandler (entity_parser, NULL);
- XML_SetUserData (entity_parser, NULL);
- status = XML_Parse (entity_parser, text, strlen (text), 1);
- XML_ParserFree (entity_parser);
- return status;
- }
- void
- gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
- {
- enum XML_Error err;
- parser->dtd_name = dtd_name;
- XML_SetParamEntityParsing (parser->expat_parser,
- XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
- XML_SetExternalEntityRefHandler (parser->expat_parser,
- gdb_xml_fetch_external_entity);
-
- err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
- if (err != XML_ERROR_NONE)
- internal_error (__FILE__, __LINE__,
- _("XML_UseForeignDTD failed: %s"),
- XML_ErrorString (err));
- }
- int
- gdb_xml_parse (struct gdb_xml_parser *parser, const char *buffer)
- {
- enum XML_Status status;
- const char *error_string;
- gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
- status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
- if (status == XML_STATUS_OK && parser->error.reason == 0)
- return 0;
- if (parser->error.reason == RETURN_ERROR
- && parser->error.error == XML_PARSE_ERROR)
- {
- gdb_assert (parser->error.message != NULL);
- error_string = parser->error.message;
- }
- else if (status == XML_STATUS_ERROR)
- {
- enum XML_Error err = XML_GetErrorCode (parser->expat_parser);
- error_string = XML_ErrorString (err);
- }
- else
- {
- gdb_assert (parser->error.reason < 0);
- throw_exception (parser->error);
- }
- if (parser->last_line != 0)
- warning (_("while parsing %s (at line %d): %s"), parser->name,
- parser->last_line, error_string);
- else
- warning (_("while parsing %s: %s"), parser->name, error_string);
- return -1;
- }
- int
- gdb_xml_parse_quick (const char *name, const char *dtd_name,
- const struct gdb_xml_element *elements,
- const char *document, void *user_data)
- {
- struct gdb_xml_parser *parser;
- struct cleanup *back_to;
- int result;
- back_to = gdb_xml_create_parser_and_cleanup (name, elements,
- user_data, &parser);
- if (dtd_name != NULL)
- gdb_xml_use_dtd (parser, dtd_name);
- result = gdb_xml_parse (parser, document);
- do_cleanups (back_to);
- return result;
- }
- static int
- xml_parse_unsigned_integer (const char *valstr, ULONGEST *valp)
- {
- const char *endptr;
- ULONGEST result;
- if (*valstr == '\0')
- return -1;
- result = strtoulst (valstr, &endptr, 0);
- if (*endptr != '\0')
- return -1;
- *valp = result;
- return 0;
- }
- ULONGEST
- gdb_xml_parse_ulongest (struct gdb_xml_parser *parser, const char *value)
- {
- ULONGEST result;
- if (xml_parse_unsigned_integer (value, &result) != 0)
- gdb_xml_error (parser, _("Can't convert \"%s\" to an integer"), value);
- return result;
- }
- void *
- gdb_xml_parse_attr_ulongest (struct gdb_xml_parser *parser,
- const struct gdb_xml_attribute *attribute,
- const char *value)
- {
- ULONGEST result;
- void *ret;
- if (xml_parse_unsigned_integer (value, &result) != 0)
- gdb_xml_error (parser, _("Can't convert %s=\"%s\" to an integer"),
- attribute->name, value);
- ret = xmalloc (sizeof (result));
- memcpy (ret, &result, sizeof (result));
- return ret;
- }
- const struct gdb_xml_enum gdb_xml_enums_boolean[] = {
- { "yes", 1 },
- { "no", 0 },
- { NULL, 0 }
- };
- void *
- gdb_xml_parse_attr_enum (struct gdb_xml_parser *parser,
- const struct gdb_xml_attribute *attribute,
- const char *value)
- {
- const struct gdb_xml_enum *enums = attribute->handler_data;
- void *ret;
- for (enums = attribute->handler_data; enums->name != NULL; enums++)
- if (strcasecmp (enums->name, value) == 0)
- break;
- if (enums->name == NULL)
- gdb_xml_error (parser, _("Unknown attribute value %s=\"%s\""),
- attribute->name, value);
- ret = xmalloc (sizeof (enums->value));
- memcpy (ret, &enums->value, sizeof (enums->value));
- return ret;
- }
- struct xinclude_parsing_data
- {
-
- struct obstack obstack;
-
- int skip_depth;
-
- int include_depth;
-
- xml_fetch_another fetcher;
- void *fetcher_baton;
- };
- static void
- xinclude_start_include (struct gdb_xml_parser *parser,
- const struct gdb_xml_element *element,
- void *user_data, VEC(gdb_xml_value_s) *attributes)
- {
- struct xinclude_parsing_data *data = user_data;
- char *href = xml_find_attribute (attributes, "href")->value;
- struct cleanup *back_to;
- char *text, *output;
- gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
- if (data->include_depth > MAX_XINCLUDE_DEPTH)
- gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
- MAX_XINCLUDE_DEPTH);
- text = data->fetcher (href, data->fetcher_baton);
- if (text == NULL)
- gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
- back_to = make_cleanup (xfree, text);
- output = xml_process_xincludes (parser->name, text, data->fetcher,
- data->fetcher_baton,
- data->include_depth + 1);
- if (output == NULL)
- gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
- obstack_grow (&data->obstack, output, strlen (output));
- xfree (output);
- do_cleanups (back_to);
- data->skip_depth++;
- }
- static void
- xinclude_end_include (struct gdb_xml_parser *parser,
- const struct gdb_xml_element *element,
- void *user_data, const char *body_text)
- {
- struct xinclude_parsing_data *data = user_data;
- data->skip_depth--;
- }
- static void XMLCALL
- xml_xinclude_default (void *data_, const XML_Char *s, int len)
- {
- struct gdb_xml_parser *parser = data_;
- struct xinclude_parsing_data *data = parser->user_data;
-
- if (data->skip_depth)
- return;
-
- obstack_grow (&data->obstack, s, len);
- }
- static void XMLCALL
- xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
- const XML_Char *sysid, const XML_Char *pubid,
- int has_internal_subset)
- {
- struct gdb_xml_parser *parser = data_;
- struct xinclude_parsing_data *data = parser->user_data;
-
- data->skip_depth++;
- }
- static void XMLCALL
- xml_xinclude_end_doctype (void *data_)
- {
- struct gdb_xml_parser *parser = data_;
- struct xinclude_parsing_data *data = parser->user_data;
- data->skip_depth--;
- }
- static void XMLCALL
- xml_xinclude_xml_decl (void *data_, const XML_Char *version,
- const XML_Char *encoding, int standalone)
- {
-
- }
- static void
- xml_xinclude_cleanup (void *data_)
- {
- struct xinclude_parsing_data *data = data_;
- obstack_free (&data->obstack, NULL);
- xfree (data);
- }
- const struct gdb_xml_attribute xinclude_attributes[] = {
- { "href", GDB_XML_AF_NONE, NULL, NULL },
- { NULL, GDB_XML_AF_NONE, NULL, NULL }
- };
- const struct gdb_xml_element xinclude_elements[] = {
- { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
- GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
- xinclude_start_include, xinclude_end_include },
- { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
- };
- char *
- xml_process_xincludes (const char *name, const char *text,
- xml_fetch_another fetcher, void *fetcher_baton,
- int depth)
- {
- struct gdb_xml_parser *parser;
- struct xinclude_parsing_data *data;
- struct cleanup *back_to;
- char *result = NULL;
- data = XCNEW (struct xinclude_parsing_data);
- obstack_init (&data->obstack);
- back_to = make_cleanup (xml_xinclude_cleanup, data);
- gdb_xml_create_parser_and_cleanup (name, xinclude_elements,
- data, &parser);
- parser->is_xinclude = 1;
- data->include_depth = depth;
- data->fetcher = fetcher;
- data->fetcher_baton = fetcher_baton;
- XML_SetCharacterDataHandler (parser->expat_parser, NULL);
- XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
-
- XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
- if (depth > 0)
-
- XML_SetDoctypeDeclHandler (parser->expat_parser,
- xml_xinclude_start_doctype,
- xml_xinclude_end_doctype);
- gdb_xml_use_dtd (parser, "xinclude.dtd");
- if (gdb_xml_parse (parser, text) == 0)
- {
- obstack_1grow (&data->obstack, '\0');
- result = xstrdup (obstack_finish (&data->obstack));
- if (depth == 0)
- gdb_xml_debug (parser, _("XInclude processing succeeded."));
- }
- else
- result = NULL;
- do_cleanups (back_to);
- return result;
- }
- #endif
- const char *
- fetch_xml_builtin (const char *filename)
- {
- const char *(*p)[2];
- for (p = xml_builtin; (*p)[0]; p++)
- if (strcmp ((*p)[0], filename) == 0)
- return (*p)[1];
- return NULL;
- }
- LONGEST
- xml_builtin_xfer_partial (const char *filename,
- gdb_byte *readbuf, const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len)
- {
- const char *buf;
- LONGEST len_avail;
- gdb_assert (readbuf != NULL && writebuf == NULL);
- gdb_assert (filename != NULL);
- buf = fetch_xml_builtin (filename);
- if (buf == NULL)
- return -1;
- len_avail = strlen (buf);
- if (offset >= len_avail)
- return 0;
- if (len > len_avail - offset)
- len = len_avail - offset;
- memcpy (readbuf, buf + offset, len);
- return len;
- }
- static void
- show_debug_xml (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- fprintf_filtered (file, _("XML debugging is %s.\n"), value);
- }
- void
- obstack_xml_printf (struct obstack *obstack, const char *format, ...)
- {
- va_list ap;
- const char *f;
- const char *prev;
- int percent = 0;
- va_start (ap, format);
- prev = format;
- for (f = format; *f; f++)
- {
- if (percent)
- {
- switch (*f)
- {
- case 's':
- {
- char *p;
- char *a = va_arg (ap, char *);
- obstack_grow (obstack, prev, f - prev - 1);
- p = xml_escape_text (a);
- obstack_grow_str (obstack, p);
- xfree (p);
- prev = f + 1;
- }
- break;
- }
- percent = 0;
- }
- else if (*f == '%')
- percent = 1;
- }
- obstack_grow_str (obstack, prev);
- va_end (ap);
- }
- char *
- xml_fetch_content_from_file (const char *filename, void *baton)
- {
- const char *dirname = baton;
- FILE *file;
- struct cleanup *back_to;
- char *text;
- size_t len, offset;
- if (dirname && *dirname)
- {
- char *fullname = concat (dirname, "/", filename, (char *) NULL);
- if (fullname == NULL)
- malloc_failure (0);
- file = gdb_fopen_cloexec (fullname, FOPEN_RT);
- xfree (fullname);
- }
- else
- file = gdb_fopen_cloexec (filename, FOPEN_RT);
- if (file == NULL)
- return NULL;
- back_to = make_cleanup_fclose (file);
-
- len = 4096;
- offset = 0;
- text = xmalloc (len);
- make_cleanup (free_current_contents, &text);
- while (1)
- {
- size_t bytes_read;
-
- bytes_read = fread (text + offset, 1, len - offset - 1, file);
- if (ferror (file))
- {
- warning (_("Read error from \"%s\""), filename);
- do_cleanups (back_to);
- return NULL;
- }
- offset += bytes_read;
- if (feof (file))
- break;
- len = len * 2;
- text = xrealloc (text, len);
- }
- fclose (file);
- discard_cleanups (back_to);
- text[offset] = '\0';
- return text;
- }
- void _initialize_xml_support (void);
- void
- _initialize_xml_support (void)
- {
- add_setshow_boolean_cmd ("xml", class_maintenance, &debug_xml,
- _("Set XML parser debugging."),
- _("Show XML parser debugging."),
- _("When set, debugging messages for XML parsers "
- "are displayed."),
- NULL, show_debug_xml,
- &setdebuglist, &showdebuglist);
- }