* cplus-dem.c (cplus_markers): Add table for gnu style and
authorFred Fish <fnf@specifix.com>
Fri, 14 Aug 1992 19:14:15 +0000 (19:14 +0000)
committerFred Fish <fnf@specifix.com>
Fri, 14 Aug 1992 19:14:15 +0000 (19:14 +0000)
use throughout, in place of compile time constant CPLUS_MARKER.
* cplus-dem.c (ARM_VTABLE_STRING, ARM_VTABLE_STRLEN):  Add.
* cplus-dem.c (cfront_special):  New function, as suggested
by pfieland@stratus.com.
* cplus-dem.c (forget_types):  New function.
* cplus-dem.c (cplus_demangle):  Call gnu_special, moved from
demangle_prefix().
* cplus-dem.c (mop_up):  Call forget_types().
* cplus-dem.c (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING):
Use throughout, instead of checking current_demangling_style.
* cplus-dem.c (demangle_signature):  When finding an explicit
start of function args, forget all remembered types for
lucid/cfront style demangling.
* cplus-dem.c (demangle_prefix):  In a sequence of two or more
underbar characters, use last pair as the delimiter.  Hoist
gnu_special() call up to cplus_demangle().  Call cfront_special()
when appropriate.
* cplus-dem.c (cplus_special):  Fix virtual table name demangling
for inherited classes.
* cplus-dem.c (demangle_args):  Document quirks of numbered
references to previously seen types.
* dbxread.c (read_ofile_symtab, process_one_symbol):
Use AUTO_DEMANGLING rather than explicitly checking
current_demangling_style.
* demangle.h:  Add some comments.
* demangle.h (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING,
CFRONT_DEMANGLING):  New macros.
* dwarfread.c (LCC_PRODUCER):  Remove trailing space, which is
not found in the actual producer string produced by lcc.
* dwarfread.c (handle_producer):  Use AUTO_DEMANGLING rather
than explicitly checking current_demangling_style.

gdb/ChangeLog
gdb/cplus-dem.c
gdb/demangle.h
gdb/dwarfread.c

index 329996cad048aa50bbdecdf83365043f72f464af..21195b9c2762d8f405384f992827fd683107a6b1 100644 (file)
@@ -1,3 +1,38 @@
+Fri Aug 14 12:11:25 1992  Fred Fish  (fnf@cygnus.com)
+
+       * cplus-dem.c (cplus_markers):  Add table for gnu style and
+       use throughout, in place of compile time constant CPLUS_MARKER.
+       * cplus-dem.c (ARM_VTABLE_STRING, ARM_VTABLE_STRLEN):  Add.
+       * cplus-dem.c (cfront_special):  New function, as suggested
+       by pfieland@stratus.com.
+       * cplus-dem.c (forget_types):  New function.
+       * cplus-dem.c (cplus_demangle):  Call gnu_special, moved from
+       demangle_prefix().
+       * cplus-dem.c (mop_up):  Call forget_types().
+       * cplus-dem.c (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING):
+       Use throughout, instead of checking current_demangling_style.
+       * cplus-dem.c (demangle_signature):  When finding an explicit
+       start of function args, forget all remembered types for
+       lucid/cfront style demangling.
+       * cplus-dem.c (demangle_prefix):  In a sequence of two or more
+       underbar characters, use last pair as the delimiter.  Hoist
+       gnu_special() call up to cplus_demangle().  Call cfront_special()
+       when appropriate.
+       * cplus-dem.c (cplus_special):  Fix virtual table name demangling
+       for inherited classes.  
+       * cplus-dem.c (demangle_args):  Document quirks of numbered
+       references to previously seen types.
+       * dbxread.c (read_ofile_symtab, process_one_symbol):
+       Use AUTO_DEMANGLING rather than explicitly checking
+       current_demangling_style.
+       * demangle.h:  Add some comments.
+       * demangle.h (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING,
+       CFRONT_DEMANGLING):  New macros.
+       * dwarfread.c (LCC_PRODUCER):  Remove trailing space, which is
+       not found in the actual producer string produced by lcc.
+       * dwarfread.c (handle_producer):  Use AUTO_DEMANGLING rather
+       than explicitly checking current_demangling_style.
+
 Thu Aug 13 11:54:46 1992  John Gilmore  (gnu at cygnus.com)
 
        * breakpoint.c (enable_longjmp_breakpoint,
index 525df0b53c98b0606bb183b9c1a838eb3cc7be9c..4bf4b110e2e5b23a2b281cc2b15cc42f61427a71 100644 (file)
 #include <ctype.h>
 #include <string.h>
 
-/* 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).  */
+/* In order to allow a single demangler executable to demangle strings
+   using various common values of CPLUS_MARKER, as well as any specific
+   one set at compile time, we maintain a string containing all the
+   commonly used ones, and check to see if the marker we are looking for
+   is in that string.  CPLUS_MARKER is usually '$' on systems where the
+   assembler can deal with that.  Where the assembler can't, it's usually
+   '.' (but on many systems '.' is used for other things).  We put the
+   current defined CPLUS_MARKER first (which defaults to '$'), followed
+   by the next most common value, followed by an explicit '$' in case
+   the value of CPLUS_MARKER is not '$'.
+
+   We could avoid this if we could just get g++ to tell us what the actual
+   cplus marker character is as part of the debug information, perhaps by
+   ensuring that it is the character that terminates the gcc<n>_compiled
+   marker symbol (FIXME). */
 
 #if !defined (CPLUS_MARKER)
 #define CPLUS_MARKER '$'
 #endif
 
+static const char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
+
 #ifndef __STDC__
 #define const
 #endif
@@ -160,6 +174,9 @@ typedef struct string               /* Beware: these aren't required to be */
 #define APPEND_BLANK(str)      {if (!STRING_EMPTY(str)) \
                                   string_append(str, " ");}
 
+#define ARM_VTABLE_STRING "__vtbl__"   /* Lucid/cfront virtual table prefix */
+#define ARM_VTABLE_STRLEN 8            /* strlen (ARM_VTABLE_STRING) */
+
 /* Prototypes for local functions */
 
 static char *
@@ -191,6 +208,9 @@ demangle_prefix PARAMS ((string *, const char **, struct work_stuff *));
 static int
 gnu_special PARAMS ((string *, const char **, struct work_stuff *));
 
+static int
+cfront_special PARAMS ((string *, const char **, struct work_stuff *));
+
 static void
 string_need PARAMS ((string *, int));
 
@@ -245,6 +265,9 @@ demangle_function_name PARAMS ((string *, const char **, struct work_stuff*,
 static void
 remember_type PARAMS ((const char *, int, struct work_stuff *));
 
+static void
+forget_types PARAMS ((struct work_stuff *));
+
 #if 0
 static void
 string_prepends PARAMS ((string *, string *));
@@ -337,7 +360,23 @@ cplus_demangle (mangled, options)
       work -> options = options;
       
       string_init (&decl);
-      success = demangle_prefix (&decl, &mangled, work);
+
+      /* First check to see if gnu style demangling is active and if the
+        string to be demangled contains a CPLUS_MARKER.  If so, attempt to
+        recognize one of the gnu special forms rather than looking for a
+        standard prefix.  In particular, don't worry about whether there
+        is a "__" string in the mangled string.  Consider "_$_5__foo" for
+        example. */
+
+      if ((AUTO_DEMANGLING || GNU_DEMANGLING)
+         && (strpbrk (mangled, cplus_markers)) != NULL)
+       {
+         success = gnu_special (&decl, &mangled, work);
+       }
+      else
+       {
+         success = demangle_prefix (&decl, &mangled, work);
+       }
       if (success && (*mangled != '\0'))
        {
          success = demangle_signature (&decl, &mangled, work);
@@ -358,13 +397,7 @@ mop_up (declp, work, success)
 
   /* Discard the remembered types, if any. */
   
-  for (i = 0; i < work -> ntypes; i++)
-    {
-      if (work -> typevec[i] != NULL)
-       {
-         free (work -> typevec[i]);
-       }
-    }
+  forget_types (work);
   if (work -> typevec != NULL)
     {
       free ((char *) work -> typevec);
@@ -439,8 +472,7 @@ demangle_signature (declp, mangled, work)
        {
          case 'Q':
            success = demangle_qualified (declp, mangled, work);
-           if (current_demangling_style == auto_demangling ||
-               current_demangling_style == gnu_demangling)
+           if (AUTO_DEMANGLING || GNU_DEMANGLING)
              {
                expect_func = 1;
              }
@@ -467,8 +499,7 @@ demangle_signature (declp, mangled, work)
                remember_type (premangle, *mangled - premangle, work);
              }
 #endif
-           if (current_demangling_style == auto_demangling ||
-               current_demangling_style == gnu_demangling)
+           if (AUTO_DEMANGLING || GNU_DEMANGLING)
              {
                expect_func = 1;
              }
@@ -480,8 +511,19 @@ demangle_signature (declp, mangled, work)
             the class name.  For GNU style, it is just implied.  So we can
             safely just consume any 'F' at this point and be compatible
             with either style. */
+
            func_done = 1;
            (*mangled)++;
+
+           /* For lucid/cfront style we have to forget any types we might
+              have remembered up to this point, since they were not argument
+              types.  GNU style considers all types seen as available for
+              back references.  See comment in demangle_args() */
+
+           if (LUCID_DEMANGLING || CFRONT_DEMANGLING)
+             {
+               forget_types (work);
+             }
            success = demangle_args (declp, mangled, work);
            break;
          
@@ -500,8 +542,7 @@ demangle_signature (declp, mangled, work)
            break;
 
          default:
-           if (current_demangling_style == auto_demangling ||
-               current_demangling_style == gnu_demangling)
+           if (AUTO_DEMANGLING || GNU_DEMANGLING)
              {
                /* Assume we have stumbled onto the first outermost function
                   argument token, and start processing args. */
@@ -518,8 +559,7 @@ demangle_signature (declp, mangled, work)
              }
            break;
        }
-      if (current_demangling_style == auto_demangling ||
-         current_demangling_style == gnu_demangling)
+      if (AUTO_DEMANGLING || GNU_DEMANGLING)
        {
          if (success && expect_func)
            {
@@ -530,8 +570,7 @@ demangle_signature (declp, mangled, work)
     }
   if (success && !func_done)
     {
-      if (current_demangling_style == auto_demangling ||
-         current_demangling_style == gnu_demangling)
+      if (AUTO_DEMANGLING || 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
@@ -894,20 +933,25 @@ demangle_prefix (declp, mangled, work)
 {
   int success = 1;
   const char *scan;
+  int i;
 
   scan = strstr (*mangled, "__");
-  if (scan == NULL)
+
+  if (scan != NULL)
     {
-      if (current_demangling_style == auto_demangling ||
-         current_demangling_style == gnu_demangling)
+      /* We found a sequence of two or more '_', ensure that we start at
+        the last pair in the sequence. */
+      i = strspn (scan, "_");
+      if (i > 2)
        {
-         success = gnu_special (declp, mangled, work);
-       }
-      else
-       {
-         success = 0;
+         scan += (i - 2); 
        }
     }
+  if (scan == NULL)
+    {
+      success = 0;
+    }
   else if (work -> static_type)
     {
       if (!isdigit (scan[0]) && (scan[0] != 't'))
@@ -926,19 +970,23 @@ demangle_prefix (declp, mangled, work)
       /* Mangled name starts with "__".  Skip over any leading '_' characters,
         then find the next "__" that separates the prefix from the signature.
         */
-      while (*scan == '_')
-       {
-         scan++;
-       }
-      if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
-       {
-         /* No separator (I.E. "__not_mangled"), or empty signature
-            (I.E. "__not_mangled_either__") */
-         success = 0;
-       }
-      else
+      if (!(CFRONT_DEMANGLING || LUCID_DEMANGLING)
+         || (cfront_special (declp, mangled, work) == 0))
        {
-         demangle_function_name (declp, mangled, work, scan);
+         while (*scan == '_')
+           {
+             scan++;
+           }
+         if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
+           {
+             /* No separator (I.E. "__not_mangled"), or empty signature
+                (I.E. "__not_mangled_either__") */
+             success = 0;
+           }
+         else
+           {
+             demangle_function_name (declp, mangled, work, scan);
+           }
        }
     }
   else if (*(scan + 2) != '\0')
@@ -975,7 +1023,8 @@ DESCRIPTION
        the normal pattern.  For example:
 
                _$_3foo         (destructor for class foo)
-               _vt$foo         (virtual table)
+               _vt$foo         (foo virtual table)
+               _vt$foo$bar     (foo::bar virtual table)
                _3foo$varname   (static data member)
  */
 
@@ -990,7 +1039,7 @@ gnu_special (declp, mangled, work)
   const char *p;
 
   if ((*mangled)[0] == '_'
-      && (*mangled)[1] == CPLUS_MARKER
+      && strchr (cplus_markers, (*mangled)[1]) != NULL
       && (*mangled)[2] == '_')
     {
       /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
@@ -1000,21 +1049,29 @@ gnu_special (declp, mangled, work)
   else if ((*mangled)[0] == '_'
           && (*mangled)[1] == 'v'
           && (*mangled)[2] == 't'
-          && (*mangled)[3] == CPLUS_MARKER)
+          && strchr (cplus_markers, (*mangled)[3]) != NULL)
     {
       /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
          and create the decl.  Note that we consume the entire mangled
         input string, which means that demangle_signature has no work
         to do. */
       (*mangled) += 4;
-      n = strlen (*mangled);
-      string_appendn (declp, *mangled, n);
+      while (**mangled != '\0')
+       {
+         n = strcspn (*mangled, cplus_markers);
+         string_appendn (declp, *mangled, n);
+         (*mangled) += n;
+         if (**mangled != '\0')
+           {
+             string_append (declp, "::");
+             (*mangled)++;
+           }
+       }
       string_append (declp, " virtual table");
-      (*mangled) += n;
     }
   else if ((*mangled)[0] == '_'
           && isdigit ((*mangled)[1])
-          && (p = strchr (*mangled, CPLUS_MARKER)) != NULL)
+          && (p = strpbrk (*mangled, cplus_markers)) != NULL)
     {
       /* static data member, "_3foo$varname" for example */
       (*mangled)++;
@@ -1033,6 +1090,67 @@ gnu_special (declp, mangled, work)
   return (success);
 }
 
+/*
+
+LOCAL FUNCTION
+
+       cfront_special -- special handling of cfront/lucid mangled strings
+
+SYNOPSIS
+
+       static int
+       cfront_special (string *declp, const char **mangled,
+                       struct work_stuff *work)
+
+
+DESCRIPTION
+
+       Process some special cfront style mangling forms that don't fit
+       the normal pattern.  For example:
+
+               __vtbl__3foo            (foo virtual table)
+               __vtbl__3foo__3bar      (bar::foo virtual table)
+
+ */
+
+static int
+cfront_special (declp, mangled, work)
+     string *declp;
+     const char **mangled;
+     struct work_stuff *work;
+{
+  int n;
+  int i;
+  int success = 1;
+  const char *p;
+
+  if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
+    {
+      /* Found a cfront style virtual table, get past ARM_VTABLE_STRING
+         and create the decl.  Note that we consume the entire mangled
+        input string, which means that demangle_signature has no work
+        to do. */
+      (*mangled) += ARM_VTABLE_STRLEN;
+      while (**mangled != '\0')
+       {
+         n = consume_count (mangled);
+         string_prependn (declp, *mangled, n);
+         (*mangled) += n;
+         if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
+           {
+             string_prepend (declp, "::");
+             (*mangled) += 2;
+           }
+       }
+      string_append (declp, " virtual table");
+    }
+  else
+    {
+      success = 0;
+    }
+  return (success);
+}
+
 /* Do a qualified name, such as "Q25Outer5Inner" for "Outer::Inner" */
 
 static int
@@ -1531,6 +1649,25 @@ remember_type (start, len, work)
   work -> typevec[work -> ntypes++] = tem;
 }
 
+/* Forget the remembered types, but not the type vector itself. */
+
+static void
+forget_types (work)
+     struct work_stuff *work;
+{
+  int i;
+
+  while (work -> ntypes > 0)
+    {
+      i = --(work -> ntypes);
+      if (work -> typevec[i] != NULL)
+       {
+         free (work -> typevec[i]);
+         work -> typevec[i] = NULL;
+       }
+    }
+}
+
 /* Process the argument list part of the signature, after any class spec
    has been consumed, as well as the first 'F' character (if any).  For
    example:
@@ -1539,7 +1676,39 @@ remember_type (start, len, work)
    "complexfunc5__FPFPc_PFl_i" =>      process "PFPc_PFl_i"
 
    DECLP must be already initialised, usually non-empty.  It won't be freed
-   on failure */
+   on failure.
+
+   Note that g++ differs significantly from cfront and lucid style mangling
+   with regards to references to previously seen types.  For example, given
+   the source fragment:
+
+     class foo {
+       public:
+       foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
+     };
+
+     foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+     void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+
+   g++ produces the names:
+
+     __3fooiRT0iT2iT2
+     foo__FiR3fooiT1iT1
+
+   while lcc (and presumably cfront as well) produces:
+
+     foo__FiR3fooT1T2T1T2
+     __ct__3fooFiR3fooT1T2T1T2
+
+   Note that g++ bases it's type numbers starting at zero and counts all
+   previously seen types, while lucid/cfront bases it's type numbers starting
+   at one and only considers types after it has seen the 'F' character
+   indicating the start of the function args.  For lucid/cfront style, we
+   account for this difference by discarding any previously seen types when
+   we see the 'F' character, and subtracting one from the type number
+   reference.
+
+ */
 
 static int
 demangle_args (declp, type, work)
@@ -1584,8 +1753,7 @@ demangle_args (declp, type, work)
            {
              return (0);
            }
-         if (current_demangling_style == lucid_demangling ||
-             current_demangling_style == cfront_demangling)
+         if (LUCID_DEMANGLING || CFRONT_DEMANGLING)
            {
              t--;
            }
@@ -1675,8 +1843,7 @@ demangle_function_name (declp, mangled, work, scan)
 
   (*mangled) = scan + 2;
 
-  if (current_demangling_style == lucid_demangling ||
-      current_demangling_style == cfront_demangling)
+  if (LUCID_DEMANGLING || CFRONT_DEMANGLING)
     {
 
       /* See if we have an ARM style constructor or destructor operator.
@@ -1701,7 +1868,7 @@ demangle_function_name (declp, mangled, work, scan)
   if (declp->p - declp->b >= 3 
       && declp->b[0] == 'o'
       && declp->b[1] == 'p'
-      && declp->b[2] == CPLUS_MARKER)
+      && strchr (cplus_markers, declp->b[2]) != NULL)
     {
       /* see if it's an assignment expression */
       if (declp->p - declp->b >= 10 /* op$assign_ */
index ce50eb79a96e84e6d2f6e7643f7f6141ff01a17b..cc3fc60c0f4347c7e4377d9bafce70a275ec82a9 100644 (file)
 #define DMGL_PARAMS    (1 << 0)        /* Include function args */
 #define DMGL_ANSI      (1 << 1)        /* Include const, volatile, etc */
 
+/* Enumeration of possible demangling styles.
+
+   Lucid and cfront styles are still kept logically distinct, even though
+   they now both behave identically.  The resulting style is actual the
+   union of both.  I.E. either style recognizes both "__pt__" and "__rf__"
+   for operator "->", even though the first is lucid style and the second
+   is cfront/ARM style. (FIXME?) */
+
 extern enum demangling_styles
 {
   unknown_demangling = 0,
@@ -28,10 +36,19 @@ extern enum demangling_styles
   cfront_demangling
 } current_demangling_style;
 
+/* Define string names for the various demangling styles. */
+
+#define AUTO_DEMANGLING_STYLE_STRING   "auto"
 #define GNU_DEMANGLING_STYLE_STRING    "gnu"
 #define LUCID_DEMANGLING_STYLE_STRING  "lucid"
 #define CFRONT_DEMANGLING_STYLE_STRING "cfront"
-#define AUTO_DEMANGLING_STYLE_STRING   "auto"
+
+/* Some macros to test what demangling style is active. */
+
+#define AUTO_DEMANGLING (current_demangling_style == auto_demangling)
+#define GNU_DEMANGLING (current_demangling_style == gnu_demangling)
+#define LUCID_DEMANGLING (current_demangling_style == lucid_demangling)
+#define CFRONT_DEMANGLING (current_demangling_style == cfront_demangling)
 
 extern void
 set_demangling_style PARAMS ((char *));
index fcca11c72f5651d145df7626f02e64ba074f8dd3..6844813fb0486aeff15e35fbdd7b80f0e8c22556 100644 (file)
@@ -76,7 +76,7 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */
 #endif
 
 #ifndef LCC_PRODUCER
-#define LCC_PRODUCER "NCR C/C++ "
+#define LCC_PRODUCER "NCR C/C++"
 #endif
 
 #ifndef CFRONT_PRODUCER
@@ -1593,7 +1593,7 @@ handle_producer (producer)
      gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
 
 #if 1 /* Works, but is experimental.  -fnf */
-  if (current_demangling_style == auto_demangling)
+  if (AUTO_DEMANGLING)
     {
       if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
        {