Add missing POSTCOMPILE step to mi/ file generation rules
[deliverable/binutils-gdb.git] / gdb / demangle.c
index 667ba1913bb65611eff73dd2e6627cfb2339bfdc..f5f93e5daef4750aa029b3b99ceeae6984b707c1 100644 (file)
 /* Basic C++ demangling support for GDB.
-   Copyright 1991, 1992 Free Software Foundation, Inc.
+
+   Copyright (C) 1991-2016 Free Software Foundation, Inc.
+
    Written by Fred Fish at Cygnus Support.
 
-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., 675 Mass Ave, Cambridge, MA 02139, 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/>.  */
 
 
 /*  This file contains support code for C++ demangling that is common
-    to a styles of demangling, and GDB specific. */
+   to a styles of demangling, and GDB specific.  */
 
 #include "defs.h"
+#include "cli/cli-utils.h" /* for skip_to_space */
 #include "command.h"
 #include "gdbcmd.h"
 #include "demangle.h"
-#include <string.h>
+#include "gdb-demangle.h"
+#include "language.h"
 
-#ifndef DEMANGLING_STYLE
-# define DEMANGLING_STYLE GNU_DEMANGLING_STYLE_STRING
+/* Select the default C++ demangling style to use.  The default is "auto",
+   which allows gdb to attempt to pick an appropriate demangling style for
+   the executable it has loaded.  It can be set to a specific style ("gnu",
+   "lucid", "arm", "hp", etc.) in which case gdb will never attempt to do auto
+   selection of the style unless you do an explicit "set demangle auto".
+   To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in
+   the appropriate target configuration file.  */
+
+#ifndef DEFAULT_DEMANGLING_STYLE
+#define DEFAULT_DEMANGLING_STYLE AUTO_DEMANGLING_STYLE_STRING
 #endif
 
-/* The current demangling style in affect.  Global so that the demangler
-   can read it (FIXME:  change the interface) */
+static void demangle_command (char *, int);
 
-enum demangling_styles current_demangling_style;
+/* See documentation in gdb-demangle.h.  */
+int demangle = 1;
 
-/* String name for the current demangling style.  Set by the "set demangling"
-   command, printed as part of the output by the "show demangling" command. */
+static void
+show_demangle (struct ui_file *file, int from_tty,
+              struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file,
+                   _("Demangling of encoded C++/ObjC names "
+                     "when displaying symbols is %s.\n"),
+                   value);
+}
 
-static char *current_demangling_style_string;
+/* See documentation in gdb-demangle.h.  */
+int asm_demangle = 0;
 
-/* List of supported demangling styles.  Contains the name of the style as
-   seen by the user, and the enum value that corresponds to that style. */
-   
-static const struct demangler
-{
-  char *demangling_style_name;
-  enum demangling_styles demangling_style;
-  char *demangling_style_doc;
-} demanglers [] =
+static void
+show_asm_demangle (struct ui_file *file, int from_tty,
+                  struct cmd_list_element *c, const char *value)
 {
-  {AUTO_DEMANGLING_STYLE_STRING,
-     auto_demangling,
-     "Automatic selection based on executable"},
-  {GNU_DEMANGLING_STYLE_STRING,
-     gnu_demangling,
-     "GNU (g++) style demangling"},
-  {LUCID_DEMANGLING_STYLE_STRING,
-     lucid_demangling,
-     "Lucid (lcc) style demangling"},
-  {CFRONT_DEMANGLING_STYLE_STRING,
-     cfront_demangling,
-     "ARM (cfront) style demangling"},
-  {NULL, 0, NULL}
-};
-
-/* show current demangling style. */
+  fprintf_filtered (file,
+                   _("Demangling of C++/ObjC names in "
+                     "disassembly listings is %s.\n"),
+                   value);
+}
+
+/* String name for the current demangling style.  Set by the
+   "set demangle-style" command, printed as part of the output by the
+   "show demangle-style" command.  */
 
+static const char *current_demangling_style_string;
+
+/* The array of names of the known demanglyng styles.  Generated by
+   _initialize_demangler from libiberty_demanglers[] array.  */
+
+static const char **demangling_style_names;
 static void
-show_demangling_command (ignore, from_tty)
-   char *ignore;
-   int from_tty;
+show_demangling_style_names(struct ui_file *file, int from_tty,
+                           struct cmd_list_element *c, const char *value)
 {
-  /* done automatically by show command. */
+  fprintf_filtered (file, _("The current C++ demangling style is \"%s\".\n"),
+                   value);
 }
 
+/* Set current demangling style.  Called by the "set demangle-style"
+   command after it has updated the current_demangling_style_string to
+   match what the user has entered.
 
-/* set current demangling style.  called by the "set demangling" command
-   after it has updated the current_demangling_style_string to match
-   what the user has entered.
-
-   if the user has entered a string that matches a known demangling style
+   If the user has entered a string that matches a known demangling style
    name in the demanglers[] array then just leave the string alone and update
    the current_demangling_style enum value to match.
 
-   if the user has entered a string that doesn't match, including an empty
+   If the user has entered a string that doesn't match, including an empty
    string, then print a list of the currently known styles and restore
    the current_demangling_style_string to match the current_demangling_style
    enum value.
 
    Note:  Assumes that current_demangling_style_string always points to
-   a malloc'd string, even if it is a null-string. */
+   a malloc'd string, even if it is a null-string.  */
 
 static void
-set_demangling_command (ignore, from_tty)
-   char *ignore;
-   int from_tty;
+set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c)
 {
-  const struct demangler *dem;
+  const struct demangler_engine *dem;
+  int i;
 
   /*  First just try to match whatever style name the user supplied with
-      one of the known ones.  Don't bother special casing for an empty
-      name, we just treat it as any other style name that doesn't match.
-      If we match, update the current demangling style enum. */
+     one of the known ones.  Don't bother special casing for an empty
+     name, we just treat it as any other style name that doesn't match.
+     If we match, update the current demangling style enum.  */
 
-  for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+  for (dem = libiberty_demanglers, i = 0;
+       dem->demangling_style != unknown_demangling; 
+       dem++)
     {
       if (strcmp (current_demangling_style_string,
-                 dem -> demangling_style_name) == 0)
+                 dem->demangling_style_name) == 0)
        {
-         current_demangling_style = dem -> demangling_style;
+         current_demangling_style = dem->demangling_style;
+         current_demangling_style_string = demangling_style_names[i];
          break;
        }
+      i++;
     }
 
-  /* Check to see if we found a match.  If not, gripe about any non-empty
-     style name and supply a list of valid ones.  FIXME:  This should
-     probably be done with some sort of completion and with help. */
+  /* We should have found a match, given we only add known styles to
+     the enumeration list.  */
+  gdb_assert (dem->demangling_style != unknown_demangling);
+}
+
+/* G++ uses a special character to indicate certain internal names.  Which
+   character it is depends on the platform:
+   - Usually '$' on systems where the assembler will accept that
+   - Usually '.' otherwise (this includes most sysv4-like systems and most
+     ELF targets)
+   - Occasionally '_' if neither of the above is usable
+
+   We check '$' first because it is the safest, and '.' often has another
+   meaning.  We don't currently try to handle '_' because the precise forms
+   of the names are different on those targets.  */
+
+static char cplus_markers[] = {'$', '.', '\0'};
+
+/* See documentation in gdb-demangle.h.  */
+
+int
+is_cplus_marker (int c)
+{
+  return c && strchr (cplus_markers, c) != NULL;
+}
+
+/* Demangle the given string in the current language.  */
+
+static void
+demangle_command (char *args, int from_tty)
+{
+  char *demangled, *name, *lang_name = NULL;
+  char *arg_buf, *arg_start;
+  int processing_args = 1;
+  const struct language_defn *lang;
+  struct cleanup *cleanups;
 
-  if (dem -> demangling_style_name == NULL)
+  arg_buf = xstrdup (args != NULL ? args : "");
+  cleanups = make_cleanup (xfree, arg_buf);
+  arg_start = arg_buf;
+
+  while (processing_args
+        && *arg_start == '-')
     {
-      if (*current_demangling_style_string != '\0')
-       {
-         printf ("Unknown demangling style `%s'.\n",
-                 current_demangling_style_string);
-       }
-      printf ("The currently understood settings are:\n\n");
-      for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+      char *p = skip_to_space (arg_start);
+
+      if (strncmp (arg_start, "-l", p - arg_start) == 0)
        {
-         printf ("%-10s %s\n", dem -> demangling_style_name,
-                 dem -> demangling_style_doc);
-         if (dem -> demangling_style == current_demangling_style)
-           {
-             free (current_demangling_style_string);
-             current_demangling_style_string =
-               strdup (dem -> demangling_style_name);
-           }
+         char *lang_name_end;
+
+         lang_name = skip_spaces (p);
+         lang_name_end = skip_to_space (lang_name);
+         lang_name = savestring (lang_name, lang_name_end - lang_name);
+         make_cleanup (xfree, lang_name);
+         p = lang_name_end;
        }
-      if (current_demangling_style == unknown_demangling)
+      else if (strncmp (arg_start, "--", p - arg_start) == 0)
+       processing_args = 0;
+      else
        {
-         /* This can happen during initialization if gdb is compiled with
-            a DEMANGLING_STYLE value that is unknown, so pick the first
-            one as the default. */
-         current_demangling_style = demanglers[0].demangling_style;
-         current_demangling_style_string =
-           strdup (demanglers[0].demangling_style_name);
-         warning ("`%s' style demangling chosen as the default.\n",
-                  current_demangling_style_string);
+         *p = '\0';
+         error (_("Unrecognized option '%s' to demangle command.  "
+                  "Try \"help demangle\"."), arg_start);
        }
+
+      arg_start = skip_spaces (p);
     }
-}
 
-/* Fake a "set demangling" command. */
+  name = arg_start;
 
-void
-set_demangling_style (style)
-     char *style;
-{
-  if (current_demangling_style_string != NULL)
+  if (*name == '\0')
+    error (_("Usage: demangle [-l language] [--] name"));
+
+  if (lang_name != NULL)
+    {
+      enum language lang_enum;
+
+      lang_enum = language_enum (lang_name);
+      if (lang_enum == language_unknown)
+       error (_("Unknown language \"%s\""), lang_name);
+      lang = language_def (lang_enum);
+    }
+  else
+    lang = current_language;
+
+  demangled = language_demangle (lang, name, DMGL_ANSI | DMGL_PARAMS);
+  if (demangled != NULL)
     {
-      free (current_demangling_style_string);
+      printf_filtered ("%s\n", demangled);
+      xfree (demangled);
     }
-  current_demangling_style_string = strdup (style);
-  set_demangling_command ((char *) NULL, 0);
+  else
+    error (_("Can't demangle \"%s\""), name);
+
+  do_cleanups (cleanups);
 }
 
+extern initialize_file_ftype _initialize_demangler; /* -Wmissing-prototypes */
+
 void
-_initialize_demangler ()
+_initialize_demangler (void)
 {
-   struct cmd_list_element *set, *show;
-
-   set = add_set_cmd ("demangle-style", class_support, var_string_noescape,
-                     (char *) &current_demangling_style_string,
-                     "Set the current C++ demangling style.",
-                     &setlist);
-   show = add_show_from_set (set, &showlist);
-   set -> function.cfunc = set_demangling_command;
-   show -> function.cfunc = show_demangling_command;
-
-   /* Set the default demangling style chosen at compilation time. */
-   set_demangling_style (DEMANGLING_STYLE);
+  int i, ndems;
+
+  /* Fill the demangling_style_names[] array, and set the default
+     demangling style chosen at compilation time.  */
+  for (ndems = 0;
+       libiberty_demanglers[ndems].demangling_style != unknown_demangling; 
+       ndems++)
+    ;
+  demangling_style_names = XCNEWVEC (const char *, ndems + 1);
+  for (i = 0;
+       libiberty_demanglers[i].demangling_style != unknown_demangling; 
+       i++)
+    {
+      demangling_style_names[i]
+       = xstrdup (libiberty_demanglers[i].demangling_style_name);
+
+      if (current_demangling_style_string == NULL
+         && strcmp (DEFAULT_DEMANGLING_STYLE, demangling_style_names[i]) == 0)
+       current_demangling_style_string = demangling_style_names[i];
+    }
+
+  add_setshow_boolean_cmd ("demangle", class_support, &demangle, _("\
+Set demangling of encoded C++/ObjC names when displaying symbols."), _("\
+Show demangling of encoded C++/ObjC names when displaying symbols."), NULL,
+                          NULL,
+                          show_demangle,
+                          &setprintlist, &showprintlist);
+
+  add_setshow_boolean_cmd ("asm-demangle", class_support, &asm_demangle, _("\
+Set demangling of C++/ObjC names in disassembly listings."), _("\
+Show demangling of C++/ObjC names in disassembly listings."), NULL,
+                          NULL,
+                          show_asm_demangle,
+                          &setprintlist, &showprintlist);
+
+  add_setshow_enum_cmd ("demangle-style", class_support,
+                       demangling_style_names,
+                       &current_demangling_style_string, _("\
+Set the current C++ demangling style."), _("\
+Show the current C++ demangling style."), _("\
+Use `set demangle-style' without arguments for a list of demangling styles."),
+                       set_demangling_command,
+                       show_demangling_style_names,
+                       &setlist, &showlist);
+
+  add_cmd ("demangle", class_support, demangle_command, _("\
+Demangle a mangled name.\n\
+Usage: demangle [-l language] [--] name\n\
+If LANGUAGE is not specified, NAME is demangled in the current language."),
+          &cmdlist);
 }
This page took 0.027438 seconds and 4 git commands to generate.