* remote.c (minitelnet): Don't redeclare escape_count, echo_check.
[binutils-gdb.git] / gdb / objc-lang.c
index 61233a8871639f7afaa657ed42947f8ceae989e7..bc937ca7ea03c90d8cdd98c5cec9232d3a3be5c5 100644 (file)
@@ -1,21 +1,26 @@
 /* Objective-C language support routines for GDB, the GNU debugger.
-   Copyright 1996 NeXT Software, Inc.
 
-This file is part of GDB.
+   Copyright 2002, 2003 Free Software Foundation, Inc.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   Contributed by Apple Computer, Inc.
+   Written by Michael Snyder.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This file is part of GDB.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -29,13 +34,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "value.h"
 #include "symfile.h"
 #include "objfiles.h"
-#include "string.h"            /* for strchr */
+#include "gdb_string.h"                /* for strchr */
 #include "target.h"            /* for target_has_execution */
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "frame.h"
 #include "gdb_regex.h"
 #include "regcache.h"
+#include "block.h"
 
 #include <ctype.h>
 
@@ -69,15 +75,6 @@ struct objc_method {
 
 /* Complaints about ObjC classes, selectors, etc.  */
 
-static struct complaint noclass_lookup_complaint = {
-  "no way to lookup Objective-C classes", 0, 0
-};
-
-static struct complaint nosel_lookup_complaint = {
-  "no way to lookup Objective-C selectors", 0, 0
-};
-
-
 #if (!defined __GNUC__ || __GNUC__ < 2 || __GNUC_MINOR__ < (defined __cplusplus ? 6 : 4))
 #define __CHECK_FUNCTION ((__const char *) 0)
 #else
@@ -155,7 +152,7 @@ lookup_objc_class (char *classname)
     function = find_function_in_inferior("objc_lookup_class");
   else
     {
-      complain (&noclass_lookup_complaint, 0);
+      complaint (&symfile_complaints, "no way to lookup Objective-C classes");
       return 0;
     }
 
@@ -182,7 +179,7 @@ lookup_child_selector (char *selname)
     function = find_function_in_inferior("sel_get_any_uid");
   else
     {
-      complain (&nosel_lookup_complaint, 0);
+      complaint (&symfile_complaints, "no way to lookup Objective-C selectors");
       return 0;
     }
 
@@ -202,8 +199,10 @@ value_nsstring (char *ptr, int len)
   if (!target_has_execution)
     return 0;          /* Can't call into inferior to create NSString.  */
 
-  if (!(sym = lookup_struct_typedef("NSString", 0, 1)) &&
-      !(sym = lookup_struct_typedef("NXString", 0, 1)))
+  sym = lookup_struct_typedef("NSString", 0, 1);
+  if (sym == NULL)
+    sym = lookup_struct_typedef("NXString", 0, 1);
+  if (sym == NULL)
     type = lookup_pointer_type(builtin_type_void);
   else
     type = lookup_pointer_type(SYMBOL_TYPE (sym));
@@ -240,7 +239,7 @@ value_nsstring (char *ptr, int len)
 /* Objective-C name demangling.  */
 
 char *
-objc_demangle (const char *mangled)
+objc_demangle (const char *mangled, int options)
 {
   char *demangled, *cp;
 
@@ -261,9 +260,10 @@ objc_demangle (const char *mangled)
       while (*cp && *cp == '_')
        cp++;                   /* skip any initial underbars in class name */
 
-      if (!(cp = strchr(cp, '_')))     /* find first non-initial underbar */
+      cp = strchr(cp, '_');
+      if (!cp)                 /* find first non-initial underbar */
        {
-         free(demangled);      /* not mangled name */
+         xfree(demangled);     /* not mangled name */
          return NULL;
        }
       if (cp[1] == '_') {      /* easy case: no category name     */
@@ -272,9 +272,10 @@ objc_demangle (const char *mangled)
       }
       else {
        *cp++ = '(';            /* less easy case: category name */
-       if (!(cp = strchr(cp, '_')))
+       cp = strchr(cp, '_');
+       if (!cp)
          {
-           free(demangled);    /* not mangled name */
+           xfree(demangled);   /* not mangled name */
            return NULL;
          }
        *cp++ = ')';
@@ -363,15 +364,13 @@ objc_printchar (int c, struct ui_file *stream)
 
 static void
 objc_printstr (struct ui_file *stream, char *string, 
-              unsigned int length, int force_ellipses)
+              unsigned int length, int width, int force_ellipses)
 {
   register unsigned int i;
   unsigned int things_printed = 0;
   int in_quotes = 0;
   int need_comma = 0;
   extern int inspect_it;
-  extern int repeat_count_threshold;
-  extern int print_max;
 
   /* If the string was not truncated due to `set print elements', and
      the last byte of it is a null, we don't print that, in
@@ -594,6 +593,35 @@ objc_create_fundamental_type (struct objfile *objfile, int typeid)
   return (type);
 }
 
+/* Determine if we are currently in the Objective-C dispatch function.
+   If so, get the address of the method function that the dispatcher
+   would call and use that as the function to step into instead. Also
+   skip over the trampoline for the function (if any).  This is better
+   for the user since they are only interested in stepping into the
+   method function anyway.  */
+static CORE_ADDR 
+objc_skip_trampoline (CORE_ADDR stop_pc)
+{
+  CORE_ADDR real_stop_pc;
+  CORE_ADDR method_stop_pc;
+  
+  real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+
+  if (real_stop_pc != 0)
+    find_objc_msgcall (real_stop_pc, &method_stop_pc);
+  else
+    find_objc_msgcall (stop_pc, &method_stop_pc);
+
+  if (method_stop_pc)
+    {
+      real_stop_pc = SKIP_TRAMPOLINE_CODE (method_stop_pc);
+      if (real_stop_pc == 0)
+       real_stop_pc = method_stop_pc;
+    }
+
+  return real_stop_pc;
+}
+
 
 /* Table mapping opcodes into strings for printing operators
    and precedences of the operators.  */
@@ -671,6 +699,8 @@ const struct language_defn objc_language_defn = {
   c_print_type,                        /* Print a type using appropriate syntax */
   c_val_print,                 /* Print a value using appropriate syntax */
   c_value_print,               /* Print a top-level value */
+  objc_skip_trampoline,        /* Language specific skip_trampoline */
+  objc_demangle,               /* Language specific symbol demangler */
   {"",     "",    "",  ""},    /* Binary format info */
   {"0%lo",  "0",   "o", ""},   /* Octal format info */
   {"%ld",   "",    "d", ""},   /* Decimal format info */
@@ -734,7 +764,7 @@ add_msglist(struct stoken *str, int addcolon)
   s = (char *)xmalloc(len);
   strcpy(s, msglist_sel);
   strncat(s, p, plen);
-  free(msglist_sel);
+  xfree(msglist_sel);
   msglist_sel = s;
   if (addcolon) {
     s[len-2] = ':';
@@ -759,9 +789,9 @@ end_msglist(void)
   if (!selid)
     error("Can't find selector \"%s\"", p);
   write_exp_elt_longcst (selid);
-  free(p);
+  xfree(p);
   write_exp_elt_longcst (val); /* Number of args */
-  free(sel);
+  xfree(sel);
 
   return val;
 }
@@ -789,23 +819,25 @@ int specialcmp(char *a, char *b)
 }
 
 /*
- * Function: compare_selectors (void *, void *)
+ * Function: compare_selectors (const void *, const void *)
  *
  * Comparison function for use with qsort.  Arguments are symbols or
  * msymbols Compares selector part of objc method name alphabetically.
  */
 
 static int
-compare_selectors (void *a, void *b)
+compare_selectors (const void *a, const void *b)
 {
   char *aname, *bname;
 
-  if ((aname = SYMBOL_SOURCE_NAME (*(struct symbol **) a)) == NULL ||
-      (bname = SYMBOL_SOURCE_NAME (*(struct symbol **) b)) == NULL)
+  aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
+  bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
+  if (aname == NULL || bname == NULL)
     error ("internal: compare_selectors(1)");
 
-  if ((aname = strchr(aname, ' ')) == NULL ||
-      (bname = strchr(bname, ' ')) == NULL)
+  aname = strchr(aname, ' ');
+  bname = strchr(bname, ' ');
+  if (aname == NULL || bname == NULL)
     error ("internal: compare_selectors(2)");
 
   return specialcmp (aname+1, bname+1);
@@ -858,15 +890,17 @@ selectors_info (char *regexp, int from_tty)
     }
 
   if (regexp != NULL)
-    if (0 != (val = re_comp (myregexp)))
-      error ("Invalid regexp (%s): %s", val, regexp);
+    {
+      val = re_comp (myregexp);
+      if (val != 0)
+       error ("Invalid regexp (%s): %s", val, regexp);
+    }
 
   /* First time thru is JUST to get max length and count.  */
   ALL_MSYMBOLS (objfile, msymbol)
     {
       QUIT;
-      if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
-       name = SYMBOL_NAME (msymbol);
+      name = SYMBOL_NATURAL_NAME (msymbol);
       if (name &&
         (name[0] == '-' || name[0] == '+') &&
          name[1] == '[')               /* Got a method name.  */
@@ -897,8 +931,7 @@ selectors_info (char *regexp, int from_tty)
       ALL_MSYMBOLS (objfile, msymbol)
        {
          QUIT;
-         if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
-           name = SYMBOL_NAME (msymbol);
+         name = SYMBOL_NATURAL_NAME (msymbol);
          if (name &&
             (name[0] == '-' || name[0] == '+') &&
              name[1] == '[')           /* Got a method name.  */
@@ -922,8 +955,7 @@ selectors_info (char *regexp, int from_tty)
          char *p = asel;
 
          QUIT;
-         if ((name = SYMBOL_DEMANGLED_NAME (sym_arr[ix])) == NULL)
-           name = SYMBOL_NAME (sym_arr[ix]);
+         name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
          name = strchr (name, ' ') + 1;
          if (p[0] && specialcmp(name, p) == 0)
            continue;           /* Seen this one already (not unique).  */
@@ -942,19 +974,20 @@ selectors_info (char *regexp, int from_tty)
 }
 
 /*
- * Function: compare_classes (void *, void *)
+ * Function: compare_classes (const void *, const void *)
  *
  * Comparison function for use with qsort.  Arguments are symbols or
  * msymbols Compares class part of objc method name alphabetically. 
  */
 
 static int
-compare_classes (void *a, void *b)
+compare_classes (const void *a, const void *b)
 {
   char *aname, *bname;
 
-  if ((aname = SYMBOL_SOURCE_NAME (*(struct symbol **) a)) == NULL ||
-      (bname = SYMBOL_SOURCE_NAME (*(struct symbol **) b)) == NULL)
+  aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
+  bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
+  if (aname == NULL || bname == NULL)
     error ("internal: compare_classes(1)");
 
   return specialcmp (aname+1, bname+1);
@@ -997,15 +1030,17 @@ classes_info (char *regexp, int from_tty)
     }
 
   if (regexp != NULL)
-    if (0 != (val = re_comp (myregexp)))
-      error ("Invalid regexp (%s): %s", val, regexp);
+    {
+      val = re_comp (myregexp);
+      if (val != 0)
+       error ("Invalid regexp (%s): %s", val, regexp);
+    }
 
   /* First time thru is JUST to get max length and count.  */
   ALL_MSYMBOLS (objfile, msymbol)
     {
       QUIT;
-      if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
-       name = SYMBOL_NAME (msymbol);
+      name = SYMBOL_NATURAL_NAME (msymbol);
       if (name &&
         (name[0] == '-' || name[0] == '+') &&
          name[1] == '[')                       /* Got a method name.  */
@@ -1029,8 +1064,7 @@ classes_info (char *regexp, int from_tty)
       ALL_MSYMBOLS (objfile, msymbol)
        {
          QUIT;
-         if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
-           name = SYMBOL_NAME (msymbol);
+         name = SYMBOL_NATURAL_NAME (msymbol);
          if (name &&
             (name[0] == '-' || name[0] == '+') &&
              name[1] == '[')                   /* Got a method name.  */
@@ -1047,8 +1081,7 @@ classes_info (char *regexp, int from_tty)
          char *p = aclass;
 
          QUIT;
-         if ((name = SYMBOL_DEMANGLED_NAME (sym_arr[ix])) == NULL)
-           name = SYMBOL_NAME (sym_arr[ix]);
+         name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
          name += 2;
          if (p[0] && specialcmp(name, p) == 0)
            continue;   /* Seen this one already (not unique).  */
@@ -1265,7 +1298,7 @@ parse_method (char *method, char *type, char **class,
   return s2;
 }
 
-void
+static void
 find_methods (struct symtab *symtab, char type, 
              const char *class, const char *category, 
              const char *selector, struct symbol **syms, 
@@ -1304,14 +1337,12 @@ find_methods (struct symtab *symtab, char type,
        continue;
 
       if (symtab)
-       if ((SYMBOL_VALUE_ADDRESS (msymbol) <  block->startaddr) ||
-           (SYMBOL_VALUE_ADDRESS (msymbol) >= block->endaddr))
+       if ((SYMBOL_VALUE_ADDRESS (msymbol) <  BLOCK_START (block)) ||
+           (SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block)))
          /* Not in the specified symtab.  */
          continue;
 
-      symname = SYMBOL_DEMANGLED_NAME (msymbol);
-      if (symname == NULL)
-       symname = SYMBOL_NAME (msymbol);
+      symname = SYMBOL_NATURAL_NAME (msymbol);
       if (symname == NULL)
        continue;
 
@@ -1347,10 +1378,8 @@ find_methods (struct symtab *symtab, char type,
       sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));
       if (sym != NULL)
         {
-          const char    *newsymname = SYMBOL_DEMANGLED_NAME (sym);
+          const char *newsymname = SYMBOL_NATURAL_NAME (sym);
          
-          if (newsymname == NULL)
-            newsymname = SYMBOL_NAME (sym);
           if (strcmp (symname, newsymname) == 0)
             {
               /* Found a high-level method sym: swap it into the
@@ -1445,7 +1474,7 @@ char *find_imps (struct symtab *symtab, struct block *block,
     if (msym != NULL) 
       {
        if (syms)
-         syms[csym] = msym;
+         syms[csym] = (struct symbol *)msym;
        csym++;
       }
   }
@@ -1522,7 +1551,7 @@ void
 print_object_command (char *args, int from_tty)
 {
   struct value *object, *function, *description;
-  CORE_ADDR string_addr;
+  CORE_ADDR string_addr, object_addr;
   int i = 0;
   char c = -1;
 
@@ -1536,22 +1565,23 @@ print_object_command (char *args, int from_tty)
       make_cleanup (free_current_contents, &expr);
     int pc = 0;
 
-#if 1
     object = expr->language_defn->evaluate_exp (builtin_type_void_data_ptr,
                                                expr, &pc, EVAL_NORMAL);
-#else
-    object = evaluate_subexp (builtin_type_void_data_ptr, 
-                             expr, &pc, EVAL_NORMAL);
-#endif
     do_cleanups (old_chain);
   }
 
-  if (!(function = find_function_in_inferior ("_NSPrintForDebugger")))
+  /* Validate the address for sanity.  */
+  object_addr = value_as_long (object);
+  read_memory (object_addr, &c, 1);
+
+  function = find_function_in_inferior ("_NSPrintForDebugger");
+  if (function == NULL)
     error ("Unable to locate _NSPrintForDebugger in child process");
 
   description = call_function_by_hand (function, 1, &object);
 
-  if ((string_addr = value_as_long (description)) == 0)
+  string_addr = value_as_long (description);
+  if (string_addr == 0)
     error ("object returns null description");
 
   read_memory (string_addr + i++, &c, 1);
@@ -1575,7 +1605,7 @@ print_object_command (char *args, int from_tty)
 struct objc_methcall {
   char *name;
  /* Return instance method to be called.  */
-  CORE_ADDR (*stop_at) (CORE_ADDR);
+  int (*stop_at) (CORE_ADDR, CORE_ADDR *);
   /* Start of pc range corresponding to method invocation.  */
   CORE_ADDR begin;
   /* End of pc range corresponding to method invocation.  */
@@ -1647,13 +1677,13 @@ find_objc_msgsend (void)
  */
 
 struct objc_submethod_helper_data {
-  CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *);
+  int (*f) (CORE_ADDR, CORE_ADDR *);
   CORE_ADDR pc;
   CORE_ADDR *new_pc;
 };
 
 int 
-find_objc_msgcall_submethod_helper (PTR arg)
+find_objc_msgcall_submethod_helper (void * arg)
 {
   struct objc_submethod_helper_data *s = 
     (struct objc_submethod_helper_data *) arg;
@@ -1665,7 +1695,7 @@ find_objc_msgcall_submethod_helper (PTR arg)
 }
 
 int 
-find_objc_msgcall_submethod (CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *),
+find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
                             CORE_ADDR pc, 
                             CORE_ADDR *new_pc)
 {
@@ -1676,7 +1706,7 @@ find_objc_msgcall_submethod (CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *),
   s.new_pc = new_pc;
 
   if (catch_errors (find_objc_msgcall_submethod_helper,
-                   (PTR) &s,
+                   (void *) &s,
                    "Unable to determine target of Objective-C method call (ignoring):\n",
                    RETURN_MASK_ALL) == 0) 
     return 1;
@@ -1690,7 +1720,10 @@ find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc)
   unsigned int i;
 
   find_objc_msgsend ();
-  if (new_pc != NULL) { *new_pc = 0; }
+  if (new_pc != NULL)
+    {
+      *new_pc = 0;
+    }
 
   for (i = 0; i < nmethcalls; i++) 
     if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end)) 
@@ -1714,7 +1747,7 @@ _initialize_objc_language (void)
   add_info ("classes", classes_info,       /* INFO CLASSES   command.  */
            "All Objective-C classes, or those matching REGEXP.");
   add_com ("print-object", class_vars, print_object_command, 
-          "Ask an Objective-C object to print itself.\n");
+          "Ask an Objective-C object to print itself.");
   add_com_alias ("po", "print-object", class_vars, 1);
 }