Build unavailable-stack frames for tracepoint.
[deliverable/binutils-gdb.git] / gdb / cp-name-parser.y
index 023e306e118d9938a6cf623a199d20378e83ab6a..c6a5c341bfc521065284735b9910b9a0ebd34bfd 100644 (file)
@@ -1,25 +1,23 @@
 /* YACC parser for C++ names, for GDB.
 
-   Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2003-2016 Free Software Foundation, Inc.
 
    Parts of the lexer are based on c-exp.y from GDB.
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Note that malloc's and realloc's in this file are transformed to
    xmalloc and xrealloc respectively by the same sed command in the
@@ -31,16 +29,12 @@ Boston, MA 02110-1301, USA.  */
 
 %{
 
-#include "config.h"
+#include "defs.h"
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <unistd.h>
-#include <string.h>
-
 #include "safe-ctype.h"
-#include "libiberty.h"
 #include "demangle.h"
+#include "cp-support.h"
 
 /* Bison does not make it easy to create a parser without global
    state, unfortunately.  Here are all the global variables used
@@ -60,7 +54,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];
 };
 
@@ -75,8 +69,7 @@ d_grab (void)
     {
       if (demangle_info->next == NULL)
        {
-         more = malloc (sizeof (struct demangle_info));
-         more->prev = demangle_info;
+         more = XNEW (struct demangle_info);
          more->next = NULL;
          demangle_info->next = more;
        }
@@ -171,6 +164,12 @@ static struct demangle_component *d_binary (const char *,
 #define yygindex cpname_yygindex
 #define yytable         cpname_yytable
 #define yycheck         cpname_yycheck
+#define yyss   cpname_yyss
+#define yysslim        cpname_yysslim
+#define yyssp  cpname_yyssp
+#define yystacksize cpname_yystacksize
+#define yyvs   cpname_yyvs
+#define yyvsp  cpname_yyvsp
 
 int yyparse (void);
 static int yylex (void);
@@ -189,7 +188,11 @@ fill_comp (enum demangle_component_type d_type, struct demangle_component *lhs,
           struct demangle_component *rhs)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_component (ret, d_type, lhs, rhs);
+  int i;
+
+  i = cplus_demangle_fill_component (ret, d_type, lhs, rhs);
+  gdb_assert (i);
+
   return ret;
 }
 
@@ -205,7 +208,11 @@ static struct demangle_component *
 make_operator (const char *name, int args)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_operator (ret, name, args);
+  int i;
+
+  i = cplus_demangle_fill_operator (ret, name, args);
+  gdb_assert (i);
+
   return ret;
 }
 
@@ -213,7 +220,11 @@ static struct demangle_component *
 make_dtor (enum gnu_v3_dtor_kinds kind, struct demangle_component *name)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_dtor (ret, kind, name);
+  int i;
+
+  i = cplus_demangle_fill_dtor (ret, kind, name);
+  gdb_assert (i);
+
   return ret;
 }
 
@@ -221,7 +232,11 @@ static struct demangle_component *
 make_builtin_type (const char *name)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_builtin_type (ret, name);
+  int i;
+
+  i = cplus_demangle_fill_builtin_type (ret, name);
+  gdb_assert (i);
+
   return ret;
 }
 
@@ -229,7 +244,11 @@ static struct demangle_component *
 make_name (const char *name, int len)
 {
   struct demangle_component *ret = d_grab ();
-  cplus_demangle_fill_name (ret, name, len);
+  int i;
+
+  i = cplus_demangle_fill_name (ret, name, len);
+  gdb_assert (i);
+
   return ret;
 }
 
@@ -255,16 +274,12 @@ make_name (const char *name, int len)
       int fold_flag;
     } abstract;
     int lval;
-    struct {
-      int val;
-      struct demangle_component *type;
-    } typed_val_int;
     const char *opname;
   }
 
-%type <comp> exp exp1 type start start_opt operator colon_name
+%type <comp> exp exp1 type start start_opt oper colon_name
 %type <comp> unqualified_name colon_ext_name
-%type <comp> template template_arg
+%type <comp> templ template_arg
 %type <comp> builtin_type
 %type <comp> typespec_2 array_indicator
 %type <comp> colon_ext_only ext_only_name
@@ -313,14 +328,6 @@ make_name (const char *name, int len)
 /* Non-C++ things we get from the demangler.  */
 %token <lval> DEMANGLER_SPECIAL
 %token CONSTRUCTION_VTABLE CONSTRUCTION_IN
-%token <typed_val_int> GLOBAL
-
-%{
-enum {
-  GLOBAL_CONSTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 20,
-  GLOBAL_DESTRUCTORS = DEMANGLE_COMPONENT_LITERAL + 21
-};
-%}
 
 /* Precedence declarations.  */
 
@@ -425,25 +432,37 @@ function
 
 demangler_special
                :       DEMANGLER_SPECIAL start
-                       { $$ = make_empty ($1);
+                       { $$ = make_empty ((enum demangle_component_type) $1);
                          d_left ($$) = $2;
                          d_right ($$) = NULL; }
                |       CONSTRUCTION_VTABLE start CONSTRUCTION_IN start
                        { $$ = fill_comp (DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE, $2, $4); }
-               |       GLOBAL
-                       { $$ = make_empty ($1.val);
-                         d_left ($$) = $1.type;
-                         d_right ($$) = NULL; }
                ;
 
-operator       :       OPERATOR NEW
-                       { $$ = make_operator ("new", 1); }
+oper   :       OPERATOR NEW
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("new", 3);
+                       }
                |       OPERATOR DELETE
-                       { $$ = make_operator ("delete", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("delete ", 1);
+                       }
                |       OPERATOR NEW '[' ']'
-                       { $$ = make_operator ("new[]", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("new[]", 3);
+                       }
                |       OPERATOR DELETE '[' ']'
-                       { $$ = make_operator ("delete[]", 1); }
+                       {
+                         /* Match the whitespacing of cplus_demangle_operators.
+                            It would abort on unrecognized string otherwise.  */
+                         $$ = make_operator ("delete[] ", 1);
+                       }
                |       OPERATOR '+'
                        { $$ = make_operator ("+", 2); }
                |       OPERATOR '-'
@@ -499,7 +518,7 @@ operator    :       OPERATOR NEW
                |       OPERATOR ARROW
                        { $$ = make_operator ("->", 2); }
                |       OPERATOR '(' ')'
-                       { $$ = make_operator ("()", 0); }
+                       { $$ = make_operator ("()", 2); }
                |       OPERATOR '[' ']'
                        { $$ = make_operator ("[]", 2); }
                ;
@@ -509,7 +528,7 @@ operator    :       OPERATOR NEW
                   since it's not clear that it's parseable.  */
 conversion_op
                :       OPERATOR typespec_2
-                       { $$ = fill_comp (DEMANGLE_COMPONENT_CAST, $2, NULL); }
+                       { $$ = fill_comp (DEMANGLE_COMPONENT_CONVERSION, $2, NULL); }
                ;
 
 conversion_op_name
@@ -535,8 +554,8 @@ conversion_op_name
 
 /* DEMANGLE_COMPONENT_NAME */
 /* This accepts certain invalid placements of '~'.  */
-unqualified_name:      operator
-               |       operator '<' template_params '>'
+unqualified_name:      oper
+               |       oper '<' template_params '>'
                        { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
                |       '~' NAME
                        { $$ = make_dtor (gnu_v3_complete_object_dtor, $2); }
@@ -560,9 +579,9 @@ colon_name  :       name
 name           :       nested_name NAME %prec NAME
                        { $$ = $1.comp; d_right ($1.last) = $2; }
                |       NAME %prec NAME
-               |       nested_name template %prec NAME
+               |       nested_name templ %prec NAME
                        { $$ = $1.comp; d_right ($1.last) = $2; }
-               |       template %prec NAME
+               |       templ %prec NAME
                ;
 
 colon_ext_name :       colon_name
@@ -592,13 +611,13 @@ nested_name       :       NAME COLONCOLON
                          d_left ($$.last) = $2;
                          d_right ($$.last) = NULL;
                        }
-               |       template COLONCOLON
+               |       templ COLONCOLON
                        { $$.comp = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
                          d_left ($$.comp) = $1;
                          d_right ($$.comp) = NULL;
                          $$.last = $$.comp;
                        }
-               |       nested_name template COLONCOLON
+               |       nested_name templ COLONCOLON
                        { $$.comp = $1.comp;
                          d_right ($1.last) = make_empty (DEMANGLE_COMPONENT_QUAL_NAME);
                          $$.last = d_right ($1.last);
@@ -609,7 +628,7 @@ nested_name :       NAME COLONCOLON
 
 /* DEMANGLE_COMPONENT_TEMPLATE */
 /* DEMANGLE_COMPONENT_TEMPLATE_ARGLIST */
-template       :       NAME '<' template_params '>'
+templ  :       NAME '<' template_params '>'
                        { $$ = fill_comp (DEMANGLE_COMPONENT_TEMPLATE, $1, $3.comp); }
                ;
 
@@ -1174,7 +1193,11 @@ exp      :       FLOAT
        ;
 
 exp    :       SIZEOF '(' type ')'     %prec UNARY
-               { $$ = d_unary ("sizeof", $3); }
+               {
+                 /* Match the whitespacing of cplus_demangle_operators.
+                    It would abort on unrecognized string otherwise.  */
+                 $$ = d_unary ("sizeof ", $3);
+               }
        ;
 
 /* C++.  */
@@ -1462,7 +1485,7 @@ c_parse_backslash (int host_char, int *target_char)
    after the zeros.  A value of 0 does not mean end of string.  */
 
 static int
-parse_escape (const char **string_ptr)
+cp_parse_escape (const char **string_ptr)
 {
   int target_char;
   int c = *(*string_ptr)++;
@@ -1483,7 +1506,7 @@ parse_escape (const char **string_ptr)
          if (c == '?')
            return 0177;
          else if (c == '\\')
-           target_char = parse_escape (string_ptr);
+           target_char = cp_parse_escape (string_ptr);
          else
            target_char = c;
 
@@ -1557,7 +1580,7 @@ yylex (void)
 {
   int c;
   int namelen;
-  const char *tokstart, *tokptr;
+  const char *tokstart;
 
  retry:
   prev_lexptr = lexptr;
@@ -1581,17 +1604,17 @@ yylex (void)
       lexptr++;
       c = *lexptr++;
       if (c == '\\')
-       c = parse_escape (&lexptr);
+       c = cp_parse_escape (&lexptr);
       else if (c == '\'')
        {
-         yyerror ("empty character constant");
+         yyerror (_("empty character constant"));
          return ERROR;
        }
 
       c = *lexptr++;
       if (c != '\'')
        {
-         yyerror ("invalid character constant");
+         yyerror (_("invalid character constant"));
          return ERROR;
        }
 
@@ -1715,7 +1738,7 @@ yylex (void)
 
            memcpy (err_copy, tokstart, p - tokstart);
            err_copy[p - tokstart] = 0;
-           yyerror ("invalid number");
+           yyerror (_("invalid number"));
            return ERROR;
          }
        lexptr = p;
@@ -1791,14 +1814,14 @@ yylex (void)
 
     case '"':
       /* These can't occur in C++ names.  */
-      yyerror ("unexpected string literal");
+      yyerror (_("unexpected string literal"));
       return ERROR;
     }
 
   if (!(c == '_' || c == '$' || ISALPHA (c)))
     {
       /* We must have come across a bad character (e.g. ';').  */
-      yyerror ("invalid character");
+      yyerror (_("invalid character"));
       return ERROR;
     }
 
@@ -1861,23 +1884,23 @@ yylex (void)
        {
          const char *p;
          lexptr = tokstart + 29;
-         yylval.typed_val_int.val = GLOBAL_CONSTRUCTORS;
+         yylval.lval = DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS;
          /* Find the end of the symbol.  */
          p = symbol_end (lexptr);
-         yylval.typed_val_int.type = make_name (lexptr, p - lexptr);
+         yylval.comp = make_name (lexptr, p - lexptr);
          lexptr = p;
-         return GLOBAL;
+         return DEMANGLER_SPECIAL;
        }
       if (strncmp (tokstart, "global destructors keyed to ", 28) == 0)
        {
          const char *p;
          lexptr = tokstart + 28;
-         yylval.typed_val_int.val = GLOBAL_DESTRUCTORS;
+         yylval.lval = DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS;
          /* Find the end of the symbol.  */
          p = symbol_end (lexptr);
-         yylval.typed_val_int.type = make_name (lexptr, p - lexptr);
+         yylval.comp = make_name (lexptr, p - lexptr);
          lexptr = p;
-         return GLOBAL;
+         return DEMANGLER_SPECIAL;
        }
 
       HANDLE_SPECIAL ("vtable for ", DEMANGLE_COMPONENT_VTABLE);
@@ -1951,20 +1974,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 = XNEW (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
@@ -1976,51 +1993,105 @@ allocate_info (void)
 char *
 cp_comp_to_string (struct demangle_component *result, int estimated_len)
 {
-  char *str, *prefix = NULL, *buf;
-  size_t err = 0;
+  size_t err;
 
-  if (result->type == GLOBAL_DESTRUCTORS)
-    {
-      result = d_left (result);
-      prefix = "global destructors keyed to ";
-    }
-  else if (result->type == GLOBAL_CONSTRUCTORS)
+  return cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, 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 = XNEW (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)
     {
-      result = d_left (result);
-      prefix = "global constructors keyed to ";
+      struct demangle_info *next = info->next;
+
+      free (info);
+      info = next;
     }
 
-  str = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, estimated_len, &err);
-  if (str == NULL)
-    return NULL;
+  /* Free any memory allocated during typedef replacement.  */
+  obstack_free (&parse_info->obstack, NULL);
 
-  if (prefix == NULL)
-    return str;
+  /* Free the parser info.  */
+  free (parse_info);
+}
 
-  buf = malloc (strlen (str) + strlen (prefix) + 1);
-  strcpy (buf, prefix);
-  strcat (buf, str);
-  free (str);
-  return (buf);
+/* 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;
+
+  /* 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 ())
     {
@@ -2031,10 +2102,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,17 +2120,6 @@ cp_print (struct demangle_component *result)
   char *str;
   size_t err = 0;
 
-  if (result->type == GLOBAL_DESTRUCTORS)
-    {
-      result = d_left (result);
-      fputs ("global destructors keyed to ", stdout);
-    }
-  else if (result->type == GLOBAL_CONSTRUCTORS)
-    {
-      result = d_left (result);
-      fputs ("global constructors keyed to ", stdout);
-    }
-
   str = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, result, 64, &err);
   if (str == NULL)
     return;
@@ -2084,6 +2145,33 @@ trim_chars (char *lexptr, char **extra_chars)
   return c;
 }
 
+/* When this file is built as a standalone program, xmalloc comes from
+   libiberty --- in which case we have to provide xfree ourselves.  */
+
+void
+xfree (void *ptr)
+{
+  if (ptr != NULL)
+    {
+      /* Literal `free' would get translated back to xfree again.  */
+      CONCAT2 (fr,ee) (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)
 {
@@ -2091,7 +2179,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)
@@ -2110,7 +2198,7 @@ main (int argc, char **argv)
        str2 = cplus_demangle (buf, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
        if (str2 == NULL)
          {
-           /* printf ("Demangling error\n"); */
+           printf ("Demangling error\n");
            if (c)
              printf ("%s%c%s\n", buf, c, extra_chars);
            else
@@ -2125,7 +2213,8 @@ main (int argc, char **argv)
            continue;
          }
 
-       cp_print (result);
+       cp_print (result->tree);
+       cp_demangled_name_parse_free (result);
 
        free (str2);
        if (c)
@@ -2144,7 +2233,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.033794 seconds and 4 git commands to generate.