🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gdb.bug
Article #9964

Gdb patches for g++ users

#9964
From: bothner
Date: Mon, 13 Aug 1990 18:58
1465 lines
41791 bytes
Here are the promised gdb patches which fix a number of g++-related
problems. The patches are relative to Tiemann's recently-announced
version 3.6- from labrea.

The major changes provide better support for multiple inheritance
(though I haven't fixed all the problems). There are a number of other
changes. E.g., before, practically *all* output would be demangled
(including source code!). Now it only demangles what I think is reasonable.
I also changed gdb's output in various places to what I think is
more reasonable. (E.g. printing a struct should not print static
members. Less verboseness in general.)

The changes work best with my just-proposed change to g++
(global function names in debugger stabs should not be mangled,
only the assembler-level name), but even without that change,
I don't think these patches should harm anything.

	--Per Bothner
bothner@cs.wisc.edu Computer Sciences Dept, U. of Wisconsin-Madison

breakpoint.c:
  In breakpoint_1, use new print_address_symbolic instead
  of find_pc_partial_function. (This forces use of assembler-level
  addresses, and avoids misleading non-mamgled source-level names.)
cplus-dem.c:
  Generalize ansi argument such that -1 means skip arglist totally.
  Removed global variable print_ansi_qualifiers (which made
  code non-reentrant), in favor of extra explicit arguments
  to internal routines.
printcmd.c:
  Add new helper function print_address_symbolic.
  Use find_pc_misc_function instead of find_pc_partial_function
  (since we want assembler-level symbols here).
stack.c:
  Print unknown function as just "f (...)", not "f (...) (...)".
  Use new fputs_demangled explicitly.
symtab.c:
  Fixed a typing violation (problem: value.h cannot be imported
  without renaming many variable in this file).
  lookup_symbol: If no matching misc_func, look for a C++-mangled name.
  decode_line_1: Moved forward some never-reached code.
  Made decode_line_2 skip function prologues correctly.
utils.c:
  fputs_filtered should not demangle by default.
  Add new fputs_demangled to demangle on demand..
valops.c:
  Change value_struct_elt to use value_primitive_field (using recursive
  utility function search_struct_field). This allows foo.bar to work
  for multiple inheritance (so far only for data fields).
  Change check_field in the same way (recursive helper function
  to support multiple inheritance).
  (Note: there are more of these problems that I haven't fixed.
  Any code that says TYPE_BASECLASS (t, 1) is probably wrong.)
  value_of_this: 'this' symbol name is now just "this", note "$this".
valprint.c:
  Don't print static members.
  Avoid printing "members of <type>" if there are none.
  Simplified type_print_derivation_info by merging duplicate code.
  Remove useless blank lines in type_print_base (ptype command).
value.h:
  Added declaration of new routine value_primitive_field.
values.c:
  Added value_primitive_field which is generalized version of
  value_field that can handle multiple inheritance (non-zero offsets etc).
  Re-implemented value_field to call value_primitive_field.
diff -c old/breakpoint.c new/breakpoint.c
*** old/breakpoint.c	Sat Jun 30 08:03:19 1990
- --- new/breakpoint.c	Sat Aug 11 21:10:59 1990
***************
*** 436,442 ****
    ALL_BREAKPOINTS (b)
      if (bnum == -1 || bnum == b->number)
        {
! 	printf_filtered ("#%-3d %c  0x%08x ", b->number,
  		"nyod"[(int) b->enable],
  		b->address);
  	last_addr = b->address;
- --- 436,442 ----
    ALL_BREAKPOINTS (b)
      if (bnum == -1 || bnum == b->number)
        {
! 	printf_filtered ("#%-3d %c  0x%08x", b->number,
  		"nyod"[(int) b->enable],
  		b->address);
  	last_addr = b->address;
***************
*** 444,467 ****
  	  {
  	    sym = find_pc_function (b->address);
  	    if (sym)
- - 	      printf_filtered (" in %s (%s line %d)", SYMBOL_NAME (sym),
- - 			       b->symtab->filename, b->line_number);
- - 	    else
- - 	      printf_filtered ("%s line %d", b->symtab->filename, b->line_number);
- - 	  }
- - 	else
- - 	  {
- - 	    char *name;
- - 	    int addr;
- - 
- - 	    if (find_pc_partial_function (b->address, &name, &addr))
  	      {
! 		if (b->address - addr)
! 		  printf_filtered ("<%s+%d>", name, b->address - addr);
! 		else
! 		  printf_filtered ("<%s>", name);
  	      }
  	  }
  	      
  	printf_filtered ("\n");
  
- --- 444,460 ----
  	  {
  	    sym = find_pc_function (b->address);
  	    if (sym)
  	      {
! 		fputs_filtered (" in ", stdout);
! 		fputs_demangled (SYMBOL_NAME (sym), stdout, 1);
! 		fputs_filtered (" (", stdout);
  	      }
+ 	    fputs_filtered (b->symtab->filename, stdout);
+ 	    printf_filtered (" line %d", b->line_number);
+ 	    if (sym) fputs_filtered(")", stdout);
  	  }
+ 	else
+ 	      print_address_symbolic (b->address, stdout);
  	      
  	printf_filtered ("\n");
  
diff -c old/cplus-dem.c new/cplus-dem.c
*** old/cplus-dem.c	Tue Jun 26 08:23:00 1990
- --- new/cplus-dem.c	Sat Aug 11 15:53:51 1990
***************
*** 23,29 ****
  
  /* This file exports one function
  
!    char *cplus_demangle (const char *name, int ansi)
     
     If NAME is a mangled function name produced by GNU C++, then
     a pointer to a malloced string giving a C++ representation
- --- 23,29 ----
  
  /* This file exports one function
  
!    char *cplus_demangle (const char *name, int mode)
     
     If NAME is a mangled function name produced by GNU C++, then
     a pointer to a malloced string giving a C++ representation
***************
*** 31,39 ****
     It is the caller's responsibility to free the string which
     is returned.
  
!    If ANSI is non-zero, then ANSI qualifiers such as `const',
     `void', and the ellipses operator `...' are output.  Otherwise
     they are not.
  
     For example,
     
- --- 31,40 ----
     It is the caller's responsibility to free the string which
     is returned.
  
!    If MODE > 0, then ANSI qualifiers such as `const',
     `void', and the ellipses operator `...' are output.  Otherwise
     they are not.
+    if MODE >= 0, parameter are emiitted; otherwise not.
  
     For example,
     
***************
*** 68,74 ****
  #endif
  
  #ifdef __STDC__
! extern char *cplus_demangle (const char *type, int ansi);
  #else
  extern char *cplus_demangle ();
  #endif
- --- 69,75 ----
  #endif
  
  #ifdef __STDC__
! extern char *cplus_demangle (const char *type, int mode);
  #else
  extern char *cplus_demangle ();
  #endif
***************
*** 148,158 ****
  #endif
  static void string_prependn (string *p, const char *s, int n);
  static int get_count (const char **type, int *count);
! static int do_args (const char **type, string *decl);
! static int do_type (const char **type, string *result);
! static int do_arg (const char **type, string *result);
! static int do_args (const char **type, string *decl);
! static void munge_function_name (string *name);
  static void remember_type (const char *type, int len);
  #else
  static void string_need ();
- --- 149,158 ----
  #endif
  static void string_prependn (string *p, const char *s, int n);
  static int get_count (const char **type, int *count);
! static int do_args (const char **type, string *decl, int arg_mode);
! static int do_type (const char **type, string *result, int arg_mode);
! static int do_arg (const char **type, string *result, int arg_mode);
! static void munge_function_name (string *name, int arg_mode);
  static void remember_type (const char *type, int len);
  #else
  static void string_need ();
***************
*** 175,186 ****
  static void remember_type ();
  #endif
  
- - static int print_ansi_qualifiers;
- - 
  char *
! cplus_demangle (type, ansi)
       const char *type;
!      int ansi;
  {
    string decl;
    int n;
- --- 175,184 ----
  static void remember_type ();
  #endif
  
  char *
! cplus_demangle (type, arg_mode)
       const char *type;
!      int arg_mode;
  {
    string decl;
    int n;
***************
*** 193,199 ****
    const char *premangle;
  #endif
  
!   print_ansi_qualifiers = ansi;
  
    if (type == NULL || *type == '\0')
      return NULL;
- --- 191,198 ----
    const char *premangle;
  #endif
  
! #define print_ansi_qualifiers (arg_mode > 0)
! #define print_arg_types (arg_mode >= 0)
  
    if (type == NULL || *type == '\0')
      return NULL;
***************
*** 253,259 ****
    else
      {
        string_appendn (&decl, type, p - type);
!       munge_function_name (&decl);
      }
    p += 2;
  
- --- 252,258 ----
    else
      {
        string_appendn (&decl, type, p - type);
!       munge_function_name (&decl, arg_mode);
      }
    p += 2;
  
***************
*** 310,322 ****
  #ifndef LONGERNAMES
        remember_type (premangle, p - premangle);
  #endif
!       success = do_args (&p, &decl);
!       if (const_flag)
  	string_append (&decl, " const");
        break;
      case 'F':
        p += 1;
!       success = do_args (&p, &decl);
        break;
      }
  
- --- 309,321 ----
  #ifndef LONGERNAMES
        remember_type (premangle, p - premangle);
  #endif
!       success = do_args (&p, &decl, arg_mode);
!       if (const_flag && print_arg_types)
  	string_append (&decl, " const");
        break;
      case 'F':
        p += 1;
!       success = do_args (&p, &decl, arg_mode);
        break;
      }
  
***************
*** 376,384 ****
  /* result will be initialised here; it will be freed on failure */
  
  static int
! do_type (type, result)
       const char **type;
       string *result;
  {
    int n;
    int done;
- --- 375,384 ----
  /* result will be initialised here; it will be freed on failure */
  
  static int
! do_type (type, result, arg_mode)
       const char **type;
       string *result;
+      int arg_mode;
  {
    int n;
    int done;
***************
*** 425,431 ****
  	      string_prepend (&decl, "(");
  	      string_append (&decl, ")");
  	    }
! 	  if (!do_args (type, &decl) || **type != '_')
  	    success = 0;
  	  else
  	    *type += 1;
- --- 425,431 ----
  	      string_prepend (&decl, "(");
  	      string_append (&decl, ")");
  	    }
! 	  if (!do_args (type, &decl, arg_mode) || **type != '_')
  	    success = 0;
  	  else
  	    *type += 1;
***************
*** 480,486 ****
  		    break;
  		  }
  	      }
! 	    if ((member && !do_args (type, &decl)) || **type != '_')
  	      {
  		success = 0;
  		break;
- --- 480,486 ----
  		    break;
  		  }
  	      }
! 	    if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
  	      {
  		success = 0;
  		break;
***************
*** 502,508 ****
  		  string_append (&decl, " ");
  		else
  		  non_empty = 1;
! 		string_append (&decl, "volatilep");
  	      }
  	    break;
  	  }
- --- 502,508 ----
  		  string_append (&decl, " ");
  		else
  		  non_empty = 1;
! 		string_append (&decl, "volatile");
  	      }
  	    break;
  	  }
***************
*** 691,703 ****
  /* `result' will be initialised in do_type; it will be freed on failure */
  
  static int
! do_arg (type, result)
       const char **type;
       string *result;
  {
    const char *start = *type;
  
!   if (!do_type (type, result))
      return 0;
    remember_type (start, *type - start);
    return 1;
- --- 691,704 ----
  /* `result' will be initialised in do_type; it will be freed on failure */
  
  static int
! do_arg (type, result, arg_mode)
       const char **type;
       string *result;
+      int arg_mode;
  {
    const char *start = *type;
  
!   if (!do_type (type, result, arg_mode))
      return 0;
    remember_type (start, *type - start);
    return 1;
***************
*** 733,746 ****
     it won't be freed on failure */
  
  static int
! do_args (type, decl)
       const char **type;
       string *decl;
  {
    string arg;
    int need_comma = 0;
  
!   string_append (decl, "(");
  
    while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
      {
- --- 734,749 ----
     it won't be freed on failure */
  
  static int
! do_args (type, decl, arg_mode)
       const char **type;
       string *decl;
+      int arg_mode;
  {
    string arg;
    int need_comma = 0;
  
!   if (print_arg_types)
!     string_append (decl, "(");
  
    while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
      {
***************
*** 754,764 ****
  	  while (--r >= 0)
  	    {
  	      const char *tem = typevec[t];
! 	      if (need_comma)
  		string_append (decl, ", ");
! 	      if (!do_arg (&tem, &arg))
  		return 0;
! 	      string_appends (decl, &arg);
  	      string_delete (&arg);
  	      need_comma = 1;
  	    }
- --- 757,768 ----
  	  while (--r >= 0)
  	    {
  	      const char *tem = typevec[t];
! 	      if (need_comma && print_arg_types)
  		string_append (decl, ", ");
! 	      if (!do_arg (&tem, &arg, arg_mode))
  		return 0;
! 	      if (print_arg_types)
! 	        string_appends (decl, &arg);
  	      string_delete (&arg);
  	      need_comma = 1;
  	    }
***************
*** 765,775 ****
  	}
        else
  	{
! 	  if (need_comma)
  	    string_append (decl, ", ");
! 	  if (!do_arg (type, &arg))
  	    return 0;
! 	  string_appends (decl, &arg);
  	  string_delete (&arg);
  	  need_comma = 1;
  	}
- --- 769,780 ----
  	}
        else
  	{
! 	  if (need_comma && print_arg_types)
  	    string_append (decl, ", ");
! 	  if (!do_arg (type, &arg, arg_mode))
  	    return 0;
! 	  if (print_arg_types)
! 	    string_appends (decl, &arg);
  	  string_delete (&arg);
  	  need_comma = 1;
  	}
***************
*** 780,796 ****
    else if (**type == 'e')
      {
        *type += 1;
!       if (need_comma)
! 	string_append (decl, ",");
!       string_append (decl, "...");
      }
  
!   string_append (decl, ")");
    return 1;
  }
  
  static void
! munge_function_name (name)
       string *name;
  {
    if (!string_empty (name) && name->p - name->b >= 3 
- --- 785,805 ----
    else if (**type == 'e')
      {
        *type += 1;
!       if (print_arg_types)
! 	{
! 	  if (need_comma)
! 	    string_append (decl, ",");
! 	  string_append (decl, "...");
!         }
      }
  
!   if (print_arg_types)
!     string_append (decl, ")");
    return 1;
  }
  
  static void
! munge_function_name (name, arg_mode)
       string *name;
  {
    if (!string_empty (name) && name->p - name->b >= 3 
***************
*** 838,844 ****
        /* type conversion operator */
        string type;
        const char *tem = name->b + 5;
!       if (do_type (&tem, &type))
  	{
  	  string_clear (name);
  	  string_append (name, "operator ");
- --- 847,853 ----
        /* type conversion operator */
        string type;
        const char *tem = name->b + 5;
!       if (do_type (&tem, &type, arg_mode))
  	{
  	  string_clear (name);
  	  string_append (name, "operator ");
diff -c old/printcmd.c new/printcmd.c
*** old/printcmd.c	Fri Jan 19 21:32:40 1990
- --- new/printcmd.c	Sat Aug 11 21:24:03 1990
***************
*** 396,428 ****
  		   value_from_long (builtin_type_int, (LONGEST) addr));
  }
  
! /* Print address ADDR symbolically on STREAM.
!    First print it as a number.  Then perhaps print
!    <SYMBOL + OFFSET> after the number.  */
  
  void
! print_address (addr, stream)
       CORE_ADDR addr;
       FILE *stream;
  {
- -   register int i = 0;
    register char *format;
- -   register struct symbol *fs;
- -   char *name;
    int name_location;
  
- -   i = find_pc_partial_function (addr, &name, &name_location);
- - 
    /* If nothing comes out, don't print anything symbolic.  */
!   
!   if (i == 0)
!     format = "0x%x";
!   else if (addr - name_location)
!     format = "0x%x <%s+%d>";
    else
!     format = "0x%x <%s>";
  
!   fprintf_filtered (stream, format, addr, name, addr - name_location);
  }
  
  /* Examine data at address ADDR in format FMT.
- --- 396,436 ----
  		   value_from_long (builtin_type_int, (LONGEST) addr));
  }
  
! /* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM. */
  
  void
! print_address_symbolic (addr, stream)
       CORE_ADDR addr;
       FILE *stream;
  {
    register char *format;
    int name_location;
+   register int i = find_pc_misc_function (addr);
  
    /* If nothing comes out, don't print anything symbolic.  */
!   if (i < 0) return;
!   name_location = misc_function_vector[i].address;
! 
!   if (addr - name_location)
!     format = " <%s+%d>";
    else
!     format = " <%s>";
  
!   fprintf_filtered (stream, format,
! 		    misc_function_vector[i].name, addr - name_location);
! }
! 
! /* Print address ADDR symbolically on STREAM.
!    First print it as a number.  Then perhaps print
!    <SYMBOL + OFFSET> after the number.  */
! 
! void
! print_address (addr, stream)
!      CORE_ADDR addr;
!      FILE *stream;
! {
!   fprintf_filtered (stream, "0x%x", addr);
!   print_address_symbolic (addr, stream);
  }
  
  /* Examine data at address ADDR in format FMT.
diff -c old/stack.c new/stack.c
*** old/stack.c	Tue Jun  5 09:19:13 1990
- --- new/stack.c	Sun Aug 12 20:18:27 1990
***************
*** 99,105 ****
        printf_filtered ("#%-2d ", level);
        printf_filtered ("0x%x in ", fi->pc);
  
!       printf_filtered ("%s (...) (...)\n", fname);
        
        return;
      }
- --- 99,106 ----
        printf_filtered ("#%-2d ", level);
        printf_filtered ("0x%x in ", fi->pc);
  
!       fputs_demangled(fname, stdout, -1);
!       fputs_filtered(" (...)\n", stdout);
        
        return;
      }
***************
*** 152,158 ****
  	printf ("#%-2d ", 0);
        if (fi->pc != sal.pc || !sal.symtab)
  	printf_filtered ("0x%x in ", fi->pc);
!       printf_filtered ("%s (", funname ? funname : "??");
        if (args)
  	{
  	  FRAME_NUM_ARGS (numargs, fi);
- --- 153,160 ----
  	printf ("#%-2d ", 0);
        if (fi->pc != sal.pc || !sal.symtab)
  	printf_filtered ("0x%x in ", fi->pc);
!       fputs_demangled(funname ? funname : "??", stdout, -1);
!       printf_filtered(" (");
        if (args)
  	{
  	  FRAME_NUM_ARGS (numargs, fi);
***************
*** 571,577 ****
  	  struct symtab_and_line sal;
  	  sal = find_pc_line (SYMBOL_VALUE (sym), 0);
  	  values_printed = 1;
! 	  fputs_filtered (SYMBOL_NAME (sym), stream);
  	  fprintf_filtered (stream, " 0x%x in file %s, line %d\n",
  			    SYMBOL_VALUE (sym), sal.symtab->filename, sal.line);
  	  fflush (stream);
- --- 573,579 ----
  	  struct symtab_and_line sal;
  	  sal = find_pc_line (SYMBOL_VALUE (sym), 0);
  	  values_printed = 1;
! 	  fputs_demangled (SYMBOL_NAME (sym), stream, 1);
  	  fprintf_filtered (stream, " 0x%x in file %s, line %d\n",
  			    SYMBOL_VALUE (sym), sal.symtab->filename, sal.line);
  	  fflush (stream);
diff -c old/symtab.c new/symtab.c
*** old/symtab.c	Wed Jul  4 07:27:27 1990
- --- new/symtab.c	Mon Aug 13 12:30:07 1990
***************
*** 26,31 ****
- --- 26,33 ----
  #include <assert.h>
  
  char *index ();
+ extern char *cplus_demangle ();
+ extern struct value * value_of_this ();
  
  /* Allocate an obstack to hold objects that should be freed
     when we load a new symbol table.
***************
*** 934,940 ****
       check to see if NAME is a field of `this'. */
    if (is_a_field_of_this)
      {
!       int v = (int) value_of_this (0);
        
        *is_a_field_of_this = 0;
        if (v && check_field (v, name))
- --- 936,942 ----
       check to see if NAME is a field of `this'. */
    if (is_a_field_of_this)
      {
!       struct value *v = value_of_this (0);
        
        *is_a_field_of_this = 0;
        if (v && check_field (v, name))
***************
*** 967,972 ****
- --- 969,994 ----
      {
        int index = lookup_misc_func (name);
  
+       if (index == -1)
+ 	{ /* Look for a mangled C++ name for NAME. */
+ 	  int name_len = strlen (name);
+ 	  for (index = misc_function_count; --index >= 0; )
+ 	      /* Assume orginal name is prefix of mangled name. */
+ 	      if (!strncmp (misc_function_vector[index].name, name, name_len))
+ 		{
+ 		  char *demangled =
+ 		      cplus_demangle(misc_function_vector[index].name, -1);
+ 		  if (demangled != NULL)
+ 		    {
+ 		      int cond = strcmp (demangled, name);
+ 		      free (demangled);
+ 		      if (!cond)
+ 			  break;
+ 		    }
+ 	        }
+ 	  /* Loop terminates on no match with index == -1. */
+         }
+ 
        if (index != -1)
  	{
  	  ps = find_pc_psymtab (misc_function_vector[index].address);
***************
*** 1861,1869 ****
    if (sym)
      error ("%s is not a function.", copy);
  
!   if ((i = lookup_misc_func (copy)) < 0)
!     error ("Function %s not defined.", copy);
!   else
      {
        value.symtab = 0;
        value.line = 0;
- --- 1883,1892 ----
    if (sym)
      error ("%s is not a function.", copy);
  
!   if (symtab_list == 0 && partial_symtab_list == 0)
!     error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
! 
!   if ((i = lookup_misc_func (copy)) >= 0)
      {
        value.symtab = 0;
        value.line = 0;
***************
*** 1876,1883 ****
        return values;
      }
  
- -   if (symtab_list == 0 && partial_symtab_list == 0)
- -     error ("No symbol table is loaded.  Use the \"symbol-file\" command.");
    error ("Function %s not defined.", copy);
  }
  
- --- 1899,1904 ----
***************
*** 1929,1934 ****
- --- 1950,1956 ----
  	  if (funfirstline)
  	    SKIP_PROLOGUE (pc);
  	  values.sals[i] = find_pc_line (pc, 0);
+ 	  values.sals[i].pc = (values.sals[i].end && values.sals[i].pc != pc) ? values.sals[i].end : pc;
  	  printf("[%d] file:%s; line number:%d\n",
  		 (i+2), values.sals[i].symtab->filename, values.sals[i].line);
  	}
diff -c old/utils.c new/utils.c
*** old/utils.c	Tue Jun 26 08:20:14 1990
- --- new/utils.c	Sat Aug 11 15:16:23 1990
***************
*** 582,656 ****
  
     Note that a longjmp to top level may occur in this routine
     (since prompt_for_continue may do so) so this routine should not be
!    called when cleanups are not in place.
  
- -    fputs_filtered demangles g++ names.*/
- - 
- - void _fputs_filtered (); /* forward decl. */
- - 
- - 
  void
  fputs_filtered (linebuffer, stream)
       char *linebuffer;
       FILE *stream;
  {
- - #ifdef __STDC__
- -   extern char *cplus_demangle (const char *, int);
- - #else
- -   extern char *cplus_demangle ();
- - #endif
- - #define SYMBOL_MAX 1024
- - 
- - #define SYMBOL_CHAR(c) (isascii(c) && (isalnum(c) || (c) == '_' || (c) == '$'))
- - 
- -   char buf[SYMBOL_MAX+1];
- -   char *p;
- - 
- -   if (linebuffer == NULL)
- -     return;
- - 
- -   p = linebuffer;
- - 
- -   while ( *p != (char) 0 ) {
- -     int i = 0;
- - 
- -     /* collect non-interesting characters into buf */
- -     while ( *p != (char) 0 && !SYMBOL_CHAR(*p) ) {
- -       buf[i++] = *p;
- -       p++;
- -     }
- -     if (i > 0) {
- -       /* output the non-interesting characters without demangling */
- -       buf[i] = (char) 0;
- -       _fputs_filtered(buf, stream);
- -       i = 0;  /* reset buf */
- -     }
- - 
- -     /* and now the interesting characters */
- -     while (i < SYMBOL_MAX && *p != (char) 0 && SYMBOL_CHAR(*p) ) {
- -       buf[i++] = *p;
- -       p++;
- -     }
- -     buf[i] = (char) 0;
- -     if (i > 0) {
- -       char * result;
- -       
- -       if ( (result = cplus_demangle(buf, 1)) != NULL ) {
- - 	_fputs_filtered(result, stream);
- - 	free(result);
- -       }
- -       else {
- - 	_fputs_filtered(buf, stream);
- -       }
- -     }
- -   }
- - }
- - 
- - void
- - _fputs_filtered (linebuffer, stream)
- -      char *linebuffer;
- -      FILE *stream;
- - {
    char *lineptr;
  
    if (linebuffer == 0)
- --- 582,594 ----
  
     Note that a longjmp to top level may occur in this routine
     (since prompt_for_continue may do so) so this routine should not be
!    called when cleanups are not in place. */
  
  void
  fputs_filtered (linebuffer, stream)
       char *linebuffer;
       FILE *stream;
  {
    char *lineptr;
  
    if (linebuffer == 0)
***************
*** 711,716 ****
- --- 649,714 ----
  	  chars_printed = 0;
  	}
      }
+ }
+ 
+ /* fputs_demangled is a variant of fputs_filtered that
+    demangles g++ names.*/
+ 
+ void
+ fputs_demangled (linebuffer, stream, arg_mode)
+      char *linebuffer;
+      FILE *stream;
+ {
+ #ifdef __STDC__
+   extern char *cplus_demangle (const char *, int);
+ #else
+   extern char *cplus_demangle ();
+ #endif
+ #define SYMBOL_MAX 1024
+ 
+ #define SYMBOL_CHAR(c) (isascii(c) && (isalnum(c) || (c) == '_' || (c) == '$'))
+ 
+   char buf[SYMBOL_MAX+1];
+   char *p;
+ 
+   if (linebuffer == NULL)
+     return;
+ 
+   p = linebuffer;
+ 
+   while ( *p != (char) 0 ) {
+     int i = 0;
+ 
+     /* collect non-interesting characters into buf */
+     while ( *p != (char) 0 && !SYMBOL_CHAR(*p) ) {
+       buf[i++] = *p;
+       p++;
+     }
+     if (i > 0) {
+       /* output the non-interesting characters without demangling */
+       buf[i] = (char) 0;
+       fputs_filtered(buf, stream);
+       i = 0;  /* reset buf */
+     }
+ 
+     /* and now the interesting characters */
+     while (i < SYMBOL_MAX && *p != (char) 0 && SYMBOL_CHAR(*p) ) {
+       buf[i++] = *p;
+       p++;
+     }
+     buf[i] = (char) 0;
+     if (i > 0) {
+       char * result;
+       
+       if ( (result = cplus_demangle(buf, arg_mode)) != NULL ) {
+ 	fputs_filtered(result, stream);
+ 	free(result);
+       }
+       else {
+ 	fputs_filtered(buf, stream);
+       }
+     }
+   }
  }
  
  /* Print ARG1, ARG2, and ARG3 on stdout using format FORMAT.  If this
diff -c old/valops.c new/valops.c
*** old/valops.c	Wed Jun 27 01:46:50 1990
- --- new/valops.c	Sun Aug 12 23:08:17 1990
***************
*** 768,773 ****
- --- 768,807 ----
    return val;
  }
  
+ /* Helper function used by value_struct_elt to recurse through baseclasses.
+    Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,
+    and treat the result as having type TYPE.
+    If found, return value, else return NULL. */
+ 
+ static value search_struct_field (name, arg1, offset, type)
+      char *name;
+      register value arg1;
+      int offset;
+      register struct type *type;
+ {
+   int i;
+   check_stub_type (type);
+   for (i = TYPE_NFIELDS (type) - 1; i >= 0; i--)
+     {
+       char *t_field_name = TYPE_FIELD_NAME (type, i);
+       if (t_field_name && !strcmp (t_field_name, name))
+ 	  return TYPE_FIELD_STATIC (type, i)
+ 	      ? value_static_field (type, name, i)
+ 	      : value_primitive_field (arg1, offset, i, type);
+     }
+ 
+   for (i = TYPE_N_BASECLASSES (type); --i >= 0; )
+     {
+       /* Needs work for virtual base classes */
+       value v = search_struct_field (name,
+ 				     arg1,
+ 				     offset + TYPE_FIELD_BITPOS (type, i) / 8,
+ 				     TYPE_FIELD_TYPE (type, i));
+       if (v) return v;
+     }
+   return NULL;
+ }
+ 
  /* Given ARG1, a value of type (pointer to a)* structure/union,
     extract the component named NAME from the ultimate target structure/union
     and return it as a value with its appropriate type.
***************
*** 827,857 ****
  
        /* Try as a variable first, because if we succeed, there
  	 is less work to be done.  */
!       while (t)
! 	{
! 	  check_stub_type (t);
  
- - 	  for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
- - 	    {
- - 	      char *t_field_name = TYPE_FIELD_NAME (t, i);
- - 	      if (t_field_name && !strcmp (t_field_name, name))
- - 		{
- - 		  found = 1;
- - 		  break;
- - 		}
- - 	    }
- - 
- - 	  if (i >= 0)
- - 	    return TYPE_FIELD_STATIC (t, i)
- - 	      ? value_static_field (t, name, i) : value_field (arg1, i);
- - 
- - 	  if (TYPE_N_BASECLASSES (t) == 0)
- - 	    break;
- - 
- - 	  t = TYPE_BASECLASS (t, 1);
- - 	  VALUE_TYPE (arg1) = t; /* side effect! */
- - 	}
- - 
        /* C++: If it was not found as a data field, then try to
           return it as a pointer to a method.  */
        t = baseclass;
- --- 861,869 ----
  
        /* Try as a variable first, because if we succeed, there
  	 is less work to be done.  */
!       value v = search_struct_field (name, arg1, 0, t);
!       if (v) return v;
  
        /* C++: If it was not found as a data field, then try to
           return it as a pointer to a method.  */
        t = baseclass;
***************
*** 998,1003 ****
- --- 1010,1055 ----
    return 0;
  }
  
+ /* Helper function for check_field: Given TYPE, a structure/union,
+    return 1 if the component named NAME from the ultimate
+    target structure/union is defined, otherwise, return 0. */
+ 
+ static int
+ check_field_in (type, name)
+      register struct type *type;
+      char *name;
+ {
+   register int i;
+ 
+   for (i = TYPE_NFIELDS (type); --i >= 0; )
+     {
+       char *t_field_name = TYPE_FIELD_NAME (type, i);
+       if (t_field_name && !strcmp (t_field_name, name))
+ 	return 1;
+     }
+ 
+   /* C++: If it was not found as a data field, then try to
+      return it as a pointer to a method.  */
+ 
+   /* Destructors are a special case.  */
+   if (destructor_name_p (name, type))
+     return 1;
+ 
+   for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+     {
+       if (!strcmp (TYPE_FN_FIELDLIST_NAME (type, i), name))
+ 	return 1;
+     }
+ 
+   for (i = TYPE_N_BASECLASSES (type); i > 0; i--)
+     {
+       if (check_field_in (TYPE_BASECLASS (type, i), name))
+ 	return 1;
+     }
+       
+   return 0;
+ }
+ 
  /* C++: Given ARG1, a value of type (pointer to a)* structure/union,
     return 1 if the component named NAME from the ultimate
     target structure/union is defined, otherwise, return 0.  */
***************
*** 1008,1018 ****
       char *name;
  {
    register struct type *t;
- -   register int i;
- -   int found = 0;
- - 
- -   struct type *baseclass;
- - 
    COERCE_ARRAY (arg1);
  
    t = VALUE_TYPE (arg1);
- --- 1060,1065 ----
***************
*** 1029,1075 ****
        && TYPE_CODE (t) != TYPE_CODE_UNION)
      error ("Internal error: `this' is not an aggregate");
  
!   baseclass = t;
! 
!   while (t)
!     {
!       for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
! 	{
! 	  char *t_field_name = TYPE_FIELD_NAME (t, i);
! 	  if (t_field_name && !strcmp (t_field_name, name))
! 	    {
! 	      return 1;
! 	    }
! 	}
!       if (TYPE_N_BASECLASSES (t) == 0)
! 	break;
! 
!       t = TYPE_BASECLASS (t, 1);
!     }
! 
!   /* C++: If it was not found as a data field, then try to
!      return it as a pointer to a method.  */
!   t = baseclass;
!   VALUE_TYPE (arg1) = t;	/* side effect! */
! 
!   /* Destructors are a special case.  */
!   if (destructor_name_p (name, t))
!     return 1;
! 
!   while (t)
!     {
!       for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
! 	{
! 	  if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
! 	    return 1;
! 	}
! 
!       if (TYPE_N_BASECLASSES (t) == 0)
! 	break;
! 
!       t = TYPE_BASECLASS (t, 1);
!     }
!   return 0;
  }
  
  /* C++: Given an aggregate type DOMAIN, and a member name NAME,
- --- 1076,1082 ----
        && TYPE_CODE (t) != TYPE_CODE_UNION)
      error ("Internal error: `this' is not an aggregate");
  
!   return check_field_in (t, name);
  }
  
  /* C++: Given an aggregate type DOMAIN, and a member name NAME,
***************
*** 1251,1257 ****
      else return 0;
  
    sym = BLOCK_SYM (b, 0);
!   if (strncmp ("$this", SYMBOL_NAME (sym), 5))
      if (complain)
        error ("current stack frame not in method");
      else return 0;
- --- 1258,1264 ----
      else return 0;
  
    sym = BLOCK_SYM (b, 0);
!   if (strcmp ("this", SYMBOL_NAME (sym)))
      if (complain)
        error ("current stack frame not in method");
      else return 0;
diff -c old/valprint.c new/valprint.c
*** old/valprint.c	Wed Jun 27 01:46:50 1990
- --- new/valprint.c	Sun Aug 12 10:47:46 1990
***************
*** 635,654 ****
  	  val_print (TYPE_FIELD_TYPE (type, i-1), baddr,
  		     0, stream, 0, 0, recurse + 1, pretty);
  	}
- -       if (i > 1) {
- - 	fprintf_filtered (stream, "\n");
- - 	print_spaces_filtered (2 + 2 * recurse, stream);
- - 	fputs_filtered ("members of ", stream);
- -         fputs_filtered (type_name_no_tag (type), stream);
- -         fputs_filtered (": ", stream);
- -       }
        if (!len && i == 1)
  	fprintf_filtered (stream, "<No data fields>");
        else
  	{
  	  for (i -= 1; i < len; i++)
  	    {
! 	      if (i > n_baseclasses) fprintf_filtered (stream, ", ");
  	      if (pretty)
  		{
  		  fprintf_filtered (stream, "\n");
- --- 635,660 ----
  	  val_print (TYPE_FIELD_TYPE (type, i-1), baddr,
  		     0, stream, 0, 0, recurse + 1, pretty);
  	}
        if (!len && i == 1)
  	fprintf_filtered (stream, "<No data fields>");
        else
  	{
+ 	  int fields_seen = 0;
  	  for (i -= 1; i < len; i++)
  	    {
! 	      /* check if static field */
! 	      if (TYPE_FIELD_STATIC (type, i))
! 		  continue;
! 	      if (fields_seen) fprintf_filtered (stream, ", ");
! 	      else if (n_baseclasses > 0)
! 		{
! 		  fprintf_filtered (stream, "\n");
! 		  print_spaces_filtered (2 + 2 * recurse, stream);
! 		  fputs_filtered ("members of ", stream);
! 		  fputs_filtered (type_name_no_tag (type), stream);
! 		  fputs_filtered (": ", stream);
! 	        }
! 	      fields_seen = 1;
  	      if (pretty)
  		{
  		  fprintf_filtered (stream, "\n");
***************
*** 656,673 ****
  		}
  	      fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
  	      fputs_filtered (" = ", stream);
! 	      /* check if static field */
! 	      if (TYPE_FIELD_STATIC (type, i))
  		{
- - 		  value v;
- - 		  
- - 		  v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
- - 		  val_print (TYPE_FIELD_TYPE (type, i),
- - 			     VALUE_CONTENTS (v), 0, stream, format,
- - 			     deref_ref, recurse + 1, pretty);
- - 		}
- - 	      else if (TYPE_FIELD_PACKED (type, i))
- - 		{
  		  char *valp = (char *) & val;
  		  union {int i; char c;} test;
  		  test.i = 1;
- --- 662,669 ----
  		}
  	      fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
  	      fputs_filtered (" = ", stream);
! 	      if (TYPE_FIELD_PACKED (type, i))
  		{
  		  char *valp = (char *) & val;
  		  union {int i; char c;} test;
  		  test.i = 1;
***************
*** 893,900 ****
    int i;
  
    fputs_filtered (" ", stream);
!   fputs_filtered (prefix, stream);
!   fputs_filtered (varstring, stream);
    fputs_filtered (" (", stream);
    if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
      {
- --- 889,896 ----
    int i;
  
    fputs_filtered (" ", stream);
!   fputs_demangled (prefix, stream, 1);
!   fputs_demangled (varstring, stream, 1);
    fputs_filtered (" (", stream);
    if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
      {
***************
*** 930,957 ****
    int i, n_baseclasses = TYPE_N_BASECLASSES (type);
    struct type *basetype = 0;
  
!   while (type && n_baseclasses == 1)
      {
! 
!       check_stub_type(type);	/* Not actually sure about this one -- Bryan. */
! 
!       basetype = TYPE_BASECLASS (type, 1);
!       if (name = type_name_no_tag (basetype))
! 	{
! 	  fprintf_filtered (stream, ": %s%s ",
! 		   TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
! 		   TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "");
! 	  fputs_filtered (name, stream);
! 	  fputs_filtered (" ", stream);
! 	}
!       n_baseclasses = TYPE_N_BASECLASSES (basetype);
!       type = basetype;
!     }
! 
!   if (type)
!     {
!       if (n_baseclasses != 0)
! 	fprintf_filtered (stream, ": ");
        for (i = 1; i <= n_baseclasses; i++)
  	{
  	  basetype = TYPE_BASECLASS (type, i);
- --- 926,937 ----
    int i, n_baseclasses = TYPE_N_BASECLASSES (type);
    struct type *basetype = 0;
  
!   while (type && n_baseclasses > 0)
      {
!       /* Not actually sure about this one -- Bryan. */
!       check_stub_type (type);
!       
!       fprintf_filtered (stream, ": ");
        for (i = 1; i <= n_baseclasses; i++)
  	{
  	  basetype = TYPE_BASECLASS (type, i);
***************
*** 965,971 ****
- --- 945,955 ----
  	  if (i < n_baseclasses)
  	    fprintf_filtered (stream, ", ");
  	}
+ 
        fprintf_filtered (stream, " ");
+       if (n_baseclasses != 1) break;
+       n_baseclasses = TYPE_N_BASECLASSES (basetype);
+       type = basetype;
      }
  }
  
***************
*** 1288,1294 ****
  
  		  fprintf_filtered (stream, ";\n");
  		}
- - 	      if (len2) fprintf_filtered (stream, "\n");
  	    }
  
  	  print_spaces_filtered (level, stream);
- --- 1272,1277 ----
diff -c old/value.h new/value.h
*** old/value.h	Tue Jun 26 01:51:24 1990
- --- new/value.h	Sat Aug 11 12:52:56 1990
***************
*** 165,171 ****
  value value_neg ();
  value value_lognot ();
  value value_struct_elt (), value_struct_elt_for_address ();
! value value_field ();
  value value_cast ();
  value value_zero ();
  value value_repeat ();
- --- 165,171 ----
  value value_neg ();
  value value_lognot ();
  value value_struct_elt (), value_struct_elt_for_address ();
! value value_field (), value_primitive_field();
  value value_cast ();
  value value_zero ();
  value value_repeat ();
diff -c old/values.c new/values.c
*** old/values.c	Tue Jul  3 11:39:01 1990
- --- new/values.c	Sat Aug 11 12:51:37 1990
***************
*** 642,648 ****
    return (double) 0;		/* To silence compiler warning.  */
  }
  
! /* Given a value ARG1 of a struct or union type,
     extract and return the value of one of its fields.
     FIELDNO says which field.
  
- --- 642,649 ----
    return (double) 0;		/* To silence compiler warning.  */
  }
  
! /* Given a value ARG1 (offset by OFFSET bytes)
!    of a struct or union type ARG_TYPE,
     extract and return the value of one of its fields.
     FIELDNO says which field.
  
***************
*** 649,676 ****
     For C++, must also be able to return values from static fields */
  
  value
! value_field (arg1, fieldno)
       register value arg1;
       register int fieldno;
  {
    register value v;
    register struct type *type;
- -   register int offset;
  
!   check_stub_type (VALUE_TYPE (arg1));
!   type = TYPE_FIELD_TYPE (VALUE_TYPE (arg1), fieldno);
  
    /* Handle packed fields */
  
!   offset = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) / 8;
    if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno))
      {
        v = value_from_long (type,
! 			   unpack_field_as_long (VALUE_TYPE (arg1),
  						 VALUE_CONTENTS (arg1),
  						 fieldno));
!       VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) % 8;
!       VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno);
      }
    else
      {
- --- 650,677 ----
     For C++, must also be able to return values from static fields */
  
  value
! value_primitive_field (arg1, offset, fieldno, arg_type)
       register value arg1;
       register int fieldno;
+      register struct type *arg_type;
  {
    register value v;
    register struct type *type;
  
!   check_stub_type (arg_type);
!   type = TYPE_FIELD_TYPE (arg_type, fieldno);
  
    /* Handle packed fields */
  
!   offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
    if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno))
      {
        v = value_from_long (type,
! 			   unpack_field_as_long (arg_type,
  						 VALUE_CONTENTS (arg1),
  						 fieldno));
!       VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
!       VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
      }
    else
      {
***************
*** 685,690 ****
- --- 686,705 ----
    VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
    VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1);
    return v;
+ }
+ 
+ /* Given a value ARG1 of a struct or union type,
+    extract and return the value of one of its fields.
+    FIELDNO says which field.
+ 
+    For C++, must also be able to return values from static fields */
+ 
+ value
+ value_field (arg1, fieldno)
+      register value arg1;
+      register int fieldno;
+ {
+   return value_primitive_field (arg1, 0, VALUE_TYPE (arg1), fieldno);
  }
  
  value
Technical Details
Message-ID: <9008131858.AA21679@sevenlayer.cs.wisc.edu>
Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!CS.WISC.EDU!bothner

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f5053,b78a05d6f56ffcae,start
X-Google-Attributes: gidf5053,public
X-Google-ArrivalTime: 1990-08-14 10:06:32 PST
Path: arc1-ca.pugleaf.net!gmdzi!unido!mcsun!uunet!tut.cis.ohio-state.edu!CS.WISC.EDU!bothner
From: bothner@CS.WISC.EDU
Newsgroups: gnu.gdb.bug
Subject: Gdb patches for g++ users
Message-ID: <9008131858.AA21679@sevenlayer.cs.wisc.edu>
Date: 13 Aug 90 18:58:42 GMT
Sender: daemon@tut.cis.ohio-state.edu
Distribution: gnu
Organization: GNUs Not Usenet
Lines: 1465
Posted: Mon Aug 13 19:58:42 1990