Add a symbol's value to the computed frag offset, rather than overwriting it.
[deliverable/binutils-gdb.git] / gdb / c-typeprint.c
index 90b626d8a95cfc58bb875654de1dce22632fb306..acfbc6f47e8c9d098b4cd731204147faa83b99ca 100644 (file)
@@ -1,5 +1,5 @@
 /* Support for printing C and C++ types for GDB, the GNU debugger.
-   Copyright 1986, 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1998, 1999
+   Copyright 1986, 1988, 1989, 1991, 1993-1996, 1998-2000
    Free Software Foundation, Inc.
 
    This file is part of GDB.
 /* Flag indicating target was compiled by HP compiler */
 extern int hp_som_som_object_present;
 
-static void cp_type_print_method_args PARAMS ((struct type ** args, char *prefix, char *varstring, int staticp, GDB_FILE * stream));
+static void cp_type_print_method_args (struct type ** args, char *prefix,
+                                      char *varstring, int staticp,
+                                      struct ui_file *stream);
 
-static void
-c_type_print_args PARAMS ((struct type *, GDB_FILE *));
+static void c_type_print_args (struct type *, struct ui_file *);
 
-static void
-cp_type_print_derivation_info PARAMS ((GDB_FILE *, struct type *));
+static void cp_type_print_derivation_info (struct ui_file *, struct type *);
 
-void
-c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
+void c_type_print_varspec_prefix (struct type *, struct ui_file *, int,
+                                 int);
 
-static void
-c_type_print_cv_qualifier PARAMS ((struct type *, GDB_FILE *, int, int));
+static void c_type_print_cv_qualifier (struct type *, struct ui_file *,
+                                      int, int);
 \f
 
 
@@ -66,7 +66,7 @@ void
 c_typedef_print (type, new, stream)
      struct type *type;
      struct symbol *new;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   CHECK_TYPEDEF (type);
   switch (current_language->la_language)
@@ -116,7 +116,7 @@ void
 c_print_type (type, varstring, stream, show, level)
      struct type *type;
      char *varstring;
-     GDB_FILE *stream;
+     struct ui_file *stream;
      int show;
      int level;
 {
@@ -183,7 +183,7 @@ c_print_type (type, varstring, stream, show, level)
 
 static void
 cp_type_print_derivation_info (stream, type)
-     GDB_FILE *stream;
+     struct ui_file *stream;
      struct type *type;
 {
   char *name;
@@ -212,7 +212,7 @@ cp_type_print_method_args (args, prefix, varstring, staticp, stream)
      char *prefix;
      char *varstring;
      int staticp;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   int i;
 
@@ -258,7 +258,7 @@ cp_type_print_method_args (args, prefix, varstring, staticp, stream)
 void
 c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
      struct type *type;
-     GDB_FILE *stream;
+     struct ui_file *stream;
      int show;
      int passed_a_ptr;
 {
@@ -356,7 +356,7 @@ c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
 static void
 c_type_print_cv_qualifier (type, stream, need_pre_space, need_post_space)
      struct type *type;
-     GDB_FILE *stream;
+     struct ui_file *stream;
      int need_pre_space;
      int need_post_space;
 {
@@ -388,7 +388,7 @@ c_type_print_cv_qualifier (type, stream, need_pre_space, need_post_space)
 static void
 c_type_print_args (type, stream)
      struct type *type;
-     GDB_FILE *stream;
+     struct ui_file *stream;
 {
   int i;
   struct type **args;
@@ -433,6 +433,135 @@ c_type_print_args (type, stream)
   fprintf_filtered (stream, ")");
 }
 
+
+/* Return true iff the j'th overloading of the i'th method of TYPE
+   is a type conversion operator, like `operator int () { ... }'.
+   When listing a class's methods, we don't print the return type of
+   such operators.  */
+static int
+is_type_conversion_operator (struct type *type, int i, int j)
+{
+  /* I think the whole idea of recognizing type conversion operators
+     by their name is pretty terrible.  But I don't think our present
+     data structure gives us any other way to tell.  If you know of
+     some other way, feel free to rewrite this function.  */
+  char *name = TYPE_FN_FIELDLIST_NAME (type, i);
+
+  if (strncmp (name, "operator", 8) != 0)
+    return 0;
+
+  name += 8;
+  if (! strchr (" \t\f\n\r", *name))
+    return 0;
+
+  while (strchr (" \t\f\n\r", *name))
+    name++;
+
+  if (strncmp (name, "new", 3) == 0)
+    name += 3;
+  else if (strncmp (name, "delete", 6) == 0)
+    name += 6;
+  else
+    return 0;
+
+  /* Is that really the end of the name?  */
+  if (('a' <= *name && *name <= 'z')
+      || ('A' <= *name && *name <= 'Z')
+      || ('0' <= *name && *name <= '9')
+      || *name == '_')
+    /* No, so the identifier following "operator" must be a type name,
+       and this is a type conversion operator.  */
+    return 1;
+
+  /* That was indeed the end of the name, so it was `operator new' or
+     `operator delete', neither of which are type conversion operators.  */
+  return 0;
+}
+
+
+/* Given a C++ qualified identifier QID, strip off the qualifiers,
+   yielding the unqualified name.  The return value is a pointer into
+   the original string.
+
+   It's a pity we don't have this information in some more structured
+   form.  Even the author of this function feels that writing little
+   parsers like this everywhere is stupid.  */
+static char *
+remove_qualifiers (char *qid)
+{
+  int quoted = 0;              /* zero if we're not in quotes;
+                                  '"' if we're in a double-quoted string;
+                                  '\'' if we're in a single-quoted string.  */
+  int depth = 0;               /* number of unclosed parens we've seen */
+  char *parenstack = (char *) alloca (strlen (qid));
+  char *scan;
+  char *last = 0;              /* The character after the rightmost
+                                  `::' token we've seen so far.  */
+
+  for (scan = qid; *scan; scan++)
+    {
+      if (quoted)
+       {
+         if (*scan == quoted)
+           quoted = 0;
+         else if (*scan == '\\' && *(scan + 1))
+           scan++;
+       }
+      else if (scan[0] == ':' && scan[1] == ':')
+       {
+         /* If we're inside parenthesis (i.e., an argument list) or
+            angle brackets (i.e., a list of template arguments), then
+            we don't record the position of this :: token, since it's
+            not relevant to the top-level structure we're trying
+            to operate on.  */
+         if (depth == 0)
+           {
+             last = scan + 2;
+             scan++;
+           }
+       }
+      else if (*scan == '"' || *scan == '\'')
+       quoted = *scan;
+      else if (*scan == '(')
+       parenstack[depth++] = ')';
+      else if (*scan == '[')
+       parenstack[depth++] = ']';
+      /* We're going to treat <> as a pair of matching characters,
+        since we're more likely to see those in template id's than
+        real less-than characters.  What a crock.  */
+      else if (*scan == '<')
+       parenstack[depth++] = '>';
+      else if (*scan == ')' || *scan == ']' || *scan == '>')
+       {
+         if (depth > 0 && parenstack[depth - 1] == *scan)
+           depth--;
+         else
+           {
+             /* We're going to do a little error recovery here.  If we
+                don't find a match for *scan on the paren stack, but
+                there is something lower on the stack that does match, we
+                pop the stack to that point.  */
+             int i;
+
+             for (i = depth - 1; i >= 0; i--)
+               if (parenstack[i] == *scan)
+                 {
+                   depth = i;
+                   break;
+                 }
+           }
+       }
+    }
+
+  if (last)
+    return last;
+  else
+    /* We didn't find any :: tokens at the top level, so declare the
+       whole thing an unqualified identifier.  */
+    return qid;
+}
+
+
 /* Print any array sizes, function arguments or close parentheses
    needed after the variable name (to describe its type).
    Args work like c_type_print_varspec_prefix.  */
@@ -440,7 +569,7 @@ c_type_print_args (type, stream)
 void
 c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
      struct type *type;
-     GDB_FILE *stream;
+     struct ui_file *stream;
      int show;
      int passed_a_ptr;
      int demangled_args;
@@ -563,7 +692,7 @@ c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
 void
 c_type_print_base (type, stream, show, level)
      struct type *type;
-     GDB_FILE *stream;
+     struct ui_file *stream;
      int show;
      int level;
 {
@@ -896,8 +1025,7 @@ c_type_print_base (type, stream, show, level)
                    }
                  else if (!is_constructor &&   /* constructors don't have declared types */
                           !is_full_physname_constructor &&     /*    " "  */
-                          !strstr (method_name, "operator "))  /* Not a type conversion operator */
-                   /* (note space -- other operators don't have it) */
+                          !is_type_conversion_operator (type, i, j))
                    {
                      type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
                                  "", stream, -1);
@@ -931,15 +1059,10 @@ c_type_print_base (type, stream, show, level)
                  else
                    {
                      char *p;
-                     char *demangled_no_class = strrchr (demangled_name, ':');
+                     char *demangled_no_class
+                       = remove_qualifiers (demangled_name);
 
-                      if (demangled_no_class == NULL)
-                        demangled_no_class = demangled_name;
-                      else
-                        {
-                          ++demangled_no_class; /* skip over last ':' */
-                       }
-                     /* get rid of the static word appended by the demangler */
+                     /* get rid of the `static' appended by the demangler */
                      p = strstr (demangled_no_class, " static");
                      if (p != NULL)
                        {
This page took 0.025926 seconds and 4 git commands to generate.