/* Helper routines for parsing XML using Expat.
- Copyright (C) 2006-2017 Free Software Foundation, Inc.
+ Copyright (C) 2006-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "gdbcmd.h"
#include "xml-support.h"
-#include "filestuff.h"
+#include "common/filestuff.h"
#include "safe-ctype.h"
#include <vector>
#include <string>
{ m_is_xinclude = is_xinclude; }
/* A thrown error, if any. */
- void set_error (gdb_exception error)
+ void set_error (gdb_exception &&error)
{
- m_error = error;
+ m_error = std::move (error);
#ifdef HAVE_XML_STOPPARSER
XML_StopParser (m_expat_parser, XML_FALSE);
#endif
gdb_xml_parser::vdebug (const char *format, va_list ap)
{
int line = XML_GetCurrentLineNumber (m_expat_parser);
- char *message;
- message = xstrvprintf (format, ap);
+ std::string message = string_vprintf (format, ap);
if (line)
fprintf_unfiltered (gdb_stderr, "%s (line %d): %s\n",
- m_name, line, message);
+ m_name, line, message.c_str ());
else
fprintf_unfiltered (gdb_stderr, "%s: %s\n",
- m_name, message);
- xfree (message);
+ m_name, message.c_str ());
}
void
ATTRIBUTES. Returns NULL if not found. */
struct gdb_xml_value *
-xml_find_attribute (VEC(gdb_xml_value_s) *attributes, const char *name)
+xml_find_attribute (std::vector<gdb_xml_value> &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;
+ for (gdb_xml_value &value : attributes)
+ if (strcmp (value.name, name) == 0)
+ return &value;
return NULL;
}
-/* Clean up a vector of parsed attribute values. */
-
-static void
-gdb_xml_values_cleanup (void *data)
-{
- VEC(gdb_xml_value_s) **values = (VEC(gdb_xml_value_s) **) 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);
-}
-
/* Handle the start of an element. NAME is the element, and ATTRS are
the names and values of this element's attributes. */
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;
/* Push an error scope. If we return or throw an exception before
filling this in, it will tell us to ignore children of this
scope.seen |= seen;
- back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
+ std::vector<gdb_xml_value> attributes;
for (attribute = element->attributes;
attribute != NULL && attribute->name != NULL;
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]))
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);
+ attributes.emplace_back (attribute->name, parsed_value);
}
/* Check for unrecognized attributes. */
scope_level &new_scope = m_scopes.back ();
new_scope.element = element;
new_scope.elements = element->children;
-
- do_cleanups (back_to);
}
/* Wrapper for gdb_xml_start_element, to prevent throwing exceptions
{
struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
- TRY
+ try
{
parser->start_element (name, attrs);
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (gdb_exception &ex)
{
- parser->set_error (ex);
+ parser->set_error (std::move (ex));
}
- END_CATCH
}
/* Handle the end of an element. NAME is the current element. */
{
struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
- TRY
+ try
{
parser->end_element (name);
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (gdb_exception &ex)
{
- parser->set_error (ex);
+ parser->set_error (std::move (ex));
}
- END_CATCH
}
/* Free a parser and all its associated state. */
void *user_data)
: m_name (name),
m_user_data (user_data),
- m_error (exception_none),
m_last_line (0),
m_dtd_name (NULL),
m_is_xinclude (false)
&& m_error.error == XML_PARSE_ERROR)
{
gdb_assert (m_error.message != NULL);
- error_string = m_error.message;
+ error_string = m_error.what ();
}
else if (status == XML_STATUS_ERROR)
{
else
{
gdb_assert (m_error.reason < 0);
- throw_exception (m_error);
+ throw_exception (std::move (m_error));
}
if (m_last_line != 0)
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)
+ void *user_data,
+ std::vector<gdb_xml_value> &attributes)
{
struct xinclude_parsing_data *data
= (struct xinclude_parsing_data *) user_data;
- char *href = (char *) xml_find_attribute (attributes, "href")->value;
- struct cleanup *back_to;
- char *text, *output;
+ char *href = (char *) xml_find_attribute (attributes, "href")->value.get ();
gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
MAX_XINCLUDE_DEPTH);
- text = data->fetcher (href, data->fetcher_baton);
- if (text == NULL)
+ gdb::optional<gdb::char_vector> text
+ = data->fetcher (href, data->fetcher_baton);
+ if (!text)
gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
- back_to = make_cleanup (xfree, text);
if (!xml_process_xincludes (data->output, parser->name (),
- text, data->fetcher,
+ text->data (), data->fetcher,
data->fetcher_baton,
data->include_depth + 1))
gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
- do_cleanups (back_to);
-
data->skip_depth++;
}
fprintf_filtered (file, _("XML debugging is %s.\n"), value);
}
-char *
+gdb::optional<gdb::char_vector>
xml_fetch_content_from_file (const char *filename, void *baton)
{
const char *dirname = (const char *) baton;
gdb_file_up file;
- struct cleanup *back_to;
- char *text;
- size_t len, offset;
if (dirname && *dirname)
{
file = gdb_fopen_cloexec (filename, FOPEN_RT);
if (file == NULL)
- return NULL;
-
- /* Read in the whole file, one chunk at a time. */
- len = 4096;
- offset = 0;
- text = (char *) xmalloc (len);
- back_to = make_cleanup (free_current_contents, &text);
- while (1)
- {
- size_t bytes_read;
+ return {};
- /* Continue reading where the last read left off. Leave at least
- one byte so that we can NUL-terminate the result. */
- bytes_read = fread (text + offset, 1, len - offset - 1, file.get ());
- if (ferror (file.get ()))
- {
- warning (_("Read error from \"%s\""), filename);
- do_cleanups (back_to);
- return NULL;
- }
+ /* Read in the whole file. */
- offset += bytes_read;
+ size_t len;
- if (feof (file.get ()))
- break;
+ if (fseek (file.get (), 0, SEEK_END) == -1)
+ perror_with_name (_("seek to end of file"));
+ len = ftell (file.get ());
+ rewind (file.get ());
- len = len * 2;
- text = (char *) xrealloc (text, len);
- }
+ gdb::char_vector text (len + 1);
- discard_cleanups (back_to);
+ if (fread (text.data (), 1, len, file.get ()) != len
+ || ferror (file.get ()))
+ {
+ warning (_("Read error from \"%s\""), filename);
+ return {};
+ }
- text[offset] = '\0';
+ text.back () = '\0';
return text;
}