xml-support.c: Use std::vector
authorPedro Alves <palves@redhat.com>
Tue, 18 Apr 2017 20:39:24 +0000 (21:39 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 18 Apr 2017 22:48:15 +0000 (23:48 +0100)
scope_level::scope_level needed both a move ctor and a dtor explicitly
coded, but those will be eliminated in a following patch.

gdb/ChangeLog:
2017-04-18  Pedro Alves  <palves@redhat.com>

* xml-support.c: Include <vector>.
(scope_level::scope_level(const gdb_xml_element *))
(scope_level::scope_level(scope_level&&)): New.
(scope_level::~scope_level): New.
(scope_level_s): Delete.
(gdb_xml_parser::scopes): Now a std::vector.
(gdb_xml_body_text, gdb_xml_start_element, gdb_xml_end_element):
Use std::vector.
(gdb_xml_parser::~gdb_xml_parser): Remove now unnecessary
scope cleanup code.
(gdb_xml_parser::gdb_xml_parser): Remove explicit initialization
of the scopes member.  Use std::vector::emplace_back.

gdb/ChangeLog
gdb/xml-support.c

index e33fc0eeff04be74a8216c9d955ee7d2674775af..85ab1aef53e2ae94467ad489739cd69080f5388f 100644 (file)
@@ -1,3 +1,18 @@
+2017-04-18  Pedro Alves  <palves@redhat.com>
+
+       * xml-support.c: Include <vector>.
+       (scope_level::scope_level(const gdb_xml_element *))
+       (scope_level::scope_level(scope_level&&)): New.
+       (scope_level::~scope_level): New.
+       (scope_level_s): Delete.
+       (gdb_xml_parser::scopes): Now a std::vector.
+       (gdb_xml_body_text, gdb_xml_start_element, gdb_xml_end_element):
+       Use std::vector.
+       (gdb_xml_parser::~gdb_xml_parser): Remove now unnecessary
+       scope cleanup code.
+       (gdb_xml_parser::gdb_xml_parser): Remove explicit initialization
+       of the scopes member.  Use std::vector::emplace_back.
+
 2017-04-18  Pedro Alves  <palves@redhat.com>
 
        * xml-support.c (gdb_xml_parser): Add ctor/dtor.  Make is_xinclude
index a9443d67fe947aeafa7b20f39819d1eee787c8c1..d6c940c0de95c8dc41ec7d00f715ad454354c609 100644 (file)
@@ -22,6 +22,7 @@
 #include "xml-support.h"
 #include "filestuff.h"
 #include "safe-ctype.h"
+#include <vector>
 
 /* Debugging flag.  */
 static int debug_xml;
@@ -42,6 +43,32 @@ static int debug_xml;
    nesting.  */
 struct scope_level
 {
+  explicit scope_level (const gdb_xml_element *elements_ = NULL)
+    : elements (elements_),
+      element (NULL),
+      seen (0),
+      body (NULL)
+  {}
+
+  scope_level (scope_level &&other) noexcept
+    : elements (other.elements),
+      element (other.element),
+      seen (other.seen),
+      body (other.body)
+  {
+    if (this != &other)
+      other.body = NULL;
+  }
+
+  ~scope_level ()
+  {
+    if (this->body)
+      {
+       obstack_free (this->body, NULL);
+       xfree (this->body);
+      }
+  }
+
   /* Elements we allow at this level.  */
   const struct gdb_xml_element *elements;
 
@@ -52,11 +79,9 @@ struct scope_level
      optional and repeatable checking).  */
   unsigned int seen;
 
-  /* Body text accumulation.  */
+  /* Body text accumulation.  This is an owning pointer.  */
   struct obstack *body;
 };
-typedef struct scope_level scope_level_s;
-DEF_VEC_O(scope_level_s);
 
 /* The parser itself, and our additional state.  */
 struct gdb_xml_parser
@@ -71,7 +96,8 @@ struct gdb_xml_parser
   const char *name;            /* Name of this parser.  */
   void *user_data;             /* The user's callback data, for handlers.  */
 
-  VEC(scope_level_s) *scopes;  /* Scoping stack.  */
+  /* Scoping stack.  */
+  std::vector<scope_level> scopes;
 
   struct gdb_exception error;  /* A thrown error, if any.  */
   int last_line;               /* The line of the thrown error, or 0.  */
@@ -89,18 +115,19 @@ static void
 gdb_xml_body_text (void *data, const XML_Char *text, int length)
 {
   struct gdb_xml_parser *parser = (struct gdb_xml_parser *) data;
-  struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
 
   if (parser->error.reason < 0)
     return;
 
-  if (scope->body == NULL)
+  scope_level &scope = parser->scopes.back ();
+
+  if (scope.body == NULL)
     {
-      scope->body = XCNEW (struct obstack);
-      obstack_init (scope->body);
+      scope.body = XCNEW (struct obstack);
+      obstack_init (scope.body);
     }
 
-  obstack_grow (scope->body, text, length);
+  obstack_grow (scope.body, text, length);
 }
 
 /* Issue a debugging message from one of PARSER's handlers.  */
@@ -179,8 +206,6 @@ gdb_xml_start_element (void *data, const XML_Char *name,
                       const XML_Char **attrs)
 {
   struct gdb_xml_parser *parser = (struct gdb_xml_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;
@@ -189,11 +214,16 @@ gdb_xml_start_element (void *data, const XML_Char *name,
 
   /* Push an error scope.  If we return or throw an exception before
      filling this in, it will tell us to ignore children of this
-     element.  */
-  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);
+     element.  Note we don't take a reference to the element yet
+     because further below we'll process the element which may recurse
+     back here and push more elements to the vector.  When the
+     recursion unrolls all such elements will have been popped back
+     already, but if one of those pushes reallocates the vector,
+     previous element references will be invalidated.  */
+  parser->scopes.emplace_back ();
+
+  /* Get a reference to the current scope.  */
+  scope_level &scope = parser->scopes[parser->scopes.size () - 2];
 
   gdb_xml_debug (parser, _("Entering element <%s>"), name);
 
@@ -201,7 +231,7 @@ gdb_xml_start_element (void *data, const XML_Char *name,
      children.  Record that we've seen it.  */
 
   seen = 1;
-  for (element = scope->elements; element && element->name;
+  for (element = scope.elements; element && element->name;
        element++, seen <<= 1)
     if (strcmp (element->name, name) == 0)
       break;
@@ -213,12 +243,10 @@ gdb_xml_start_element (void *data, const XML_Char *name,
         list into the new scope even if there was no match.  */
       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;
+         scope_level &unknown_scope = parser->scopes.back ();
+         unknown_scope.elements = scope.elements;
          return;
        }
 
@@ -226,10 +254,10 @@ gdb_xml_start_element (void *data, const XML_Char *name,
       return;
     }
 
-  if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope->seen))
+  if (!(element->flags & GDB_XML_EF_REPEATABLE) && (seen & scope.seen))
     gdb_xml_error (parser, _("Element <%s> only expected once"), name);
 
-  scope->seen |= seen;
+  scope.seen |= seen;
 
   back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
 
@@ -302,10 +330,13 @@ gdb_xml_start_element (void *data, const XML_Char *name,
   if (element->start_handler)
     element->start_handler (parser, element, parser->user_data, attributes);
 
-  /* Fill in a new scope level.  */
-  scope = VEC_last (scope_level_s, parser->scopes);
-  scope->element = element;
-  scope->elements = element->children;
+  /* Fill in a new scope level.  Note that we must delay getting a
+     back reference till here because above we might have recursed,
+     which may have reallocated the vector which invalidates
+     iterators/pointers/references.  */
+  scope_level &new_scope = parser->scopes.back ();
+  new_scope.element = element;
+  new_scope.elements = element->children;
 
   do_cleanups (back_to);
 }
@@ -342,7 +373,7 @@ gdb_xml_start_element_wrapper (void *data, const XML_Char *name,
 static void
 gdb_xml_end_element (gdb_xml_parser *parser, const XML_Char *name)
 {
-  struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
+  struct scope_level *scope = &parser->scopes.back ();
   const struct gdb_xml_element *element;
   unsigned int seen;
 
@@ -387,12 +418,7 @@ gdb_xml_end_element (gdb_xml_parser *parser, const XML_Char *name)
     XML_DefaultCurrent (parser->expat_parser);
 
   /* Pop the scope level.  */
-  if (scope->body)
-    {
-      obstack_free (scope->body, NULL);
-      xfree (scope->body);
-    }
-  VEC_pop (scope_level_s, parser->scopes);
+  parser->scopes.pop_back ();
 }
 
 /* Wrapper for gdb_xml_end_element, to prevent throwing exceptions
@@ -424,19 +450,7 @@ gdb_xml_end_element_wrapper (void *data, const XML_Char *name)
 
 gdb_xml_parser::~gdb_xml_parser ()
 {
-  struct scope_level *scope;
-  int ix;
-
   XML_ParserFree (this->expat_parser);
-
-  /* Clean up the scopes.  */
-  for (ix = 0; VEC_iterate (scope_level_s, this->scopes, ix, scope); ix++)
-    if (scope->body)
-      {
-       obstack_free (scope->body, NULL);
-       xfree (scope->body);
-      }
-  VEC_free (scope_level_s, this->scopes);
 }
 
 /* Initialize a parser.  */
@@ -446,7 +460,6 @@ gdb_xml_parser::gdb_xml_parser (const char *name_,
                                void *user_data_)
   : name (name_),
     user_data (user_data_),
-    scopes (NULL),
     error (exception_none),
     last_line (0),
     dtd_name (NULL),
@@ -464,10 +477,7 @@ gdb_xml_parser::gdb_xml_parser (const char *name_,
   XML_SetCharacterDataHandler (this->expat_parser, gdb_xml_body_text);
 
   /* Initialize the outer scope.  */
-  scope_level start_scope;
-  memset (&start_scope, 0, sizeof (start_scope));
-  start_scope.elements = elements;
-  VEC_safe_push (scope_level_s, this->scopes, &start_scope);
+  this->scopes.emplace_back (elements);
 }
 
 /* External entity handler.  The only external entities we support