PR c++/12266
[deliverable/binutils-gdb.git] / gdb / cp-name-parser.y
index 286bbb46c8e22b05a6513490a4be8035b52471b5..f257370c2e9abf43b00b690907e79fc25eace4f3 100644 (file)
@@ -41,6 +41,7 @@
 #include "libiberty.h"
 #include "demangle.h"
 #include "cp-support.h"
+#include "gdb_assert.h"
 
 /* Bison does not make it easy to create a parser without global
    state, unfortunately.  Here are all the global variables used
@@ -60,7 +61,7 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
 
 struct demangle_info {
   int used;
-  struct demangle_info *prev, *next;
+  struct demangle_info *next;
   struct demangle_component comps[ALLOC_CHUNK];
 };
 
@@ -76,7 +77,6 @@ d_grab (void)
       if (demangle_info->next == NULL)
        {
          more = malloc (sizeof (struct demangle_info));
-         more->prev = demangle_info;
          more->next = NULL;
          demangle_info->next = more;
        }
@@ -1935,20 +1935,14 @@ yyerror (char *msg)
    generally allocate too many components, but the extra memory usage
    doesn't hurt because the trees are temporary and the storage is
    reused.  More may be allocated later, by d_grab.  */
-static void
+static struct demangle_info *
 allocate_info (void)
 {
-  if (demangle_info == NULL)
-    {
-      demangle_info = malloc (sizeof (struct demangle_info));
-      demangle_info->prev = NULL;
-      demangle_info->next = NULL;
-    }
-  else
-    while (demangle_info->prev)
-      demangle_info = demangle_info->prev;
+  struct demangle_info *info = malloc (sizeof (struct demangle_info));
 
-  demangle_info->used = 0;
+  info->next = NULL;
+  info->used = 0;
+  return info;
 }
 
 /* Convert RESULT to a string.  The return value is allocated
@@ -1966,23 +1960,102 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len)
                               &err);
 }
 
+/* A convenience function to allocate and initialize a new struct
+   demangled_parse_info.  */
+
+struct demangle_parse_info *
+cp_new_demangle_parse_info (void)
+{
+  struct demangle_parse_info *info;
+
+  info = malloc (sizeof (struct demangle_parse_info));
+  info->info = NULL;
+  info->tree = NULL;
+  obstack_init (&info->obstack);
+
+  return info;
+}
+
+/* Free any memory associated with the given PARSE_INFO.  */
+
+void
+cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
+{
+  struct demangle_info *info = parse_info->info;
+
+  /* Free any allocated chunks of memory for the parse.  */
+  while (info != NULL)
+    {
+      struct demangle_info *next = info->next;
+
+      free (info);
+      info = next;
+    }
+
+  /* Free any memory allocated during typedef replacement.  */
+  obstack_free (&parse_info->obstack, NULL);
+
+  /* Free the parser info.  */
+  free (parse_info);
+}
+
+/* Merge the two parse trees given by DEST and SRC.  The parse tree
+   in SRC is attached to DEST at the node represented by TARGET.
+   SRC is then freed.
+
+   NOTE 1: Since there is no API to merge obstacks, this function does
+   even attempt to try it.  Fortunately, we do not (yet?) need this ability.
+   The code will assert if SRC->obstack is not empty.
+
+   NOTE 2: The string from which SRC was parsed must not be freed, since
+   this function will place pointers to that string into DEST.  */
+
+void
+cp_merge_demangle_parse_infos (struct demangle_parse_info *dest,
+                              struct demangle_component *target,
+                              struct demangle_parse_info *src)
+
+{
+  struct demangle_info *di;
+
+  /* Copy the SRC's parse data into DEST.  */
+  *target = *src->tree;
+  di = dest->info;
+  while (di->next != NULL)
+    di = di->next;
+  di->next = src->info;
+
+  /* Clear the (pointer to) SRC's parse data so that it is not freed when
+     cp_demangled_parse_info_free is called.  */
+  src->info = NULL;
+
+  /* Assert if the SRC obstack is not empty.  */
+  gdb_assert (obstack_empty_p (&src->obstack));
+
+  /* Free SRC.  */
+  cp_demangled_name_parse_free (src);
+}
+
 /* Convert a demangled name to a demangle_component tree.  On success,
-   the root of the new tree is returned; it is valid until the next
-   call to this function and should not be freed.  On error, NULL is
+   a structure containing the root of the new tree is returned; it must
+   be freed by calling cp_demangled_name_parse_free. On error, NULL is
    returned, and an error message will be set in *ERRMSG (which does
    not need to be freed).  */
 
-struct demangle_component *
+struct demangle_parse_info *
 cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
 {
   static char errbuf[60];
-  struct demangle_component *result;
+  struct demangle_parse_info *result;
 
   prev_lexptr = lexptr = demangled_name;
   error_lexptr = NULL;
   global_errmsg = NULL;
 
-  allocate_info ();
+  demangle_info = allocate_info ();
+
+  result = cp_new_demangle_parse_info ();
+  result->info = demangle_info;
 
   if (yyparse ())
     {
@@ -1993,10 +2066,11 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
          strcat (errbuf, "'");
          *errmsg = errbuf;
        }
+      cp_demangled_name_parse_free (result);
       return NULL;
     }
 
-  result = global_result;
+  result->tree = global_result;
   global_result = NULL;
 
   return result;
@@ -2048,6 +2122,20 @@ xfree (void *ptr)
     }
 }
 
+/* GDB normally defines internal_error itself, but when this file is built
+   as a standalone program, we must also provide an implementation.  */
+
+void
+internal_error (const char *file, int line, const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  fprintf (stderr, "%s:%d: internal error: ", file, line);
+  vfprintf (stderr, fmt, ap);
+  exit (1);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -2055,7 +2143,7 @@ main (int argc, char **argv)
   char buf[65536];
   int arg;
   const char *errmsg;
-  struct demangle_component *result;
+  struct demangle_parse_info *result;
 
   arg = 1;
   if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
@@ -2089,7 +2177,8 @@ main (int argc, char **argv)
            continue;
          }
 
-       cp_print (result);
+       cp_print (result->tree);
+       cp_demangled_name_parse_free (result);
 
        free (str2);
        if (c)
@@ -2108,7 +2197,8 @@ main (int argc, char **argv)
          fputc ('\n', stderr);
          return 0;
        }
-      cp_print (result);
+      cp_print (result->tree);
+      cp_demangled_name_parse_free (result);
       putchar ('\n');
     }
   return 0;
This page took 0.028846 seconds and 4 git commands to generate.