* Makefile.in (DEMANGLING_STYLE): New define to set default
authorFred Fish <fnf@specifix.com>
Tue, 14 Jul 1992 02:13:12 +0000 (02:13 +0000)
committerFred Fish <fnf@specifix.com>
Tue, 14 Jul 1992 02:13:12 +0000 (02:13 +0000)
demangling style for C++.  Defaults to "auto".
* Makefile.in (DEMANGLE_OPTS):  Use DEMANGLING_STYLE.
* Makefile.in (SFILES_MAINDIR):  Add demangle.c
* Makefile.in (OBS):  Add demangle.o
* cplus-dem.c (GNU_DEMANGLING, ARM_DEMANGLING, LUCID_DEMANGLING):
Remove compile time decisions about demangling style and replace
with runtime decisions using current_demangling_style.
* cplus-dem.c (main):  Expand code included during building of
standalone demangler to recognize demangling style options.
* dbxread.c (demangle.h):  Include.
* dbxread.c (read_ofile_symtab, process_one_symbol):  Set GNU C++
demangling style if processing g++ code and current demangling style
is auto (Note: this feature currently disabled.)
* demangle.c:  New file, generic demangling control.
* demangle.h (demangling_styles):  New enumeration to select one
of several demangling styles.  Also define string names for each
style.
* demangle.h (set_demangling_style):  Add prototype.
* dwarfread.c (demangle.h):  Include.
* dwarfread.c (GPLUS_PRODUCER, LCC_PRODUCER, CFRONT_PRODUCER):
New producer string prefixes to recognize.
* dwarfread.c (handle_producer):  Consolidate actions for specific
producers.  Set demangling style based on producer string if
current style is auto.  (Note: this feature currently disabled.)
* config/ncr3000.mt (DEMANGLE_OPTS):  Remove.

gdb/.Sanitize
gdb/ChangeLog
gdb/Makefile.in
gdb/cplus-dem.c
gdb/demangle.c [new file with mode: 0644]
gdb/demangle.h
gdb/dwarfread.c

index 3e25295..78b4d85 100644 (file)
@@ -71,6 +71,7 @@ cplus-dem.c
 createtags
 dbxread.c
 defs.h
+demangle.c
 demangle.h
 depend
 doc
index 1d12c7f..4422419 100644 (file)
@@ -1,3 +1,32 @@
+Mon Jul 13 19:06:54 1992  Fred Fish  (fnf@cygnus.com)
+
+       * Makefile.in (DEMANGLING_STYLE):  New define to set default
+       demangling style for C++.  Defaults to "auto".
+       * Makefile.in (DEMANGLE_OPTS):  Use DEMANGLING_STYLE.
+       * Makefile.in (SFILES_MAINDIR):  Add demangle.c
+       * Makefile.in (OBS):  Add demangle.o
+       * cplus-dem.c (GNU_DEMANGLING, ARM_DEMANGLING, LUCID_DEMANGLING):
+       Remove compile time decisions about demangling style and replace
+       with runtime decisions using current_demangling_style.
+       * cplus-dem.c (main):  Expand code included during building of
+       standalone demangler to recognize demangling style options.
+       * dbxread.c (demangle.h):  Include.
+       * dbxread.c (read_ofile_symtab, process_one_symbol):  Set GNU C++
+       demangling style if processing g++ code and current demangling style
+       is auto (Note: this feature currently disabled.)
+       * demangle.c:  New file, generic demangling control.
+       * demangle.h (demangling_styles):  New enumeration to select one
+       of several demangling styles.  Also define string names for each
+       style.
+       * demangle.h (set_demangling_style):  Add prototype.
+       * dwarfread.c (demangle.h):  Include.
+       * dwarfread.c (GPLUS_PRODUCER, LCC_PRODUCER, CFRONT_PRODUCER):
+       New producer string prefixes to recognize.
+       * dwarfread.c (handle_producer):  Consolidate actions for specific
+       producers.  Set demangling style based on producer string if
+       current style is auto.  (Note: this feature currently disabled.)
+       * config/ncr3000.mt (DEMANGLE_OPTS):  Remove.
+
 Sat Jul 11 18:23:58 1992  John Gilmore  (gnu at cygnus.com)
 
        * config/sun4sol2.mh:  Remove -xs flag, default INSTALL to cp.
index 54d9074..35ddfbe 100644 (file)
@@ -168,15 +168,20 @@ DIST=gdb
 LINT=/usr/5bin/lint
 LINTFLAGS= -I${BFD_DIR}
 
+# 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", "cfront", 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 DEMANGLING_STYLE in the
+# appropriate target dependent makefile fragment.
+DEMANGLING_STYLE = "auto"
+
 # Select demangler to use.
-DEMANGLER=cplus-dem
+DEMANGLER = cplus-dem
 
-# Select options to use when compiling ${DEMANGLER}.c.  The default is no
-# options, which is correct for most targets, and also defaults to g++ style
-# demangling.  For other demangling styles, such as the Annotated C++
-# Reference Manual (section 7.2.1c) style, set this define in the target-
-# dependent makefile fragment.
-DEMANGLE_OPTS=
+# Select options to use when compiling ${DEMANGLER}.c.
+DEMANGLE_OPTS = -DDEMANGLING_STYLE=${DEMANGLING_STYLE}
 
 # Host and target-dependent makefile fragments come in here.
 ####
@@ -186,7 +191,7 @@ DEMANGLE_OPTS=
 # Files which are included via a config/* Makefile fragment
 # should *not* be specified here; they're in "ALLDEPFILES".
 SFILES_MAINDIR = \
-        blockframe.c breakpoint.c command.c core.c \
+        blockframe.c breakpoint.c command.c core.c demangle.c \
         environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
         main.c printcmd.c gdbtypes.c \
         remote.c source.c stack.c symmisc.c symtab.c symfile.c \
@@ -280,7 +285,7 @@ OBS = main.o blockframe.o breakpoint.o findvar.o stack.o source.o \
     command.o utils.o expprint.o environ.o version.o gdbtypes.o \
     copying.o $(DEPFILES) ${DEMANGLER}.o mem-break.o target.o \
     inftarg.o ieee-float.o putenv.o parse.o language.o $(YYOBJ) \
-    buildsym.o objfiles.o minsyms.o maint.o \
+    buildsym.o objfiles.o minsyms.o maint.o demangle.o \
     dbxread.o coffread.o elfread.o dwarfread.o xcoffread.o mipsread.o
 
 RAPP_OBS = rgdb.o rudp.o rserial.o serial.o udp.o $(XDEPFILES)
index f3b3d88..525df0b 100644 (file)
 #include <ctype.h>
 #include <string.h>
 
-#if !defined (GNU_DEMANGLING) && !defined (ARM_DEMANGLING)
-# define GNU_DEMANGLING 1
-#endif
-
 /* This is '$' on systems where the assembler can deal with that.
    Where the assembler can't, it's '.' (but on many systems '.' is
    used for other things).  */
@@ -91,11 +87,8 @@ static const struct optable
   "ami",         "-=",         DMGL_ANSI,      /* ansi */
   "mult",        "*",          0,              /* old */
   "ml",                  "*",          DMGL_ANSI,      /* ansi */
-#ifdef ARM_DEMANGLING
-  "amu",         "*=",         DMGL_ANSI,      /* ansi */
-#else
-  "aml",         "*=",         DMGL_ANSI,      /* ansi */
-#endif
+  "amu",         "*=",         DMGL_ANSI,      /* ansi (ARM/Lucid) */
+  "aml",         "*=",         DMGL_ANSI,      /* ansi (GNU/g++) */
   "convert",     "+",          0,              /* old (unary +) */
   "negate",      "-",          0,              /* old (unary -) */
   "trunc_mod",   "%",          0,              /* old */
@@ -134,11 +127,8 @@ static const struct optable
   "rs",                  ">>",         DMGL_ANSI,      /* ansi */
   "ars",         ">>=",        DMGL_ANSI,      /* ansi */
   "component",   "->",         0,              /* old */
-#ifdef LUCID_DEMANGLING
   "pt",                  "->",         DMGL_ANSI,      /* ansi; Lucid C++ form */
-#else
-  "rf",                  "->",         DMGL_ANSI,      /* ansi */
-#endif
+  "rf",                  "->",         DMGL_ANSI,      /* ansi; ARM/GNU form */
   "indirect",    "*",          0,              /* old */
   "method_call",  "->()",      0,              /* old */
   "addr",        "&",          0,              /* old (unary &) */
@@ -434,9 +424,7 @@ demangle_signature (declp, mangled, work)
 {
   int success = 1;
   int func_done = 0;
-#ifdef GNU_DEMANGLING
   int expect_func = 0;
-#endif
 #ifndef LONGERNAMES
   const char *premangle;
 #endif
@@ -451,9 +439,11 @@ demangle_signature (declp, mangled, work)
        {
          case 'Q':
            success = demangle_qualified (declp, mangled, work);
-#ifdef GNU_DEMANGLING
-           expect_func = 1;
-#endif
+           if (current_demangling_style == auto_demangling ||
+               current_demangling_style == gnu_demangling)
+             {
+               expect_func = 1;
+             }
            break;
          
          case 'S':
@@ -477,9 +467,11 @@ demangle_signature (declp, mangled, work)
                remember_type (premangle, *mangled - premangle, work);
              }
 #endif
-#ifdef GNU_DEMANGLING
-           expect_func = 1;
-#endif
+           if (current_demangling_style == auto_demangling ||
+               current_demangling_style == gnu_demangling)
+             {
+               expect_func = 1;
+             }
            break;
          
          case 'F':
@@ -508,39 +500,47 @@ demangle_signature (declp, mangled, work)
            break;
 
          default:
-#ifdef GNU_DEMANGLING
-           /* Assume we have stumbled onto the first outermost function
-              argument token, and start processing args. */
-           func_done = 1;
-           success = demangle_args (declp, mangled, work);
-#else
-           /* Non-GNU demanglers use a specific token to mark the start
-              of the outermost function argument tokens.  Typically 'F',
-              for ARM-demangling, for example.  So if we find something
-              we are not prepared for, it must be an error. */
-           success = 0;
-#endif
+           if (current_demangling_style == auto_demangling ||
+               current_demangling_style == gnu_demangling)
+             {
+               /* Assume we have stumbled onto the first outermost function
+                  argument token, and start processing args. */
+               func_done = 1;
+               success = demangle_args (declp, mangled, work);
+             }
+           else
+             {
+               /* Non-GNU demanglers use a specific token to mark the start
+                  of the outermost function argument tokens.  Typically 'F',
+                  for ARM-demangling, for example.  So if we find something
+                  we are not prepared for, it must be an error. */
+               success = 0;
+             }
            break;
        }
-#ifdef GNU_DEMANGLING
-      if (success && expect_func)
+      if (current_demangling_style == auto_demangling ||
+         current_demangling_style == gnu_demangling)
        {
-         func_done = 1;
-         success = demangle_args (declp, mangled, work);
+         if (success && expect_func)
+           {
+             func_done = 1;
+             success = demangle_args (declp, mangled, work);
+           }
        }
-#endif
     }
   if (success && !func_done)
     {
-#ifdef GNU_DEMANGLING
-      /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
-        bar__3fooi is 'foo::bar(int)'.  We get here when we find the
-        first case, and need to ensure that the '(void)' gets added to
-        the current declp.  Note that with ARM_DEMANGLING, the first
-        case represents the name of a static data member 'foo::bar',
-        which is in the current declp, so we leave it alone. */
-      success = demangle_args (declp, mangled, work);
-#endif
+      if (current_demangling_style == auto_demangling ||
+         current_demangling_style == gnu_demangling)
+       {
+         /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+            bar__3fooi is 'foo::bar(int)'.  We get here when we find the
+            first case, and need to ensure that the '(void)' gets added to
+            the current declp.  Note that with ARM, the first case
+            represents the name of a static data member 'foo::bar',
+            which is in the current declp, so we leave it alone. */
+         success = demangle_args (declp, mangled, work);
+       }
     }
   if (success && work -> static_type && PRINT_ARG_TYPES)
     {
@@ -895,9 +895,18 @@ demangle_prefix (declp, mangled, work)
   int success = 1;
   const char *scan;
 
-  if ((scan = strstr (*mangled, "__")) == NULL)
+  scan = strstr (*mangled, "__");
+  if (scan == NULL)
     {
-      success = gnu_special (declp, mangled, work);
+      if (current_demangling_style == auto_demangling ||
+         current_demangling_style == gnu_demangling)
+       {
+         success = gnu_special (declp, mangled, work);
+       }
+      else
+       {
+         success = 0;
+       }
     }
   else if (work -> static_type)
     {
@@ -1575,9 +1584,11 @@ demangle_args (declp, type, work)
            {
              return (0);
            }
-#ifdef ARM_DEMANGLING
-         t--;
-#endif
+         if (current_demangling_style == lucid_demangling ||
+             current_demangling_style == cfront_demangling)
+           {
+             t--;
+           }
          /* Validate the type index.  Protect against illegal indices from
             malformed type strings. */
          if ((t < 0) || (t >= work -> ntypes))
@@ -1664,28 +1675,29 @@ demangle_function_name (declp, mangled, work, scan)
 
   (*mangled) = scan + 2;
 
-#ifdef ARM_DEMANGLING
+  if (current_demangling_style == lucid_demangling ||
+      current_demangling_style == cfront_demangling)
+    {
 
-  /* See if we have an ARM style constructor or destructor operator.
-     If so, then just record it, clear the decl, and return.
-     We can't build the actual constructor/destructor decl until later,
-     when we recover the class name from the signature. */
+      /* See if we have an ARM style constructor or destructor operator.
+        If so, then just record it, clear the decl, and return.
+        We can't build the actual constructor/destructor decl until later,
+        when we recover the class name from the signature. */
 
-  if (strcmp (declp -> b, "__ct") == 0)
-    {
-      work -> constructor = 1;
-      string_clear (declp);
-      return;
-    }
-  else if (strcmp (declp -> b, "__dt") == 0)
-    {
-      work -> destructor = 1;
-      string_clear (declp);
-      return;
+      if (strcmp (declp -> b, "__ct") == 0)
+       {
+         work -> constructor = 1;
+         string_clear (declp);
+         return;
+       }
+      else if (strcmp (declp -> b, "__dt") == 0)
+       {
+         work -> destructor = 1;
+         string_clear (declp);
+         return;
+       }
     }
 
-#endif
-
   if (declp->p - declp->b >= 3 
       && declp->b[0] == 'o'
       && declp->b[1] == 'p'
@@ -1996,20 +2008,56 @@ xrealloc (oldmem, size)
   return (newmem);
 }
 
+#include <stdio.h>
+
+enum demangling_styles current_demangling_style = gnu_demangling;
+
 main (argc, argv)
   int argc;
   char **argv;
 {
   char mangled_name[128];
   char *result;
-  
-  if (argc > 1)
+  int c;
+  extern char *optarg;
+  extern int optind;
+
+  while ((c = getopt (argc, argv, "s:?")) != EOF)
     {
-      argc--;
-      argv++;
-      while (argc-- > 0)
+      switch (c)
        {
-         demangle_it (*argv);
+         case '?':
+           fprintf (stderr, "usage: demangle [-s style] [arg1 [arg2]] ...\n");
+           fprintf (stderr, "style = { gnu, lucid, cfront }\n");
+           fprintf (stderr, "reads args from stdin if none supplied\n");
+           exit (0);
+           break;
+         case 's':
+           if (strcmp (optarg, "gnu") == 0)
+             {
+               current_demangling_style = gnu_demangling;
+             }
+           else if (strcmp (optarg, "lucid") == 0)
+             {
+               current_demangling_style = lucid_demangling;
+             }
+           else if (strcmp (optarg, "cfront") == 0)
+             {
+               current_demangling_style = cfront_demangling;
+             }
+           else
+             {
+               fprintf (stderr, "unknown demangling style `%s'\n", optarg);
+               exit (1);
+             }
+           break;
+       }
+    }
+  if (optind < argc)
+    {
+      for ( ; optind < argc; optind++)
+       {
+         demangle_it (argv[optind]);
        }
     }
   else
@@ -2021,4 +2069,4 @@ main (argc, argv)
     }
 }
 
-#endif
+#endif /* main */
diff --git a/gdb/demangle.c b/gdb/demangle.c
new file mode 100644 (file)
index 0000000..9710856
--- /dev/null
@@ -0,0 +1,185 @@
+/* Basic C++ demangling support for GDB.
+   Copyright 1991, 1992 Free Software Foundation, Inc.
+   Written by Fred Fish at Cygnus Support.
+
+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 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.  */
+
+
+/*  This file contains support code for C++ demangling that is common
+    to a styles of demangling, and GDB specific. */
+
+#include "defs.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "demangle.h"
+#include <string.h>
+
+#ifndef DEMANGLING_STYLE
+# define 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) */
+
+enum demangling_styles current_demangling_style;
+
+/* 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 char *current_demangling_style_string;
+
+/* 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 [] =
+{
+  {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. */
+
+static void
+show_demangling_command (ignore, from_tty)
+   char *ignore;
+   int from_tty;
+{
+  /* done automatically by show command. */
+}
+
+
+/* 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
+   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
+   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. */
+
+static void
+set_demangling_command (ignore, from_tty)
+   char *ignore;
+   int from_tty;
+{
+  const struct demangler *dem;
+
+  /*  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. */
+
+  for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+    {
+      if (strcmp (current_demangling_style_string,
+                 dem -> demangling_style_name) == 0)
+       {
+         current_demangling_style = dem -> demangling_style;
+         break;
+       }
+    }
+
+  /* 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. */
+
+  if (dem -> demangling_style_name == NULL)
+    {
+      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++)
+       {
+         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);
+           }
+       }
+      if (current_demangling_style == unknown_demangling)
+       {
+         /* 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);
+       }
+    }
+}
+
+/* Fake a "set demangling" command. */
+
+void
+set_demangling_style (style)
+     char *style;
+{
+  if (current_demangling_style_string != NULL)
+    {
+      free (current_demangling_style_string);
+    }
+  current_demangling_style_string = strdup (style);
+  set_demangling_command ((char *) NULL, 0);
+}
+
+void
+_initialize_demangler ()
+{
+   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);
+}
index 71cdb80..ce50eb7 100644 (file)
@@ -1,4 +1,4 @@
-/* Demangler defs for GNU C++ style demangling.
+/* Defs for interface to demanglers.
    Copyright 1992 Free Software Foundation, Inc.
    
    This program is free software; you can redistribute it and/or modify
 
 #define DMGL_PARAMS    (1 << 0)        /* Include function args */
 #define DMGL_ANSI      (1 << 1)        /* Include const, volatile, etc */
+
+extern enum demangling_styles
+{
+  unknown_demangling = 0,
+  auto_demangling,
+  gnu_demangling,
+  lucid_demangling,
+  cfront_demangling
+} current_demangling_style;
+
+#define GNU_DEMANGLING_STYLE_STRING    "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING  "lucid"
+#define CFRONT_DEMANGLING_STYLE_STRING "cfront"
+#define AUTO_DEMANGLING_STYLE_STRING   "auto"
+
+extern void
+set_demangling_style PARAMS ((char *));
index 484472d..6ba1e77 100644 (file)
@@ -53,6 +53,7 @@ other things to work on, if you get bored. :-)
 #include "libbfd.h"    /* FIXME Secret Internal BFD stuff (bfd_read) */
 #include "elf/dwarf.h"
 #include "buildsym.h"
+#include "demangle.h"
 
 #ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
 #define SQUAWK(stuff) dwarfwarn stuff
@@ -70,6 +71,18 @@ typedef unsigned int DIE_REF;        /* Reference to a DIE */
 #define GCC_PRODUCER "GNU C "
 #endif
 
+#ifndef GPLUS_PRODUCER
+#define GPLUS_PRODUCER "GNU C++ "
+#endif
+
+#ifndef LCC_PRODUCER
+#define LCC_PRODUCER "LUCID C++ "
+#endif
+
+#ifndef CFRONT_PRODUCER
+#define CFRONT_PRODUCER "CFRONT "      /* A wild a** guess... */
+#endif
+
 #define STREQ(a,b)             (strcmp(a,b)==0)
 #define STREQN(a,b,n)          (strncmp(a,b,n)==0)
 
@@ -302,6 +315,9 @@ static void
 add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));
 
 static void
+handle_producer PARAMS ((char *));
+
+static void
 read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
 
 static void
@@ -1530,6 +1546,57 @@ read_func_scope (dip, thisdie, enddie, objfile)
   list_in_scope = &file_symbols;
 }
 
+
+/*
+
+LOCAL FUNCTION
+
+       handle_producer -- process the AT_producer attribute
+
+DESCRIPTION
+
+       Perform any operations that depend on finding a particular
+       AT_producer attribute.
+
+ */
+
+static void
+handle_producer (producer)
+     char *producer;
+{
+
+  /* If this compilation unit was compiled with g++ or gcc, then set the
+     processing_gcc_compilation flag. */
+
+  processing_gcc_compilation =
+    STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+      || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+
+  /* Select a demangling style if we can identify the producer and if
+     the current style is auto.  We leave the current style alone if it
+     is not auto.  We also leave the demangling style alone if we find a
+     gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
+
+#if 0 /* Works, but is disabled for now.  -fnf */
+  if (current_demangling_style == auto_demangling)
+    {
+      if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
+       {
+         set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+       }
+      else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER)))
+       {
+         set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
+       }
+      else if (STREQN (producer, CFRONT_PRODUCER, strlen (CFRONT_PRODUCER)))
+       {
+         set_demangling_style (CFRONT_DEMANGLING_STYLE_STRING);
+       }
+    }
+#endif
+}
+
+
 /*
 
 LOCAL FUNCTION
@@ -1570,8 +1637,7 @@ read_file_scope (dip, thisdie, enddie, objfile)
     }
   if (dip -> at_producer != NULL)
     {
-      processing_gcc_compilation =
-       STREQN (dip -> at_producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+      handle_producer (dip -> at_producer);
     }
   numutypes = (enddie - thisdie) / 4;
   utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));