* strerror.c: Revert last change. Declare static sys_nerr
[deliverable/binutils-gdb.git] / gdb / linespec.c
index 088c2e63d8138cc5223998620f61f4a77578e866..7e8c6a7c9297e6dc458c97bc83981ab2c5d44b7e 100644 (file)
@@ -33,6 +33,8 @@
 #include "cp-abi.h"
 #include "parser-defs.h"
 #include "block.h"
+#include "objc-lang.h"
+#include "linespec.h"
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -49,6 +51,12 @@ static struct symtabs_and_lines decode_indirect (char **argptr);
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
 
+static struct symtabs_and_lines decode_objc (char **argptr,
+                                            int funfirstline,
+                                            struct symtab *file_symtab,
+                                            char ***canonical,
+                                            char *saved_arg);
+
 static struct symtabs_and_lines decode_compound (char **argptr,
                                                 int funfirstline,
                                                 char ***canonical,
@@ -64,6 +72,9 @@ static struct symtabs_and_lines find_method (int funfirstline,
                                             struct type *t,
                                             struct symbol *sym_class);
 
+static int collect_methods (char *copy, struct type *t,
+                           struct symbol **sym_arr);
+
 static NORETURN void cplusplus_error (const char *name,
                                      const char *fmt, ...)
      ATTR_NORETURN ATTR_FORMAT (printf, 2, 3);
@@ -72,11 +83,19 @@ static int total_number_of_methods (struct type *type);
 
 static int find_methods (struct type *, char *, struct symbol **);
 
+static int add_matching_methods (int method_counter, struct type *t,
+                                struct symbol **sym_arr);
+
+static int add_constructors (int method_counter, struct type *t,
+                            struct symbol **sym_arr);
+
 static void build_canonical_line_spec (struct symtab_and_line *,
                                       char *, char ***);
 
 static char *find_toplevel_char (char *s, char c);
 
+static int is_objc_method_format (const char *s);
+
 static struct symtabs_and_lines decode_line_2 (struct symbol *[],
                                               int, int, char ***);
 
@@ -184,7 +203,7 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
      the class, then the loop can't do any good.  */
   if (class_name
       && (lookup_symbol (class_name, (struct block *) NULL,
-                        STRUCT_NAMESPACE, (int *) NULL,
+                        STRUCT_DOMAIN, (int *) NULL,
                         (struct symtab **) NULL)))
     {
       int method_counter;
@@ -200,7 +219,6 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
           method_counter >= 0;
           --method_counter)
        {
-         int field_counter;
          char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
          char dem_opname[64];
 
@@ -216,88 +234,13 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
 
          if (strcmp_iw (name, method_name) == 0)
            /* Find all the overloaded methods with that name.  */
-           for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
-                field_counter >= 0;
-                --field_counter)
-             {
-               struct fn_field *f;
-               char *phys_name;
-
-               f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
-               if (TYPE_FN_FIELD_STUB (f, field_counter))
-                 {
-                   char *tmp_name;
-
-                   tmp_name = gdb_mangle_name (t,
-                                               method_counter,
-                                               field_counter);
-                   phys_name = alloca (strlen (tmp_name) + 1);
-                   strcpy (phys_name, tmp_name);
-                   xfree (tmp_name);
-                 }
-               else
-                 phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-               
-               /* Destructor is handled by caller, don't add it to
-                  the list.  */
-               if (is_destructor_name (phys_name) != 0)
-                 continue;
-
-               sym_arr[i1] = lookup_symbol (phys_name,
-                                            NULL, VAR_NAMESPACE,
-                                            (int *) NULL,
-                                            (struct symtab **) NULL);
-               if (sym_arr[i1])
-                 i1++;
-               else
-                 {
-                   /* This error message gets printed, but the method
-                      still seems to be found
-                      fputs_filtered("(Cannot find method ", gdb_stdout);
-                      fprintf_symbol_filtered (gdb_stdout, phys_name,
-                      language_cplus,
-                      DMGL_PARAMS | DMGL_ANSI);
-                      fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
-                    */
-                 }
-             }
+           i1 += add_matching_methods (method_counter, t,
+                                       sym_arr + i1);
          else if (strncmp (class_name, name, name_len) == 0
                   && (class_name[name_len] == '\0'
                       || class_name[name_len] == '<'))
-           {
-             /* For GCC 3.x and stabs, constructors and destructors
-                have names like __base_ctor and __complete_dtor.
-                Check the physname for now if we're looking for a
-                constructor.  */
-             for (field_counter
-                    = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
-                  field_counter >= 0;
-                  --field_counter)
-               {
-                 struct fn_field *f;
-                 char *phys_name;
-                 
-                 f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
-                 /* GCC 3.x will never produce stabs stub methods, so
-                    we don't need to handle this case.  */
-                 if (TYPE_FN_FIELD_STUB (f, field_counter))
-                   continue;
-                 phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-                 if (! is_constructor_name (phys_name))
-                   continue;
-
-                 /* If this method is actually defined, include it in the
-                    list.  */
-                 sym_arr[i1] = lookup_symbol (phys_name,
-                                              NULL, VAR_NAMESPACE,
-                                              (int *) NULL,
-                                              (struct symtab **) NULL);
-                 if (sym_arr[i1])
-                   i1++;
-               }
-           }
+           i1 += add_constructors (method_counter, t,
+                                   sym_arr + i1);
        }
     }
 
@@ -319,6 +262,113 @@ find_methods (struct type *t, char *name, struct symbol **sym_arr)
   return i1;
 }
 
+/* Add the symbols associated to methods of the class whose type is T
+   and whose name matches the method indexed by METHOD_COUNTER in the
+   array SYM_ARR.  Return the number of methods added.  */
+
+static int
+add_matching_methods (int method_counter, struct type *t,
+                     struct symbol **sym_arr)
+{
+  int field_counter;
+  int i1 = 0;
+
+  for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+       field_counter >= 0;
+       --field_counter)
+    {
+      struct fn_field *f;
+      char *phys_name;
+
+      f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+      if (TYPE_FN_FIELD_STUB (f, field_counter))
+       {
+         char *tmp_name;
+
+         tmp_name = gdb_mangle_name (t,
+                                     method_counter,
+                                     field_counter);
+         phys_name = alloca (strlen (tmp_name) + 1);
+         strcpy (phys_name, tmp_name);
+         xfree (tmp_name);
+       }
+      else
+       phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+               
+      /* Destructor is handled by caller, don't add it to
+        the list.  */
+      if (is_destructor_name (phys_name) != 0)
+       continue;
+
+      sym_arr[i1] = lookup_symbol (phys_name,
+                                  NULL, VAR_DOMAIN,
+                                  (int *) NULL,
+                                  (struct symtab **) NULL);
+      if (sym_arr[i1])
+       i1++;
+      else
+       {
+         /* This error message gets printed, but the method
+            still seems to be found
+            fputs_filtered("(Cannot find method ", gdb_stdout);
+            fprintf_symbol_filtered (gdb_stdout, phys_name,
+            language_cplus,
+            DMGL_PARAMS | DMGL_ANSI);
+            fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
+         */
+       }
+    }
+
+  return i1;
+}
+
+/* Add the symbols associated to constructors of the class whose type
+   is CLASS_TYPE and which are indexed by by METHOD_COUNTER to the
+   array SYM_ARR.  Return the number of methods added.  */
+
+static int
+add_constructors (int method_counter, struct type *t,
+                 struct symbol **sym_arr)
+{
+  int field_counter;
+  int i1 = 0;
+
+  /* For GCC 3.x and stabs, constructors and destructors
+     have names like __base_ctor and __complete_dtor.
+     Check the physname for now if we're looking for a
+     constructor.  */
+  for (field_counter
+        = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
+       field_counter >= 0;
+       --field_counter)
+    {
+      struct fn_field *f;
+      char *phys_name;
+                 
+      f = TYPE_FN_FIELDLIST1 (t, method_counter);
+
+      /* GCC 3.x will never produce stabs stub methods, so
+        we don't need to handle this case.  */
+      if (TYPE_FN_FIELD_STUB (f, field_counter))
+       continue;
+      phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+      if (! is_constructor_name (phys_name))
+       continue;
+
+      /* If this method is actually defined, include it in the
+        list.  */
+      sym_arr[i1] = lookup_symbol (phys_name,
+                                  NULL, VAR_DOMAIN,
+                                  (int *) NULL,
+                                  (struct symtab **) NULL);
+      if (sym_arr[i1])
+       i1++;
+    }
+
+  return i1;
+}
+
 /* Helper function for decode_line_1.
    Build a canonical line spec in CANONICAL if it is non-NULL and if
    the SAL has a symtab.
@@ -395,6 +445,25 @@ find_toplevel_char (char *s, char c)
   return 0;
 }
 
+/* Determines if the gives string corresponds to an Objective-C method
+   representation, such as -[Foo bar:] or +[Foo bar]. Objective-C symbols
+   are allowed to have spaces and parentheses in them.  */
+
+static int 
+is_objc_method_format (const char *s)
+{
+  if (s == NULL || *s == '\0')
+    return 0;
+  /* Handle arguments with the format FILENAME:SYMBOL.  */
+  if ((s[0] == ':') && (strchr ("+-", s[1]) != NULL) 
+      && (s[2] == '[') && strchr(s, ']'))
+    return 1;
+  /* Handle arguments that are just SYMBOL.  */
+  else if ((strchr ("+-", s[0]) != NULL) && (s[1] == '[') && strchr(s, ']'))
+    return 1;
+  return 0;
+}
+
 /* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
    operate on (ask user if necessary).
    If CANONICAL is non-NULL return a corresponding array of mangled names
@@ -435,11 +504,18 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
       if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
        {
          values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
-         printf_unfiltered ("[%d] %s at %s:%d\n",
-                            (i + 2),
-                            SYMBOL_PRINT_NAME (sym_arr[i]),
-                            values.sals[i].symtab->filename,
-                            values.sals[i].line);
+         if (values.sals[i].symtab)
+           printf_unfiltered ("[%d] %s at %s:%d\n",
+                              (i + 2),
+                              SYMBOL_PRINT_NAME (sym_arr[i]),
+                              values.sals[i].symtab->filename,
+                              values.sals[i].line);
+         else
+           printf_unfiltered ("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n",
+                              (i + 2),
+                              SYMBOL_PRINT_NAME (sym_arr[i]),
+                              values.sals[i].line);
+
        }
       else
        printf_unfiltered ("?HERE\n");
@@ -586,6 +662,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   int is_quoted;
   /* Is part of *ARGPTR is enclosed in double quotes?  */
   int is_quote_enclosed;
+  int is_objc_method = 0;
   char *saved_arg = *argptr;
 
   /* Defaults have defaults.  */
@@ -611,6 +688,24 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 
   p = locate_first_half (argptr, &is_quote_enclosed);
 
+  /* Check if this is an Objective-C method (anything that starts with
+     a '+' or '-' and a '[').  */
+  if (is_objc_method_format (p))
+    {
+      is_objc_method = 1;
+      paren_pointer  = NULL; /* Just a category name.  Ignore it.  */
+    }
+
+  /* Check if the symbol could be an Objective-C selector.  */
+
+  {
+    struct symtabs_and_lines values;
+    values = decode_objc (argptr, funfirstline, NULL,
+                         canonical, saved_arg);
+    if (values.sals != NULL)
+      return values;
+  }
+
   /* Does it look like there actually were two parts?  */
 
   if ((p[0] == ':' || p[0] == '.') && paren_pointer == NULL)
@@ -652,7 +747,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       copy = (char *) alloca (p - *argptr + 1);
       memcpy (copy, *argptr, p - *argptr);
       copy[p - *argptr] = '\000';
-      sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
       if (sym)
        {
          *argptr = (*p == '\'') ? p + 1 : p;
@@ -692,6 +787,11 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       if (p[-1] != '\'')
        error ("Unmatched single quote.");
     }
+  else if (is_objc_method)
+    {
+      /* allow word separators in method names for Obj-C */
+      p = skip_quoted_chars (*argptr, NULL, "");
+    }
   else if (paren_pointer != NULL)
     {
       p = paren_pointer + 1;
@@ -890,6 +990,12 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
            error ("malformed template specification in command");
          p = temp_end;
        }
+      /* Check for a colon and a plus or minus and a [ (which
+         indicates an Objective-C method) */
+      if (is_objc_method_format (p))
+       {
+         break;
+       }
       /* Check for the end of the first half of the linespec.  End of
          line, a tab, a double colon or the last single colon, or a
          space.  But if enclosed in double quotes we do not break on
@@ -933,6 +1039,95 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
 
 \f
 
+/* Here's where we recognise an Objective-C Selector.  An Objective C
+   selector may be implemented by more than one class, therefore it
+   may represent more than one method/function.  This gives us a
+   situation somewhat analogous to C++ overloading.  If there's more
+   than one method that could represent the selector, then use some of
+   the existing C++ code to let the user choose one.  */
+
+struct symtabs_and_lines
+decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
+            char ***canonical, char *saved_arg)
+{
+  struct symtabs_and_lines values;
+  struct symbol **sym_arr = NULL;
+  struct symbol *sym = NULL;
+  char *copy = NULL;
+  struct block *block = NULL;
+  int i1 = 0;
+  int i2 = 0;
+
+  values.sals = NULL;
+  values.nelts = 0;
+
+  if (file_symtab != NULL)
+    block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab), STATIC_BLOCK);
+  else
+    block = get_selected_block (0);
+    
+  copy = find_imps (file_symtab, block, *argptr, NULL, &i1, &i2); 
+    
+  if (i1 > 0)
+    {
+      sym_arr = (struct symbol **) alloca ((i1 + 1) * sizeof (struct symbol *));
+      sym_arr[i1] = 0;
+
+      copy = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2); 
+      *argptr = copy;
+    }
+
+  /* i1 now represents the TOTAL number of matches found.
+     i2 represents how many HIGH-LEVEL (struct symbol) matches,
+     which will come first in the sym_arr array.  Any low-level
+     (minimal_symbol) matches will follow those.  */
+      
+  if (i1 == 1)
+    {
+      if (i2 > 0)
+       {
+         /* Already a struct symbol.  */
+         sym = sym_arr[0];
+       }
+      else
+       {
+         sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
+         if ((sym != NULL) && strcmp (SYMBOL_LINKAGE_NAME (sym_arr[0]), SYMBOL_LINKAGE_NAME (sym)) != 0)
+           {
+             warning ("debugging symbol \"%s\" does not match selector; ignoring", SYMBOL_LINKAGE_NAME (sym));
+             sym = NULL;
+           }
+       }
+             
+      values.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+      values.nelts = 1;
+             
+      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+       {
+         /* Canonicalize this, so it remains resolved for dylib loads.  */
+         values.sals[0] = find_function_start_sal (sym, funfirstline);
+         build_canonical_line_spec (values.sals, SYMBOL_NATURAL_NAME (sym), canonical);
+       }
+      else
+       {
+         /* The only match was a non-debuggable symbol.  */
+         values.sals[0].symtab = 0;
+         values.sals[0].line = 0;
+         values.sals[0].end = 0;
+         values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym_arr[0]);
+       }
+      return values;
+    }
+
+  if (i1 > 1)
+    {
+      /* More than one match. The user must choose one or more.  */
+      return decode_line_2 (sym_arr, i2, funfirstline, canonical);
+    }
+
+  return values;
+}
+
 /* This handles C++ and Java compound data structures.  P should point
    at the first component separator, i.e. double-colon or period.  */
 
@@ -1083,7 +1278,7 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
   /* Set argptr to skip over the name.  */
   *argptr = (*p == '\'') ? p + 1 : p;
   /* Look up entire name */
-  sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+  sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
   if (sym)
     return symbol_found (funfirstline, canonical, copy, sym,
                         NULL, sym_symtab);
@@ -1122,7 +1317,7 @@ lookup_prefix_sym (char **argptr, char *p)
     p++;
   *argptr = p;
 
-  return lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
+  return lookup_symbol (copy, 0, STRUCT_DOMAIN, 0,
                        (struct symtab **) NULL);
 }
 
@@ -1135,29 +1330,15 @@ find_method (int funfirstline, char ***canonical, char *saved_arg,
 {
   struct symtabs_and_lines values;
   struct symbol *sym = 0;
-  int i1 = 0;  /*  Counter for the symbol array.  */
+  int i1;      /*  Counter for the symbol array.  */
   struct symbol **sym_arr =  alloca (total_number_of_methods (t)
                                     * sizeof (struct symbol *));
 
-  if (destructor_name_p (copy, t))
-    {
-      /* Destructors are a special case.  */
-      int m_index, f_index;
+  /* Find all methods with a matching name, and put them in
+     sym_arr.  */
 
-      if (get_destructor_fn_field (t, &m_index, &f_index))
-       {
-         struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
+  i1 = collect_methods (copy, t, sym_arr);
 
-         sym_arr[i1] =
-           lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
-                          NULL, VAR_NAMESPACE, (int *) NULL,
-                          (struct symtab **) NULL);
-         if (sym_arr[i1])
-           i1++;
-       }
-    }
-  else
-    i1 = find_methods (t, copy, sym_arr);
   if (i1 == 1)
     {
       /* There is exactly one field with that name.  */
@@ -1206,6 +1387,38 @@ find_method (int funfirstline, char ***canonical, char *saved_arg,
     }
 }
 
+/* Find all methods named COPY in the class whose type is T, and put
+   them in SYM_ARR.  Return the number of methods found.  */
+
+static int
+collect_methods (char *copy, struct type *t,
+                struct symbol **sym_arr)
+{
+  int i1 = 0;  /*  Counter for the symbol array.  */
+
+  if (destructor_name_p (copy, t))
+    {
+      /* Destructors are a special case.  */
+      int m_index, f_index;
+
+      if (get_destructor_fn_field (t, &m_index, &f_index))
+       {
+         struct fn_field *f = TYPE_FN_FIELDLIST1 (t, m_index);
+
+         sym_arr[i1] =
+           lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, f_index),
+                          NULL, VAR_DOMAIN, (int *) NULL,
+                          (struct symtab **) NULL);
+         if (sym_arr[i1])
+           i1++;
+       }
+    }
+  else
+    i1 = find_methods (t, copy, sym_arr);
+
+  return i1;
+}
+
 \f
 
 /* Return the symtab associated to the filename given by the substring
@@ -1372,7 +1585,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
         convenience variable.  */
 
       /* Look up entire name as a symbol first.  */
-      sym = lookup_symbol (copy, 0, VAR_NAMESPACE, 0, &sym_symtab);
+      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0, &sym_symtab);
       file_symtab = (struct symtab *) 0;
       need_canonical = 1;
       /* Symbol was found --> jump to normal symbol processing.  */
@@ -1430,7 +1643,7 @@ decode_variable (char *copy, int funfirstline, char ***canonical,
                        ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
                                             STATIC_BLOCK)
                        : get_selected_block (0)),
-                      VAR_NAMESPACE, 0, &sym_symtab);
+                      VAR_DOMAIN, 0, &sym_symtab);
 
   if (sym != NULL)
     return symbol_found (funfirstline, canonical, copy, sym,
@@ -1482,7 +1695,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
        {
          struct blockvector *bv = BLOCKVECTOR (sym_symtab);
          struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-         if (lookup_block_symbol (b, copy, NULL, VAR_NAMESPACE) != NULL)
+         if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
            build_canonical_line_spec (values.sals, copy, canonical);
        }
       return values;
This page took 0.030298 seconds and 4 git commands to generate.