* debug.h (struct debug_write_fns): Add tag parameter to
authorIan Lance Taylor <ian@airs.com>
Mon, 8 Jan 1996 23:18:51 +0000 (23:18 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 8 Jan 1996 23:18:51 +0000 (23:18 +0000)
enum_type, start_struct_type, and start_class_type.
* debug.c (debug_write_type): Pass any tag name to
start_struct_type, debug_write_class_type, and enum_type.  If
DEBUG_KIND_TAGGED, pass the name in the recursive call.
(debug_write_class_type): Accept a new tag parameter, and pass it
to start_class_type.
* prdbg.c (pop_type): Don't remove '+' character.
(pr_enum_type): Accept and use tag parameter.
(pr_start_struct_type): Likewise.
(pr_start_class_type): Likewise.
(pr_class_baseclass): Adjust algorithm used to find where to put
the baseclass name.
(pr_tag): Don't bother to insert the tag name.

binutils/debug.c
binutils/debug.h
binutils/prdbg.c

index 18eb529818be836444e0f347b8e78c629f9b65ef..239abdbb80313f3838b53cee9a2ae42f47285ab8 100644 (file)
@@ -1,5 +1,5 @@
 /* debug.c -- Handle generic debugging information.
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
@@ -48,7 +48,7 @@ struct debug_handle
   struct debug_function *current_function;
   /* The current block.  */
   struct debug_block *current_block;
-  /* The current line number information for the current block.  */
+  /* The current line number information for the current unit.  */
   struct debug_lineno *current_lineno;
   /* Mark.  This is used by debug_write.  */
   unsigned int mark;
@@ -66,6 +66,10 @@ struct debug_unit
      file is always the main one, and that is where the main file name
      is stored.  */
   struct debug_file *files;
+  /* Line number information for this compilation unit.  This is not
+     stored by function, because assembler code may have line number
+     information without function information.  */
+  struct debug_lineno *linenos;
 };
 
 /* Information kept for a single source file.  */
@@ -394,12 +398,11 @@ struct debug_block
   bfd_vma end;
   /* Local variables.  */
   struct debug_namespace *locals;
-  /* Line number information.  */
-  struct debug_lineno *linenos;
 };
 
-/* Line number information we keep for a function.  FIXME: This
-   structure is easy to create, but can be very space inefficient.  */
+/* Line number information we keep for a compilation unit.  FIXME:
+   This structure is easy to create, but can be very space
+   inefficient.  */
 
 struct debug_lineno
 {
@@ -511,7 +514,7 @@ static boolean debug_write_type
           struct debug_type *, struct debug_name *));
 static boolean debug_write_class_type
   PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
-          struct debug_type *));
+          struct debug_type *, const char *));
 static boolean debug_write_function
   PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
           const char *, enum debug_object_linkage, struct debug_function *));
@@ -769,7 +772,6 @@ debug_record_function (handle, name, return_type, global, addr)
 
   info->current_function = f;
   info->current_block = b;
-  info->current_lineno = NULL;
 
   /* FIXME: If we could handle nested functions, this would be the
      place: we would want to use a different namespace.  */
@@ -855,7 +857,6 @@ debug_end_function (handle, addr)
 
   info->current_function = NULL;
   info->current_block = NULL;
-  info->current_lineno = NULL;
 
   return true;
 }
@@ -897,7 +898,6 @@ debug_start_block (handle, addr)
   *pb = b;
 
   info->current_block = b;
-  info->current_lineno = NULL;
 
   return true;
 }
@@ -931,7 +931,6 @@ debug_end_block (handle, addr)
   info->current_block->end = addr;
 
   info->current_block = parent;
-  info->current_lineno = NULL;
 
   return true;
 }
@@ -949,10 +948,9 @@ debug_record_line (handle, lineno, addr)
   struct debug_lineno *l;
   unsigned int i;
 
-  if (info->current_unit == NULL
-      || info->current_block == NULL)
+  if (info->current_unit == NULL)
     {
-      debug_error ("debug_record_line: no current block");
+      debug_error ("debug_record_line: no current unit");
       return false;
     }
 
@@ -971,11 +969,12 @@ debug_record_line (handle, lineno, addr)
     }
 
   /* If we get here, then either 1) there is no current_lineno
-     structure, which means this is the first line number since we got
-     to this block, 2) the current_lineno structure is for a different
-     file, or 3) the current_lineno structure is full.  Regardless, we
-     want to allocate a new debug_lineno structure, put it in the
-     right place, and make it the new current_lineno structure.  */
+     structure, which means this is the first line number in this
+     compilation unit, 2) the current_lineno structure is for a
+     different file, or 3) the current_lineno structure is full.
+     Regardless, we want to allocate a new debug_lineno structure, put
+     it in the right place, and make it the new current_lineno
+     structure.  */
 
   l = (struct debug_lineno *) xmalloc (sizeof *l);
   memset (l, 0, sizeof *l);
@@ -989,18 +988,7 @@ debug_record_line (handle, lineno, addr)
   if (info->current_lineno != NULL)
     info->current_lineno->next = l;
   else
-    {
-      struct debug_lineno **pl;
-
-      /* We may be back in this block after dealing with child blocks,
-         which means we may have some line number information for this
-         block even though current_lineno was NULL.  */
-      for (pl = &info->current_block->linenos;
-          *pl != NULL;
-          pl = &(*pl)->next)
-       ;
-      *pl = l;
-    }
+    info->current_unit->linenos = l;
 
   info->current_lineno = l;
 
@@ -2098,6 +2086,7 @@ debug_write (handle, fns, fhandle)
     {
       struct debug_file *f;
       boolean first_file;
+      struct debug_lineno *l;
 
       if (! (*fns->start_compilation_unit) (fhandle, u->files->filename))
        return false;
@@ -2124,6 +2113,20 @@ debug_write (handle, fns, fhandle)
                }
            }
        }
+
+      for (l = u->linenos; l != NULL; l = l->next)
+       {
+         unsigned int i;
+
+         for (i = 0; i < DEBUG_LINENO_COUNT; i++)
+           {
+             if (l->linenos[i] == (unsigned long) -1)
+               break;
+             if (! (*fns->lineno) (fhandle, l->file->filename, l->linenos[i],
+                                   l->addrs[i]))
+               return false;
+           }
+       }
     }
 
   return true;
@@ -2179,7 +2182,11 @@ debug_write_name (info, fns, fhandle, n)
   /*NOTREACHED*/
 }
 
-/* Write out a type.  */
+/* Write out a type.  If the type is DEBUG_KIND_NAMED or
+   DEBUG_KIND_TAGGED, then the name argument is the name for which we
+   are about to call typedef or tag.  If the type is anything else,
+   then the name argument is a tag from a DEBUG_KIND_TAGGED type which
+   points to this one.  */
 
 static boolean
 debug_write_type (info, fns, fhandle, type, name)
@@ -2190,6 +2197,7 @@ debug_write_type (info, fns, fhandle, type, name)
      struct debug_name *name;
 {
   unsigned int i;
+  const char *tag;
 
   /* If we have a name for this type, just output it.  We only output
      typedef names after they have been defined.  We output type tags
@@ -2214,6 +2222,15 @@ debug_write_type (info, fns, fhandle, type, name)
   if (name != NULL)
     name->mark = info->mark;
 
+  tag = NULL;
+  if (name != NULL
+      && type->kind != DEBUG_KIND_NAMED
+      && type->kind != DEBUG_KIND_TAGGED)
+    {
+      assert (name->kind == DEBUG_OBJECT_TAG);
+      tag = name->name;
+    }
+
   switch (type->kind)
     {
     case DEBUG_KIND_INDIRECT:
@@ -2241,7 +2258,7 @@ debug_write_type (info, fns, fhandle, type, name)
        }
       type->u.kclass->mark = info->class_mark;
 
-      if (! (*fns->start_struct_type) (fhandle,
+      if (! (*fns->start_struct_type) (fhandle, tag,
                                       type->kind == DEBUG_KIND_STRUCT,
                                       type->size))
        return false;
@@ -2262,9 +2279,9 @@ debug_write_type (info, fns, fhandle, type, name)
       return (*fns->end_struct_type) (fhandle);
     case DEBUG_KIND_CLASS:
     case DEBUG_KIND_UNION_CLASS:
-      return debug_write_class_type (info, fns, fhandle, type);
+      return debug_write_class_type (info, fns, fhandle, type, tag);
     case DEBUG_KIND_ENUM:
-      return (*fns->enum_type) (fhandle, type->u.kenum->names,
+      return (*fns->enum_type) (fhandle, tag, type->u.kenum->names,
                                type->u.kenum->values);
     case DEBUG_KIND_POINTER:
       if (! debug_write_type (info, fns, fhandle, type->u.kpointer,
@@ -2349,9 +2366,11 @@ debug_write_type (info, fns, fhandle, type, name)
        return false;
       return (*fns->volatile_type) (fhandle);
     case DEBUG_KIND_NAMED:
-    case DEBUG_KIND_TAGGED:
       return debug_write_type (info, fns, fhandle, type->u.knamed->type,
                               (struct debug_name *) NULL);
+    case DEBUG_KIND_TAGGED:
+      return debug_write_type (info, fns, fhandle, type->u.knamed->type,
+                              type->u.knamed->name);
     default:
       abort ();
       return false;
@@ -2361,11 +2380,12 @@ debug_write_type (info, fns, fhandle, type, name)
 /* Write out a class type.  */
 
 static boolean
-debug_write_class_type (info, fns, fhandle, type)
+debug_write_class_type (info, fns, fhandle, type, tag)
      struct debug_handle *info;
      const struct debug_write_fns *fns;
      PTR fhandle;
      struct debug_type *type;
+     const char *tag;
 {
   unsigned int i;
 
@@ -2385,7 +2405,7 @@ debug_write_class_type (info, fns, fhandle, type)
        return false;
     }
 
-  if (! (*fns->start_class_type) (fhandle,
+  if (! (*fns->start_class_type) (fhandle, tag,
                                  type->kind == DEBUG_KIND_CLASS,
                                  type->size,
                                  type->u.kclass->vptrbase != NULL,
@@ -2533,7 +2553,6 @@ debug_write_block (info, fns, fhandle, block)
      struct debug_block *block;
 {
   struct debug_name *n;
-  struct debug_lineno *l;
   struct debug_block *b;
 
   if (! (*fns->start_block) (fhandle, block->start))
@@ -2548,20 +2567,6 @@ debug_write_block (info, fns, fhandle, block)
        }
     }
 
-  for (l = block->linenos; l != NULL; l = l->next)
-    {
-      unsigned int i;
-
-      for (i = 0; i < DEBUG_LINENO_COUNT; i++)
-       {
-         if (l->linenos[i] == (unsigned long) -1)
-           break;
-         if (! (*fns->lineno) (fhandle, l->file->filename, l->linenos[i],
-                               l->addrs[i]))
-           return false;
-       }
-    }
-
   for (b = block->children; b != NULL; b = b->next)
     {
       if (! debug_write_block (info, fns, fhandle, b))
index 6682e47e10ef2a97db62e7fa61d9c7dbf68f8eec..0fed1535bf226bcd9c4293f2b071274da905042b 100644 (file)
@@ -1,5 +1,5 @@
 /* debug.h -- Describe generic debugging information.
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
@@ -192,9 +192,11 @@ struct debug_write_fns
   /* Push a boolean type onto the type stack, given the size.  */
   boolean (*bool_type) PARAMS ((PTR, unsigned int));
 
-  /* Push an enum type onto the type stack, given a NULL terminated
-     array of names and the associated values.  */
-  boolean (*enum_type) PARAMS ((PTR, const char **, bfd_signed_vma *));
+  /* Push an enum type onto the type stack, given the tag, a NULL
+     terminated array of names and the associated values.  If there is
+     no tag, the tag argument will be NULL.  */
+  boolean (*enum_type) PARAMS ((PTR, const char *, const char **,
+                               bfd_signed_vma *));
 
   /* Pop the top type on the type stack, and push a pointer to that
      type onto the type stack.  */
@@ -240,8 +242,8 @@ struct debug_write_fns
      method).  An argument type of -1 means that no argument in
      formation is available.  The next type on the type stack below
      the domain and the argument types is the return type of the
-     method.  All these types must be poppsed, and then the method
-     type must be pushed.  */
+     method.  All these types must be popped, and then the method type
+     must be pushed.  */
   boolean (*method_type) PARAMS ((PTR, boolean, int));
 
   /* Pop the top type off the type stack, and push a const qualified
@@ -254,10 +256,12 @@ struct debug_write_fns
 
   /* Start building a struct.  This is followed by calls to the
      struct_field function, and finished by a call to the
-     end_struct_type function.  The boolean argument is true for a
-     struct, false for a union.  The unsigned int argument is the
-     size.  */
-  boolean (*start_struct_type) PARAMS ((PTR, boolean, unsigned int));
+     end_struct_type function.  The second argument is the tag; this
+     will be NULL if there isn't one.  The boolean argument is true
+     for a struct, false for a union.  The unsigned int argument is
+     the size.  */
+  boolean (*start_struct_type) PARAMS ((PTR, const char *, boolean,
+                                       unsigned int));
 
   /* Add a field to the struct type currently being built.  The type
      of the field should be popped off the type stack.  The arguments
@@ -273,19 +277,20 @@ struct debug_write_fns
      functions: struct_field, class_static_member, class_baseclass,
      class_start_method, class_method_variant,
      class_static_method_variant, and class_end_method.  The class is
-     finished by a call to end_class_type.  The boolean argument is
-     true for a struct, false for a union.  The next argument is the
-     size.  The next argument is true if there is a virtual function
-     table; if there is, the next argument is true if the virtual
-     function table can be found in the type itself, and is false if
-     the type of the object holding the virtual function table should
-     be popped from the type stack.  */
-  boolean (*start_class_type) PARAMS ((PTR, boolean, unsigned int,
-                                      boolean, boolean));
+     finished by a call to end_class_type.  The second argument is the
+     tag; this will be NULL if there isn't one.  The boolean argument
+     is true for a struct, false for a union.  The next argument is
+     the size.  The next argument is true if there is a virtual
+     function table; if there is, the next argument is true if the
+     virtual function table can be found in the type itself, and is
+     false if the type of the object holding the virtual function
+     table should be popped from the type stack.  */
+  boolean (*start_class_type) PARAMS ((PTR, const char *, boolean,
+                                      unsigned int, boolean, boolean));
 
   /* Add a static member to the class currently being built.  The
      arguments are the field name, the physical name, and the
-     visibility.  */
+     visibility.  The type must be popped off the type stack.  */
   boolean (*class_static_member) PARAMS ((PTR, const char *, const char *,
                                          enum debug_visibility));
   
@@ -319,7 +324,8 @@ struct debug_write_fns
 
   /* Describe a static variant to the class method currently being
      built.  The arguments are the same as for class_method_variant,
-     except that the last two arguments are omitted.  */
+     except that the last two arguments are omitted.  The type of the
+     variant must be popped off the type stack.  */
   boolean (*class_static_method_variant) PARAMS ((PTR, const char *,
                                                  enum debug_visibility,
                                                  boolean, boolean));
@@ -342,7 +348,9 @@ struct debug_write_fns
   boolean (*typdef) PARAMS ((PTR, const char *));
 
   /* Pop the type stack, and declare it as a tagged struct or union or
-     enum or whatever.  */
+     enum or whatever.  The tag passed down here is redundant, since
+     was also passed when enum_type, start_struct_type, or
+     start_class_type was called.  */
   boolean (*tag) PARAMS ((PTR, const char *));
 
   /* This is called to record a named integer constant.  */
@@ -376,15 +384,15 @@ struct debug_write_fns
      starting address of the block.  */
   boolean (*start_block) PARAMS ((PTR, bfd_vma));
 
-  /* Record line number information for the current block.  */
-  boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
-
   /* Finish writing out a block.  The argument is the ending address
      of the block.  */
   boolean (*end_block) PARAMS ((PTR, bfd_vma));
 
   /* Finish writing out a function.  */
   boolean (*end_function) PARAMS ((PTR));
+
+  /* Record line number information for the current compilation unit.  */
+  boolean (*lineno) PARAMS ((PTR, const char *, unsigned long, bfd_vma));
 };
 
 /* Exported functions.  */
@@ -446,8 +454,8 @@ extern boolean debug_start_block PARAMS ((PTR, bfd_vma));
 
 extern boolean debug_end_block PARAMS ((PTR, bfd_vma));
 
-/* Associate a line number in the current source file and function
-   with a given address.  */
+/* Associate a line number in the current source file with a given
+   address.  */
 
 extern boolean debug_record_line PARAMS ((PTR, unsigned long, bfd_vma));
 
index c8c2bab9b4e5fcee661449e255dbc4b5a635a86a..c41d60cdb061f95b08f39784f931459054492020 100644 (file)
@@ -1,5 +1,5 @@
 /* prdbg.c -- Print out generic debugging information.
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>.
 
    This file is part of GNU Binutils.
@@ -78,7 +78,8 @@ static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
 static boolean pr_float_type PARAMS ((PTR, unsigned int));
 static boolean pr_complex_type PARAMS ((PTR, unsigned int));
 static boolean pr_bool_type PARAMS ((PTR, unsigned int));
-static boolean pr_enum_type PARAMS ((PTR, const char **, bfd_signed_vma *));
+static boolean pr_enum_type
+  PARAMS ((PTR, const char *, const char **, bfd_signed_vma *));
 static boolean pr_pointer_type PARAMS ((PTR));
 static boolean pr_function_type PARAMS ((PTR));
 static boolean pr_reference_type PARAMS ((PTR));
@@ -90,12 +91,13 @@ static boolean pr_offset_type PARAMS ((PTR));
 static boolean pr_method_type PARAMS ((PTR, boolean, int));
 static boolean pr_const_type PARAMS ((PTR));
 static boolean pr_volatile_type PARAMS ((PTR));
-static boolean pr_start_struct_type PARAMS ((PTR, boolean, unsigned int));
+static boolean pr_start_struct_type
+  PARAMS ((PTR, const char *, boolean, unsigned int));
 static boolean pr_struct_field
   PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
 static boolean pr_end_struct_type PARAMS ((PTR));
 static boolean pr_start_class_type
-  PARAMS ((PTR, boolean, unsigned int, boolean, boolean));
+  PARAMS ((PTR, const char *, boolean, unsigned int, boolean, boolean));
 static boolean pr_class_static_member
   PARAMS ((PTR, const char *, const char *, enum debug_visibility));
 static boolean pr_class_baseclass
@@ -121,9 +123,9 @@ static boolean pr_start_function PARAMS ((PTR, const char *, boolean));
 static boolean pr_function_parameter
   PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma));
 static boolean pr_start_block PARAMS ((PTR, bfd_vma));
-static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
 static boolean pr_end_block PARAMS ((PTR, bfd_vma));
 static boolean pr_end_function PARAMS ((PTR));
+static boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma));
 
 static const struct debug_write_fns pr_fns =
 {
@@ -168,9 +170,9 @@ static const struct debug_write_fns pr_fns =
   pr_start_function,
   pr_function_parameter,
   pr_start_block,
-  pr_lineno,
   pr_end_block,
-  pr_end_function
+  pr_end_function,
+  pr_lineno
 };
 \f
 /* Print out the generic debugging information recorded in dhandle.  */
@@ -337,7 +339,7 @@ pop_type (info)
      struct pr_handle *info;
 {
   struct pr_stack *o;
-  char *ret, *s;
+  char *ret;
 
   assert (info->stack != NULL);
 
@@ -346,10 +348,6 @@ pop_type (info)
   ret = o->type;
   free (o);
 
-  s = strchr (ret, '+');
-  if (s != NULL)
-    memmove (s, s + 2, strlen (s + 2) + 1);
-
   return ret;
 }
 
@@ -500,8 +498,9 @@ pr_bool_type (p, size)
 /* Push an enum type onto the type stack.  */
 
 static boolean
-pr_enum_type (p, names, values)
+pr_enum_type (p, tag, names, values)
      PTR p;
+     const char *tag;
      const char **names;
      bfd_signed_vma *values;
 {
@@ -509,8 +508,15 @@ pr_enum_type (p, names, values)
   unsigned int i;
   bfd_signed_vma val;
 
-  /* The + indicates where the tag goes, if there is one.  */
-  if (! push_type (info, "enum + { "))
+  if (! push_type (info, "enum "))
+    return false;
+  if (tag != NULL)
+    {
+      if (! append_type (info, tag)
+         || ! append_type (info, " "))
+       return false;
+    }
+  if (! append_type (info, "{ "))
     return false;
 
   val = 0;
@@ -824,26 +830,30 @@ pr_volatile_type (p)
 /* Start accumulating a struct type.  */
 
 static boolean
-pr_start_struct_type (p, structp, size)
+pr_start_struct_type (p, tag, structp, size)
      PTR p;
+     const char *tag;
      boolean structp;
      unsigned int size;
 {
   struct pr_handle *info = (struct pr_handle *) p;
-  const char *t;
   char ab[30];
 
   info->indent += 2;
 
-  if (structp)
-    t = "struct";
-  else
-    t = "union";
+  if (! push_type (info, structp ? "struct " : "union "))
+    return false;
+  if (tag != NULL)
+    {
+      if (! append_type (info, tag)
+         || ! append_type (info, " "))
+       return false;
+    }
   if (size != 0)
-    sprintf (ab, "%s + { /* size %u */\n", t, size);
+    sprintf (ab, "{ /* size %u */\n", size);
   else
-    sprintf (ab, "%s + {\n", t);
-  if (! push_type (info, ab))
+    strcpy (ab, "{\n");
+  if (! append_type (info, ab))
     return false;
   info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
   return indent_type (info);
@@ -977,8 +987,9 @@ pr_end_struct_type (p)
 /* Start a class type.  */
 
 static boolean
-pr_start_class_type (p, structp, size, vptr, ownvptr)
+pr_start_class_type (p, tag, structp, size, vptr, ownvptr)
      PTR p;
+     const char *tag;
      boolean structp;
      unsigned int size;
      boolean vptr;
@@ -996,8 +1007,15 @@ pr_start_class_type (p, structp, size, vptr, ownvptr)
        return false;
     }
 
-  if (! push_type (info, structp ? "class" : "union class")
-      || ! append_type (info, " + {"))
+  if (! push_type (info, structp ? "class " : "union class "))
+    return false;
+  if (tag != NULL)
+    {
+      if (! append_type (info, tag)
+         || ! append_type (info, " "))
+       return false;
+    }
+  if (! append_type (info, "{"))
     return false;
   if (size != 0 || vptr || ownvptr)
     {
@@ -1079,7 +1097,7 @@ pr_class_baseclass (p, bitpos, virtual, visibility)
   char *t;
   const char *prefix;
   char ab[20];
-  char *s, *n;
+  char *s, *l, *n;
 
   assert (info->stack != NULL && info->stack->next != NULL);
 
@@ -1134,27 +1152,19 @@ pr_class_baseclass (p, bitpos, virtual, visibility)
 
   /* Now the top of the stack is something like "public A / * bitpos
      10 * /".  The next element on the stack is something like "class
-     + { / * size 8 * /\n...".  We want to substitute the top of the
-     stack in after the +.  */
-  s = strchr (info->stack->next->type, '+');
+     xx { / * size 8 * /\n...".  We want to substitute the top of the
+     stack in before the {.  */
+  s = strchr (info->stack->next->type, '{');
   assert (s != NULL);
+  --s;
 
-  if (s[2] != ':')
-    {
-      ++s;
-      assert (s[1] == '{');
-      if (! prepend_type (info, " : "))
-       return false;
-    }
-  else
-    {
-      /* We already have a baseclass.  Append this one after a comma.  */
-      s = strchr (s, '{');
-      assert (s != NULL);
-      --s;
-      if (! prepend_type (info, ", "))
-       return false;
-    }
+  /* If there is already a ':', then we already have a baseclass, and
+     we must append this one after a comma.  */
+  for (l = info->stack->next->type; l != s; l++)
+    if (*l == ':')
+      break;
+  if (! prepend_type (info, l == s ? " : " : ", "))
+    return false;
 
   t = pop_type (info);
   if (t == NULL)
@@ -1426,31 +1436,17 @@ pr_typdef (p, name)
   return true;
 }
 
-/* Output a tag.  */
+/* Output a tag.  The tag should already be in the string on the
+   stack, so all we have to do here is print it out.  */
 
+/*ARGSUSED*/
 static boolean
 pr_tag (p, name)
      PTR p;
      const char *name;
 {
   struct pr_handle *info = (struct pr_handle *) p;
-  char *t, *s, *n;
-
-  assert (info->stack != NULL);
-
-  t = info->stack->type;
-
-  s = strchr (t, '+');
-  assert (s != NULL);
-
-  n = (char *) xmalloc (strlen (t) + strlen (name));
-
-  memcpy (n, t, s - t);
-  strcpy (n + (s - t), name);
-  strcat (n, s + 1);
-
-  free (t);
-  info->stack->type = n;
+  char *t;
 
   t = pop_type (info);
   if (t == NULL)
@@ -1459,7 +1455,7 @@ pr_tag (p, name)
   indent (info);
   fprintf (info->f, "%s;\n", t);
 
-  free (n);
+  free (t);
 
   return true;
 }