[PATCH] Objective-C language support.

Adam Fedor
2002-09-18T15:24:25Z

[-- Attachment #1: Type: text/plain, Size: 3011 bytes --]

This patch adds Objective-C language support to gdb based upon a patch
provided by Apple Computer Inc from their version of gdb. Note that the
patch only contains changes to existing files. New files (objc-lang.h,
objc-lang.c, objc-exp.y) and a gdb.objc testsuite directory are located at

ftp://ftp.gnustep.org/pub/gnustep/contrib/gdb-objc-patch.tar.gz

gdb ChangeLog
--------------
2002-09-17 Adam Fedor <fedor@gnu.org>

* Add Objective-C language support to gdb (mostly from a patch
provided by Apple Computer, Inc.).
* Makefile.in: Add rules for objc files. Extra dependencies for
changed files
* breakpoint.c (parse_breakpoint_sals): Ignore ObjC method
names when checking default.

* completer.c (skip_quoted): Take additional argument.
* completer.h: Update definition of skip_quoted.
* c-exp.y: Update for change in skip_quoted.
* jv-exp.y: Likewise.
* p-exp.y: Likewise.
* defs.h (enum language): Add language_objc. Update definitions.

* elfread.c (elf_symtab_read): Skip ObjC symbols.

* expression.h: New ops NSSTRING, SELECTOR, MSGCALL, and SELF.
* eval.c (evaludate_subexp): Remove static attribute.
(evaluate_subexp_standard): Handle new ops.
* expprint.c (print_subexp): Likewise.
(op_name): Likewise.
* parse.c: Likewise.

* infrun.c (handle_inferior_event): Step into ObjC method call.

* language.c (binop_result_type): Add language_objc to case.
(integral_type): Likewise.
(character_type): Likewise.
(string_type): Likewise.
(boolean_type): Likewise.
(structured_type): Likewise.
(binop_type_check): Likewise.
* language.h (CAST_IS_CONVERSION): Likewise.

* linespec.c (decode_line_1): Handle ObjC methods.

* maint.c (maintenance_demangle): Demangle ObjC names.

* objc-exp.y: New file
* objc-lang.h: Likewise.
* objc-lang.c: Likewise.

* parser-defs.h (struct objc_class_str): New struct.
* printfcmd.c (address_info): Print 'self' for ObjC.
* source.c (print_source_lines): Update comments.
* stabsread.c (stabsread_objc_colon): New function.
(define_symbol): Use it.
* stabsread.h: Declare it.

* symfile.c (init_filename_language_table): Add ObjC extensions.

* symtab.h: New objc_specific struct.
(SYMBOL_INIT_LANGUAGE_SPECIFIC): Handle ObjC.
(SYMBOL_DEMANGLED_NAME): Likewise.
* symtab.c (symbol_init_demangled_name): Demangle ObjC symbols.
(make_symbol_completion_list): Likewise.

* utils.c (puts_filtered_tabular): New function.
(fprintf_symbol_filtered): Get ObjC demangled name.
* valops.c (call_function_by_hand_expecting_type): New function.
(value_of_local): New function.
(value_of_this): Use it.
* values.h: Define functions.

gdb/doc ChangeLog:
-----------------
2002-09-17 Adam Fedor <fedor@gnu.org>

* gdb.texinfo: Add ObjC documentation.

gdb/testsuite ChangeLog:
-----------------
2002-09-17 Adam Fedor <fedor@gnu.org>

* configure.in: Add gdb.objc dir
* gdb.base/default.exp: Update for ObjC in output.
* gdb.base/help.exp: Likewise.
* gdb.base/maint.exp: Likewise.
* gdb.objc/: New testsuite dir

[-- Attachment #2: current-gdb-objc.patch --]
[-- Type: text/plain, Size: 78449 bytes --]

Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.259
diff -u -p -r1.259 Makefile.in
--- gdb/Makefile.in 17 Sep 2002 04:44:21 -0000 1.259
+++ gdb/Makefile.in 17 Sep 2002 19:29:47 -0000
@@ -680,6 +680,7 @@ mipsnbsd_tdep_h = mipsnbsd-tdep.h
monitor_h = monitor.h
nbsd_tdep_h = nbsd-tdep.h
ns32k_tdep_h = ns32k-tdep.h $(osabi_h)
+objc_lang_h = objc-lang.h
objfiles_h = objfiles.h $(gdb_obstack_h) $(symfile_h)
ocd_h = ocd.h
osabi_h = osabi.h
@@ -832,7 +833,7 @@ COMMON_OBS = version.o blockframe.o brea
exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
dbxread.o coffread.o elfread.o \
dwarfread.o dwarf2read.o mipsread.o stabsread.o corefile.o \
- c-lang.o f-lang.o \
+ c-lang.o objc-lang.o f-lang.o \
ui-out.o cli-out.o \
varobj.o wrapper.o \
jv-lang.o jv-valprint.o jv-typeprint.o \
@@ -853,10 +854,13 @@ SUBDIRS = @SUBDIRS@

# For now, shortcut the "configure GDB for fewer languages" stuff.
YYFILES = c-exp.tab.c \
+ objc-exp.tab.c \
ada-exp.tab.c \
jv-exp.tab.c \
f-exp.tab.c m2-exp.tab.c p-exp.tab.c
+
YYOBJ = c-exp.tab.o \
+ objc-exp.tab.o \
jv-exp.tab.o \
f-exp.tab.o m2-exp.tab.o p-exp.tab.o

@@ -1131,6 +1135,7 @@ local-maintainer-clean:
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
rm -f c-exp.tab.c \
+ objc-exp.tab.c \
ada-lex.c ada-exp.tab.c \
jv-exp.tab \
f-exp.tab.c m2-exp.tab.c p-exp.tab.c
@@ -1227,6 +1232,22 @@ c-exp.tab.c: c-exp.y
mv c-exp.new ./c-exp.tab.c

# See comments above ...
+.PRECIOUS: objc-exp.tab.c
+objc-exp.tab.o: objc-exp.tab.c
+objc-exp.tab.c: objc-exp.y
+ $(SHELL) $(YLWRAP) "$(YACC)" $(srcdir)/objc-exp.y y.tab.c objc-exp.tmp -- $(YFLAGS)
+ -sed -e '/extern.*malloc/d' \
+ -e '/extern.*realloc/d' \
+ -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' \
+ -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' \
+ -e '/^#line.*y.tab.c/d' \
+ < objc-exp.tmp > objc-exp.new
+ -rm objc-exp.tmp
+ mv objc-exp.new ./objc-exp.tab.c
+
+# See comments above ...
.PRECIOUS: jv-exp.tab.c
jv-exp.tab.o: jv-exp.tab.c
jv-exp.tab.c: jv-exp.y
@@ -1441,6 +1462,10 @@ c-exp.tab.o: c-exp.tab.c $(defs_h) $(gdb
$(value_h) $(parser_defs_h) $(language_h) $(c_lang_h) $(bfd_h) \
$(symfile_h) $(objfiles_h)

+objc-exp.tab.o: objc-exp.tab.c $(objc_lang_h) $(defs_h) $(expression_h) \
+ $(gdbtypes_h) $(language_h) $(parser_defs_h) $(symtab_h) $(value_h) \
+ $(bfd_h) $(objfiles_h) $(symfile_h)
+
jv-exp.tab.o: jv-exp.tab.c jv-lang.h $(defs_h) $(expression_h) \
$(gdbtypes_h) $(language_h) $(parser_defs_h) $(symtab_h) $(value_h) \
$(bfd_h) $(objfiles_h) $(symfile_h)
@@ -1645,7 +1670,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h)
environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
- $(f_lang_h) $(cp_abi_h)
+ $(f_lang_h) $(cp_abi_h) $(objc_lang_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@@ -1654,7 +1679,7 @@ exec.o: exec.c $(defs_h) $(frame_h) $(in
$(language_h) $(symfile_h) $(objfiles_h) $(completer_h) $(value_h) \
$(gdb_string_h) $(gdbcore_h) $(gdb_stat_h) $(xcoffsolib_h)
expprint.o: expprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
- $(value_h) $(language_h) $(parser_defs_h)
+ $(value_h) $(language_h) $(parser_defs_h) $(target_h) $(gdb_string_h)
f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \
$(valprint_h)
Index: gdb/breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.86
diff -u -p -r1.86 breakpoint.c
--- gdb/breakpoint.c 5 Sep 2002 01:28:14 -0000 1.86
+++ gdb/breakpoint.c 17 Sep 2002 19:29:52 -0000
@@ -4618,9 +4618,11 @@ parse_breakpoint_sals (char **address,
current_source_symtab (which is decode_line_1's default). This
should produce the results we want almost all of the time while
leaving default_breakpoint_* alone. */
+ /* also ignore objc method name */
if (default_breakpoint_valid
&& (!current_source_symtab
- || (strchr ("+-", (*address)[0]) != NULL)))
+ || ((strchr ("+-", (*address)[0]) != NULL)
+ && ((*address)[1] != '['))))
*sals = decode_line_1 (address, 1, default_breakpoint_symtab,
default_breakpoint_line, addr_string);
else
Index: gdb/c-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/c-exp.y,v
retrieving revision 1.12
diff -u -p -r1.12 c-exp.y
--- gdb/c-exp.y 3 Sep 2002 02:45:56 -0000 1.12
+++ gdb/c-exp.y 17 Sep 2002 19:29:53 -0000
@@ -49,6 +49,7 @@ Foundation, Inc., 59 Temple Place - Suit
#include "bfd.h" /* Required by objfiles.h. */
#include "symfile.h" /* Required by objfiles.h. */
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "completer.h"

/* Flag indicating we're dealing with HP-compiled objects */
extern int hp_som_som_object_present;
@@ -1321,7 +1322,9 @@ yylex ()
c = *lexptr++;
if (c != '\'')
{
- namelen = skip_quoted (tokstart) - tokstart;
+ namelen = skip_quoted (tokstart,
+ get_gdb_completer_word_break_characters())
+ - tokstart;
if (namelen > 2)
{
lexptr = tokstart + namelen;
Index: gdb/completer.c
===================================================================
RCS file: /cvs/src/src/gdb/completer.c,v
retrieving revision 1.11
diff -u -p -r1.11 completer.c
--- gdb/completer.c 24 Mar 2002 00:40:35 -0000 1.11
+++ gdb/completer.c 17 Sep 2002 19:29:53 -0000
@@ -683,7 +683,7 @@ line_completion_function (char *text, in
location after the "word". */

char *
-skip_quoted (char *str)
+skip_quoted (char *str, char *breakchars)
{
char quote_char = '\0';
char *scan;
@@ -705,7 +705,7 @@ skip_quoted (char *str)
/* Found start of a quoted string. */
quote_char = *scan;
}
- else if (strchr (gdb_completer_word_break_characters, *scan))
+ else if (strchr (breakchars, *scan))
{
break;
}
Index: gdb/completer.h
===================================================================
RCS file: /cvs/src/src/gdb/completer.h,v
retrieving revision 1.6
diff -u -p -r1.6 completer.h
--- gdb/completer.h 18 Feb 2002 01:12:38 -0000 1.6
+++ gdb/completer.h 17 Sep 2002 19:29:53 -0000
@@ -39,6 +39,6 @@ extern char *get_gdb_completer_quote_cha

/* Exported to linespec.c */

-extern char *skip_quoted (char *str);
+extern char *skip_quoted (char *str, char *);

#endif /* defined (COMPLETER_H) */
Index: gdb/defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.94
diff -u -p -r1.94 defs.h
--- gdb/defs.h 1 Aug 2002 17:18:32 -0000 1.94
+++ gdb/defs.h 17 Sep 2002 19:29:59 -0000
@@ -208,6 +208,7 @@ enum language
language_auto, /* Placeholder for automatic setting */
language_c, /* C */
language_cplus, /* C++ */
+ language_objc, /* Objective-C */
language_java, /* Java */
/* OBSOLETE language_chill, */ /* Chill */
language_fortran, /* Fortran */
@@ -304,6 +305,10 @@ extern int inside_main_func (CORE_ADDR p

/* OBSOLETE extern char *chill_demangle (const char *); */

+/* From objc-lang.c, for the moment. (FIXME) */
+
+extern char *objc_demangle (const char *);
+
/* From utils.c */

extern void initialize_utils (void);
@@ -445,6 +450,8 @@ extern void puts_filtered (const char *)

extern void puts_unfiltered (const char *);

+extern void puts_filtered_tabular (char *string, int width, int right);
+
extern void puts_debug (char *prefix, char *string, char *suffix);

extern void vprintf_filtered (const char *, va_list) ATTR_FORMAT (printf, 1, 0);
@@ -531,7 +538,7 @@ extern void print_transfer_performance (

typedef void initialize_file_ftype (void);

-extern char *skip_quoted (char *);
+extern char *skip_quoted (char *, char *);

extern char *gdb_readline (char *);

Index: gdb/elfread.c
===================================================================
RCS file: /cvs/src/src/gdb/elfread.c,v
retrieving revision 1.23
diff -u -p -r1.23 elfread.c
--- gdb/elfread.c 24 Jul 2002 23:51:35 -0000 1.23
+++ gdb/elfread.c 17 Sep 2002 19:29:59 -0000
@@ -349,7 +349,12 @@ elf_symtab_read (struct objfile *objfile
}
else if (sym->section->flags & SEC_CODE)
{
- if (sym->flags & BSF_GLOBAL)
+ if (sym->name[0] == '.' && (strncmp (sym->name + 1, "objc_", 4) == 0))
+ {
+ /* Looks like an Objective-C special symbol */
+ continue;
+ }
+ else if (sym->flags & BSF_GLOBAL)
{
ms_type = mst_text;
}
Index: gdb/eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.23
diff -u -p -r1.23 eval.c
--- gdb/eval.c 1 Aug 2002 17:18:32 -0000 1.23
+++ gdb/eval.c 17 Sep 2002 19:30:03 -0000
@@ -30,6 +30,7 @@
#include "frame.h"
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
+#include "objc-lang.h"
#include "cp-abi.h"

/* Defined in symtab.c */
@@ -49,9 +50,6 @@ static struct value *evaluate_subexp_for
static struct value *evaluate_subexp_for_address (struct expression *,
int *, enum noside);

-static struct value *evaluate_subexp (struct type *, struct expression *,
- int *, enum noside);
-
static char *get_label (struct expression *, int *);

static struct value *evaluate_struct_tuple (struct value *,
@@ -62,7 +60,7 @@ static LONGEST init_array_element (struc
struct expression *, int *, enum noside,
LONGEST, LONGEST);

-static struct value *
+struct value *
evaluate_subexp (struct type *expect_type, register struct expression *exp,
register int *pos, enum noside noside)
{
@@ -468,6 +466,15 @@ evaluate_subexp_standard (struct type *e
goto nosideret;
return value_string (&exp->elts[pc + 2].string, tem);

+ case OP_NSSTRING: /* Objective C Foundation Class NSString constant */
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ if (noside == EVAL_SKIP)
+ {
+ goto nosideret;
+ }
+ return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);
+
case OP_BITSTRING:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos)
@@ -664,6 +671,291 @@ evaluate_subexp_standard (struct type *e
return arg2;
}

+ case OP_SELECTOR:
+ { /* Objective C @selector operator */
+ char *sel = &exp->elts[pc + 2].string;
+ int len = longest_to_int (exp->elts[pc + 1].longconst);
+
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (sel[len] != 0)
+ sel[len] = 0; /* make sure terminated */
+ return value_from_longest (lookup_pointer_type (builtin_type_void),
+ lookup_child_selector (sel));
+ }
+
+ case OP_MSGCALL:
+ { /* Objective C message (method) call */
+
+ static unsigned long responds_selector = 0;
+ static unsigned long method_selector = 0;
+ static unsigned int selector_generation = 0;
+
+ unsigned long selector = 0;
+
+ int using_gcc = 0;
+ int struct_return = 0;
+
+ static struct value *msg_send = NULL;
+ static struct value *msg_send_stret = NULL;
+ static struct value *msg_send_typed = NULL;
+ static int gnu_runtime = 0;
+
+ struct value * target = NULL;
+ struct value * method = NULL;
+ struct value * called_method = NULL;
+
+ struct value * ret = NULL;
+ struct symbol *sym = NULL;
+ CORE_ADDR addr = 0;
+
+ /* First evaluate the target (class or object) of the message */
+ (*pos) += 3;
+
+ nargs = exp->elts[pc + 2].longconst;
+ argvec = (struct value **) alloca (sizeof (struct value *)
+ * (nargs + 5));
+
+ target = evaluate_subexp (0, exp, pos, (noside == EVAL_AVOID_SIDE_EFFECTS) ? EVAL_NORMAL : noside);
+ selector = exp->elts[pc + 1].longconst;
+
+ if (value_as_long (target) == 0)
+ return value_from_longest (builtin_type_long, 0);
+
+ if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0))
+ gnu_runtime = 1;
+
+ if (gnu_runtime)
+ {
+ msg_send = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_typed = find_function_in_inferior ("objc_msg_lookup");
+ }
+ else
+ {
+ msg_send = find_function_in_inferior ("objc_msgSend");
+ msg_send_stret = find_function_in_inferior ("objc_msgSend_stret");
+ msg_send_typed = find_function_in_inferior ("objc_msgSend");
+ }
+
+ /* Verify target responds to method selector. This logic needs
+ * work: not sure of GNU variant's name. Must also account for
+ * new (NSObject) and old (Object) worlds
+ */
+
+ if (1)
+ {
+ responds_selector = lookup_child_selector ("respondsToSelector:");
+ if (responds_selector == 0)
+ responds_selector = lookup_child_selector ("respondsTo:");
+
+ if (responds_selector == 0)
+ error ("no 'respondsTo:' or 'respondsToSelector:' method");
+
+ if (gnu_runtime)
+ {
+ method_selector = lookup_child_selector ("methodFor:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodForSelector:");
+ }
+ else
+ {
+ method_selector = lookup_child_selector ("methodForSelector:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodFor:");
+ }
+
+ if (method_selector == 0)
+ error ("no 'methodFor:' or 'methodForSelector:' method");
+
+ }
+
+ /* call "respondsToSelector:" method, to make sure that
+ * the target class implements the user's desired method selector
+ */
+
+ argvec[0] = msg_send_typed;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, responds_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand_expecting_type (argvec[0], NULL, 3, argvec + 1, 1);
+ if (gnu_runtime)
+ {
+ /* objc_msg_lookup returns a pointer */
+ argvec[0] = ret; /* prepare to call the method */
+ ret = call_function_by_hand_expecting_type (argvec[0], NULL, 3, argvec + 1, 1);
+ }
+ if (value_as_long (ret) == 0)
+ error ("Target does not respond to this message selector.");
+
+ /* call "methodForSelector:" method, to get the address of a
+ * function method that implements this selector for this class.
+ * If we can find a symbol at that address, then we know the
+ * return type, parameter types etc. (that's a good thing).
+ */
+
+ argvec[0] = msg_send_typed;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, method_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand_expecting_type (argvec[0], NULL, 3, argvec + 1, 1);
+ if (gnu_runtime)
+ {
+ argvec[0] = ret; /* prepare to call the method */
+ ret = call_function_by_hand_expecting_type (argvec[0], NULL, 3, argvec + 1, 1);
+ }
+
+ /* ret should now be the selector */
+
+ addr = value_as_long (ret);
+ if (addr)
+ {
+ /* is it a high_level symbol? */
+
+#ifdef GDB_TARGET_IS_HPPA
+ CORE_ADDR tmp;
+ /* code and comment lifted from hppa-tdep.c -- unfortunately
+ there is no builtin function to do this for me. */
+ /* If bit 30 (counting from the left) is on, then addr is the
+ address of the PLT entry for this function, not the address
+ of the function itself. Bit 31 has meaning too, but only
+ for MPE. */
+ if (addr & 0x2)
+ addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
+ if (tmp = skip_trampoline_code (addr, 0))
+ addr = tmp; /* in case of trampoline code */
+#endif
+
+ sym = find_pc_function (addr);
+ if (sym != NULL)
+ method = value_of_variable (sym, 0);
+ }
+
+ /* If we found a method with symbol information, check to see
+ * if it returns a struct. Otherwise assume it doesn't.
+ */
+
+ if (method)
+ {
+ struct block *b;
+ CORE_ADDR funaddr;
+ struct type *value_type;
+
+ funaddr = find_function_addr (method, &value_type);
+
+ b = block_for_pc (funaddr);
+
+ /* If compiled without -g, assume GCC 2. */
+ using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
+
+ CHECK_TYPEDEF (value_type);
+
+ if ((value_type == NULL)
+ || (TYPE_CODE(value_type) == TYPE_CODE_ERROR))
+ {
+ if (expect_type != NULL)
+ value_type = expect_type;
+ }
+
+ struct_return = using_struct_return (method, funaddr, value_type, using_gcc);
+ }
+ else if (expect_type != NULL)
+ {
+ struct_return = using_struct_return (NULL, addr, check_typedef (expect_type), using_gcc);
+ }
+
+ /* Found a function symbol. Now we will substitute its
+ * value in place of the message dispatcher (obj_msgSend),
+ * so that we call the method directly instead of thru
+ * the dispatcher. The main reason for doing this is that
+ * we can now evaluate the return value and parameter values
+ * according to their known data types, in case we need to
+ * do things like promotion, dereferencing, special handling
+ * of structs and doubles, etc.
+ *
+ * We want to use the type signature of 'method', but still
+ * jump to objc_msgSend() or objc_msgSend_stret() to better
+ * mimic the behavior of the runtime.
+ */
+
+ if (method)
+ {
+ if (TYPE_CODE (VALUE_TYPE (method)) != TYPE_CODE_FUNC)
+ error ("method address has symbol information with non-function type; skipping");
+ if (struct_return)
+ VALUE_ADDRESS (method) = value_as_address (msg_send_stret);
+ else
+ VALUE_ADDRESS (method) = value_as_address (msg_send);
+ called_method = method;
+ }
+ else
+ {
+ if (struct_return)
+ called_method = msg_send_stret;
+ else
+ called_method = msg_send;
+ }
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type, call an
+ error. This can happen if somebody tries to turn a variable into
+ a function call. This is here because people often want to
+ call, eg, strcmp, which gdb doesn't know is a function. If
+ gdb isn't asked for it's opinion (ie. through "whatis"),
+ it won't offer it. */
+
+ struct type *type = VALUE_TYPE (called_method);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ type = TYPE_TARGET_TYPE (type);
+
+ if (type)
+ {
+ if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
+ return allocate_value (expect_type);
+ else
+ return allocate_value (type);
+ }
+ else
+ error ("Expression of type other than \"method returning ...\" used as a method");
+ }
+
+ /* Now depending on whether we found a symbol for the method,
+ * we will either call the runtime dispatcher or the method directly.
+ */
+
+ argvec[0] = called_method;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, selector);
+ /* user-supplied arguments */
+ for (tem = 0; tem < nargs; tem++)
+ argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem + 3] = 0;
+
+ if (gnu_runtime && (method != NULL))
+ {
+ ret = call_function_by_hand_expecting_type (argvec[0], NULL, nargs + 2, argvec + 1, 1);
+ /* objc_msg_lookup returns a pointer */
+ argvec[0] = ret;
+ ret = call_function_by_hand_expecting_type (argvec[0], expect_type, nargs + 2, argvec + 1, 1);
+ }
+ else
+ ret = call_function_by_hand_expecting_type (argvec[0], expect_type, nargs + 2, argvec + 1, 1);
+
+ return ret;
+ }
+ break;
+
case OP_FUNCALL:
(*pos) += 2;
op = exp->elts[*pos].opcode;
@@ -1745,6 +2037,10 @@ evaluate_subexp_standard (struct type *e
case OP_THIS:
(*pos) += 1;
return value_of_this (1);
+
+ case OP_SELF:
+ (*pos) += 1;
+ return value_of_local ("self", 1);

case OP_TYPE:
error ("Attempt to use a type name as an expression");
Index: gdb/expprint.c
===================================================================
RCS file: /cvs/src/src/gdb/expprint.c,v
retrieving revision 1.8
diff -u -p -r1.8 expprint.c
--- gdb/expprint.c 1 Aug 2002 17:18:32 -0000 1.8
+++ gdb/expprint.c 17 Sep 2002 19:30:04 -0000
@@ -26,6 +26,9 @@
#include "value.h"
#include "language.h"
#include "parser-defs.h"
+#include "target.h"
+
+#include "gdb_string.h"

#ifdef HAVE_CTYPE_H
#include <ctype.h>
@@ -174,6 +177,51 @@ print_subexp (register struct expression
fprintf_unfiltered (stream, "B'<unimplemented>'");
return;

+ case OP_NSSTRING: /* Objective C Foundation Class NSString constant */
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ fputs_filtered ("@\"", stream);
+ LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 1, 0);
+ fputs_filtered ("\"", stream);
+ return;
+
+ case OP_MSGCALL:
+ { /* Objective C message (method) call */
+ char *selector;
+ (*pos) += 3;
+ nargs = longest_to_int (exp->elts[pc + 2].longconst);
+ fprintf_unfiltered (stream, "[");
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ if (0 == target_read_string (exp->elts[pc + 1].longconst,
+ &selector, 1024, NULL))
+ {
+ error ("bad selector");
+ return;
+ }
+ /* NOTE: "selector" was malloc'd by target_read_string; must be freed */
+ if (nargs)
+ {
+ char *s, *nextS;
+ s = alloca (strlen (selector) + 1);
+ strcpy (s, selector);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ nextS = strchr (s, ':');
+ *nextS = '\0';
+ fprintf_unfiltered (stream, " %s: ", s);
+ s = nextS + 1;
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ }
+ else
+ {
+ fprintf_unfiltered (stream, " %s", selector);
+ }
+ fprintf_unfiltered (stream, "]");
+ free (selector);
+ return;
+ }
+
case OP_ARRAY:
(*pos) += 3;
nargs = longest_to_int (exp->elts[pc + 2].longconst);
@@ -381,6 +429,13 @@ print_subexp (register struct expression
error ("Invalid expression");
break;

+ /* Objective-C ops */
+
+ case OP_SELF:
+ ++(*pos);
+ fputs_filtered ("self", stream); /* the ObjC equivalent of "this" */
+ return;
+
/* C++ ops */

case OP_THIS:
@@ -681,6 +736,8 @@ op_name (int opcode)
return "STRUCTOP_PTR";
case OP_THIS:
return "OP_THIS";
+ case OP_SELF:
+ return "OP_SELF";
case OP_SCOPE:
return "OP_SCOPE";
case OP_TYPE:
Index: gdb/expression.h
===================================================================
RCS file: /cvs/src/src/gdb/expression.h,v
retrieving revision 1.4
diff -u -p -r1.4 expression.h
--- gdb/expression.h 1 Aug 2002 17:18:32 -0000 1.4
+++ gdb/expression.h 17 Sep 2002 19:30:05 -0000
@@ -181,6 +181,12 @@ enum exp_opcode
making three exp_elements. */
OP_FUNCALL,

+ /* OP_MSGCALL is followed by a string in the next exp_element and then an
+ integer. The string is the selector string. The integer is the number
+ of arguments to the message call. That many plus one values are used,
+ the first one being the object pointer. This is an Objective C message */
+ OP_MSGCALL,
+
/* This is EXACTLY like OP_FUNCALL but is semantically different.
In F77, array subscript expressions, substring expressions
and function calls are all exactly the same syntactically. They may
@@ -273,11 +279,17 @@ enum exp_opcode
STRUCTOP_STRUCT,
STRUCTOP_PTR,

- /* C++ */
- /* OP_THIS is just a placeholder for the class instance variable.
+ /* C++: OP_THIS is just a placeholder for the class instance variable.
It just comes in a tight (OP_THIS, OP_THIS) pair. */
OP_THIS,

+ /* Objective C: "@selector" pseudo-operator */
+ OP_SELECTOR,
+
+ /* Objective-C: OP_SELF is just a placeholder for the class instance
+ variable. It just comes in a tight (OP_SELF, OP_SELF) pair. */
+ OP_SELF,
+
/* OP_SCOPE surrounds a type name and a field name. The type
name is encoded as one element, but the field name stays as
a string, which, of course, is variable length. */
@@ -305,7 +317,10 @@ enum exp_opcode
OP_NAME,

/* An unparsed expression. Used for Scheme (for now at least) */
- OP_EXPRSTRING
+ OP_EXPRSTRING,
+
+ /* An Objective C Foundation Class NSString constant */
+ OP_NSSTRING,
};

union exp_element
@@ -369,6 +384,10 @@ enum noside

extern struct value *evaluate_subexp_standard
(struct type *, struct expression *, int *, enum noside);
+
+extern struct value *evaluate_subexp (struct type *, struct expression *,
+ int *, enum noside);
+

/* From expprint.c */

Index: gdb/infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.70
diff -u -p -r1.70 infrun.c
--- gdb/infrun.c 23 Aug 2002 21:55:36 -0000 1.70
+++ gdb/infrun.c 17 Sep 2002 19:30:26 -0000
@@ -42,6 +42,7 @@
#include "inf-loop.h"
#include "regcache.h"
#include "value.h"
+#include "objc-lang.h"

/* Prototypes for local functions */

@@ -2786,6 +2787,26 @@ process_event_stop_test:
return;
}
}
+
+ /* ObjC */
+ {
+ CORE_ADDR new_stop;
+
+ if (tmp)
+ find_objc_msgcall (tmp, &new_stop);
+ else
+ find_objc_msgcall (stop_pc, &new_stop);
+
+ if (new_stop) /* step into a method call */
+ ecs->stop_func_start = new_stop;
+
+ if (new_stop)
+ {
+ tmp = SKIP_TRAMPOLINE_CODE (new_stop);
+ if (tmp != 0)
+ ecs->stop_func_start = tmp;
+ }
+ }

/* If we have line number information for the function we
are thinking of stepping into, step into it.
Index: gdb/jv-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/jv-exp.y,v
retrieving revision 1.9
diff -u -p -r1.9 jv-exp.y
--- gdb/jv-exp.y 3 Sep 2002 02:45:56 -0000 1.9
+++ gdb/jv-exp.y 17 Sep 2002 19:30:27 -0000
@@ -48,6 +48,7 @@ Foundation, Inc., 59 Temple Place - Suit
#include "bfd.h" /* Required by objfiles.h. */
#include "symfile.h" /* Required by objfiles.h. */
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "completer.h"

/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
@@ -918,7 +919,9 @@ yylex ()
c = *lexptr++;
if (c != '\'')
{
- namelen = skip_quoted (tokstart) - tokstart;
+ namelen = skip_quoted (tokstart,
+ get_gdb_completer_word_break_characters())
+ - tokstart;
if (namelen > 2)
{
lexptr = tokstart + namelen;
Index: gdb/language.c
===================================================================
RCS file: /cvs/src/src/gdb/language.c,v
retrieving revision 1.26
diff -u -p -r1.26 language.c
--- gdb/language.c 1 Aug 2002 17:18:32 -0000 1.26
+++ gdb/language.c 17 Sep 2002 19:30:31 -0000
@@ -549,6 +549,7 @@ binop_result_type (struct value *v1, str
{
case language_c:
case language_cplus:
+ case language_objc:
if (TYPE_CODE (t1) == TYPE_CODE_FLT)
return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
VALUE_TYPE (v2) : VALUE_TYPE (v1);
@@ -786,6 +787,7 @@ integral_type (struct type *type)
{
case language_c:
case language_cplus:
+ case language_objc:
return (TYPE_CODE (type) != TYPE_CODE_INT) &&
(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
case language_m2:
@@ -828,6 +830,7 @@ character_type (struct type *type)

case language_c:
case language_cplus:
+ case language_objc:
return (TYPE_CODE (type) == TYPE_CODE_INT) &&
TYPE_LENGTH (type) == sizeof (char)
? 1 : 0;
@@ -850,6 +853,7 @@ string_type (struct type *type)

case language_c:
case language_cplus:
+ case language_objc:
/* C does not have distinct string type. */
return (0);
default:
@@ -868,6 +872,7 @@ boolean_type (struct type *type)
{
case language_c:
case language_cplus:
+ case language_objc:
/* Might be more cleanly handled by having a
TYPE_CODE_INT_NOT_BOOL for (OBSOLETE) CHILL and such
languages, or a TYPE_CODE_INT_OR_BOOL for C. */
@@ -904,6 +909,7 @@ structured_type (struct type *type)
{
case language_c:
case language_cplus:
+ case language_objc:
return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
(TYPE_CODE (type) == TYPE_CODE_UNION) ||
(TYPE_CODE (type) == TYPE_CODE_ARRAY);
@@ -1124,6 +1130,7 @@ binop_type_check (struct value *arg1, st
#ifdef _LANG_c
case language_c:
case language_cplus:
+ case language_objc:
switch (op)
{
case BINOP_DIV:
Index: gdb/language.h
===================================================================
RCS file: /cvs/src/src/gdb/language.h,v
retrieving revision 1.11
diff -u -p -r1.11 language.h
--- gdb/language.h 1 Aug 2002 17:18:32 -0000 1.11
+++ gdb/language.h 17 Sep 2002 19:30:36 -0000
@@ -288,7 +288,8 @@ language_mode;
/* "cast" really means conversion */
/* FIXME -- should be a setting in language_defn */
#define CAST_IS_CONVERSION (current_language->la_language == language_c || \
- current_language->la_language == language_cplus)
+ current_language->la_language == language_cplus || \
+ current_language->la_language == language_objc)

extern void language_info (int);

Index: gdb/linespec.c
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.21
diff -u -p -r1.21 linespec.c
--- gdb/linespec.c 11 May 2002 22:46:19 -0000 1.21
+++ gdb/linespec.c 17 Sep 2002 19:30:39 -0000
@@ -31,6 +31,8 @@
#include "completer.h"
#include "cp-abi.h"

+extern int allow_objc_selectors_flag;
+
/* Prototype for one function in parser-defs.h,
instead of including that entire file. */

@@ -40,6 +42,11 @@ extern char *find_template_name_end (cha

extern char *operator_chars (char *, char **);

+/* From objc-lang.h. Included here to avoid conflict with other prototypes */
+extern char *find_imps (struct symtab *symtab, struct block *block,
+ char *method, struct symbol **syms, unsigned int *nsym,
+ unsigned int *ndebug);
+
/* Prototypes for local functions */

static void cplusplus_error (const char *name, const char *fmt, ...) ATTR_FORMAT (printf, 2, 3);
@@ -531,13 +538,13 @@ decode_line_1 (char **argptr, int funfir
int i1;
int is_quoted;
int is_quote_enclosed;
+ int is_objc_method = 0;
int has_parens;
int has_if = 0;
int has_comma = 0;
struct symbol **sym_arr;
struct type *t;
char *saved_arg = *argptr;
- extern char *gdb_completer_quote_characters;

INIT_SAL (&val); /* initialize to zeroes */

@@ -593,6 +600,7 @@ decode_line_1 (char **argptr, int funfir
*/

/* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+ /* Or it could be an ObjC method name with embedded ':'s */

is_quoted = (**argptr
&& strchr (get_gdb_completer_quote_characters (),
@@ -649,6 +657,15 @@ decode_line_1 (char **argptr, int funfir
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 (*p && (p[0] == ':') && (strchr ("+-", p[1]) != NULL)
+ && (p[2] == '['))
+ {
+ is_objc_method = 1;
+ has_parens = 0; /* Probably just a category name. Ignore it */
+ 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 enclosed spaces */
@@ -686,6 +703,92 @@ decode_line_1 (char **argptr, int funfir
if (has_comma)
*ii = ',';

+ /* 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.
+ */
+
+ if (allow_objc_selectors_flag && !has_if && !has_comma)
+ {
+ unsigned int i2;
+ char *copy = NULL;
+ struct block *block;
+
+ if (s)
+ block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ else
+ block = get_selected_block (NULL);
+
+
+ copy = find_imps (s, 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 (s, block, *argptr, sym_arr, &i1, &i2);
+ *argptr = copy;
+ if (is_quoted)
+ *argptr = *argptr + 1;
+ }
+
+ /* 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)
+ {
+ /* exactly one matching method */
+ extern int info_verbose;
+
+ 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_NAME (sym_arr[0]), SYMBOL_NAME (sym)) != 0)
+ {
+ warning ("debugging symbol \"%s\" does not match selector; ignoring", SYMBOL_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_SOURCE_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 -- user must choose one or more */
+ return decode_line_2 (sym_arr, i2, funfirstline, canonical);
+ }
+ }
+
if ((p[0] == ':' || p[0] == '.') && !has_parens)
{
/* C++ */
@@ -754,7 +857,8 @@ decode_line_1 (char **argptr, int funfir
&& strchr (get_gdb_completer_quote_characters (),
**argptr) != NULL)
{
- p = skip_quoted (*argptr);
+ p = skip_quoted (*argptr,
+ get_gdb_completer_word_break_characters());
*argptr = *argptr + 1;
}
else
@@ -1081,20 +1185,29 @@ decode_line_1 (char **argptr, int funfir
Find the next token (everything up to end or next whitespace). */

if (**argptr == '$') /* May be a convenience variable */
- p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1)); /* One or two $ chars possible */
+ {
+ /* One or two $ chars possible */
+ p = skip_quoted (*argptr + (((*argptr)[1] == '$') ? 2 : 1),
+ get_gdb_completer_word_break_characters());
+ }
else if (is_quoted)
{
- p = skip_quoted (*argptr);
+ p = skip_quoted (*argptr, get_gdb_completer_word_break_characters());
if (p[-1] != '\'')
error ("Unmatched single quote.");
}
+ else if (is_objc_method)
+ {
+ /* allow word separators in method names for Obj-C */
+ p = skip_quoted (*argptr, "");
+ }
else if (has_parens)
{
p = pp + 1;
}
else
{
- p = skip_quoted (*argptr);
+ p = skip_quoted (*argptr, get_gdb_completer_word_break_characters());
}

copy = (char *) alloca (p - *argptr + 1);
Index: gdb/maint.c
===================================================================
RCS file: /cvs/src/src/gdb/maint.c,v
retrieving revision 1.27
diff -u -p -r1.27 maint.c
--- gdb/maint.c 15 Jun 2002 21:07:57 -0000 1.27
+++ gdb/maint.c 17 Sep 2002 19:30:45 -0000
@@ -141,7 +141,16 @@ maintenance_demangle (char *args, int fr
}
else
{
- demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+ switch (current_language->la_language)
+ {
+ case language_objc:
+ demangled = objc_demangle (args);
+ break;
+ case language_cplus:
+ default:
+ demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+ break;
+ }
if (demangled != NULL)
{
printf_unfiltered ("%s\n", demangled);
@@ -641,7 +650,7 @@ _initialize_maint_cmds (void)
"Commands for use by GDB maintainers.\n\
Includes commands to dump specific internal GDB structures in\n\
a human readable form, to cause GDB to deliberately dump core,\n\
-to test internal functions such as the C++ demangler, etc.",
+to test internal functions such as the C++/ObjC demangler, etc.",
&maintenancelist, "maintenance ", 0,
&cmdlist);

@@ -698,7 +707,7 @@ Cause GDB to behave as if an internal er
&maintenancelist);

add_cmd ("demangle", class_maintenance, maintenance_demangle,
- "Demangle a C++ mangled name.\n\
+ "Demangle a C++/ObjC mangled name.\n\
Call internal GDB demangler routine to demangle a C++ link name\n\
and prints the result.",
&maintenancelist);
Index: gdb/p-exp.y
===================================================================
RCS file: /cvs/src/src/gdb/p-exp.y,v
retrieving revision 1.13
diff -u -p -r1.13 p-exp.y
--- gdb/p-exp.y 3 Sep 2002 02:45:56 -0000 1.13
+++ gdb/p-exp.y 17 Sep 2002 19:30:47 -0000
@@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place - Suit
#include "bfd.h" /* Required by objfiles.h. */
#include "symfile.h" /* Required by objfiles.h. */
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "completer.h"

/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
@@ -1100,8 +1101,10 @@ yylex ()
c = *lexptr++;
if (c != '\'')
{
- namelen = skip_quoted (tokstart) - tokstart;
- if (namelen > 2)
+ namelen = skip_quoted (tokstart,
+ get_gdb_completer_word_break_characters())
+ - tokstart;
+ if (namelen > 2)
{
lexptr = tokstart + namelen;
if (lexptr[-1] != '\'')
Index: gdb/parse.c
===================================================================
RCS file: /cvs/src/src/gdb/parse.c,v
retrieving revision 1.25
diff -u -p -r1.25 parse.c
--- gdb/parse.c 21 Jun 2002 14:32:10 -0000 1.25
+++ gdb/parse.c 17 Sep 2002 19:30:53 -0000
@@ -867,6 +867,11 @@ length_of_subexp (register struct expres
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
break;

+ case OP_MSGCALL: /* Objective C message (method) call */
+ oplen = 4;
+ args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
+ break;
+
case UNOP_MAX:
case UNOP_MIN:
oplen = 3;
@@ -898,6 +903,8 @@ length_of_subexp (register struct expres
/* fall through */
case OP_M2_STRING:
case OP_STRING:
+ case OP_NSSTRING: /* Objective C Foundation Class NSString constant */
+ case OP_SELECTOR: /* Objective C "@selector" pseudo-op */
case OP_NAME:
case OP_EXPRSTRING:
oplen = longest_to_int (expr->elts[endpos - 2].longconst);
@@ -936,6 +943,7 @@ length_of_subexp (register struct expres

/* C++ */
case OP_THIS:
+ case OP_SELF:
oplen = 2;
break;

@@ -1004,6 +1012,11 @@ prefixify_subexp (register struct expres
args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
break;

+ case OP_MSGCALL: /* Objective C message (method) call */
+ oplen = 4;
+ args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
+ break;
+
case UNOP_MIN:
case UNOP_MAX:
oplen = 3;
@@ -1034,6 +1047,8 @@ prefixify_subexp (register struct expres
/* fall through */
case OP_M2_STRING:
case OP_STRING:
+ case OP_NSSTRING: /* Objective C Foundation Class NSString constant */
+ case OP_SELECTOR: /* Objective C "@selector" pseudo-op */
case OP_NAME:
case OP_EXPRSTRING:
oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
@@ -1072,6 +1087,7 @@ prefixify_subexp (register struct expres

/* C++ */
case OP_THIS:
+ case OP_SELF:
oplen = 2;
break;

Index: gdb/parser-defs.h
===================================================================
RCS file: /cvs/src/src/gdb/parser-defs.h,v
retrieving revision 1.11
diff -u -p -r1.11 parser-defs.h
--- gdb/parser-defs.h 24 Jul 2002 03:03:52 -0000 1.11
+++ gdb/parser-defs.h 17 Sep 2002 19:30:53 -0000
@@ -79,6 +79,14 @@ struct symtoken
int is_a_field_of_this;
};

+struct objc_class_str
+ {
+ struct stoken stoken;
+ struct type *type;
+ int class;
+ };
+
+
/* For parsing of complicated types.
An array should be preceded in the list by the size of the array. */
enum type_pieces
@@ -215,6 +223,11 @@ struct op_print
and builtin regs. */

extern int target_map_name_to_register (char *, int);
+
+/* for parsing Objective C */
+extern void start_msglist (void);
+extern void add_msglist (struct stoken *str, int addcolon);
+extern int end_msglist (void);

/* Function used to avoid direct calls to fprintf
in the code generated by the bison parser. */
Index: gdb/printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.41
diff -u -p -r1.41 printcmd.c
--- gdb/printcmd.c 10 Sep 2002 02:04:38 -0000 1.41
+++ gdb/printcmd.c 17 Sep 2002 19:30:55 -0000
@@ -1104,7 +1104,11 @@ address_info (char *exp, int from_tty)
printf_filtered ("Symbol \"");
fprintf_symbol_filtered (gdb_stdout, exp,
current_language->la_language, DMGL_ANSI);
- printf_filtered ("\" is a field of the local class variable `this'\n");
+ printf_filtered ("\" is a field of the local class variable ");
+ if (current_language->la_language == language_objc)
+ printf_filtered ("'self'\n"); /* ObjC equivalent of "this" */
+ else
+ printf_filtered ("'this'\n");
return;
}

Index: gdb/source.c
===================================================================
RCS file: /cvs/src/src/gdb/source.c,v
retrieving revision 1.29
diff -u -p -r1.29 source.c
--- gdb/source.c 11 Jun 2002 20:36:51 -0000 1.29
+++ gdb/source.c 17 Sep 2002 19:30:56 -0000
@@ -1114,8 +1114,9 @@ print_source_lines (struct symtab *s, in

/* Print a list of files and line numbers which a user may choose from
in order to list a function which was specified ambiguously (as with
- `list classname::overloadedfuncname', for example). The vector in
- SALS provides the filenames and line numbers. */
+ `list classname::overloadedfuncname', or 'list objectiveCSelector:).
+ The vector in SALS provides the filenames and line numbers.
+ NOTE: some of the SALS may have no filename or line information! */

static void
ambiguous_line_spec (struct symtabs_and_lines *sals)
Index: gdb/stabsread.c
===================================================================
RCS file: /cvs/src/src/gdb/stabsread.c,v
retrieving revision 1.39
diff -u -p -r1.39 stabsread.c
--- gdb/stabsread.c 14 Sep 2002 02:09:39 -0000 1.39
+++ gdb/stabsread.c 17 Sep 2002 19:31:03 -0000
@@ -1273,7 +1273,7 @@ define_symbol (CORE_ADDR valu, char *str
struct objfile *objfile)
{
register struct symbol *sym;
- char *p = (char *) strchr (string, ':');
+ char *p = (char *) stabsread_objc_colon (string);
int deftype;
int synonym = 0;
register int i;
@@ -2006,7 +2006,8 @@ define_symbol (CORE_ADDR valu, char *str
a typedef for "foo". Unfortunately, cfront never makes the typedef
when translating C++ into C. We make the typedef here so that
"ptype foo" works as expected for cfront translated code. */
- else if (current_subfile->language == language_cplus)
+ else if ((current_subfile->language == language_cplus)
+ || (current_subfile->language == language_objc))
synonym = 1;

SYMBOL_TYPE (sym) = read_type (&p, objfile);
@@ -5615,6 +5616,30 @@ finish_global_stabs (struct objfile *obj
patch_block_stabs (global_symbols, global_stabs, objfile);
xfree (global_stabs);
global_stabs = NULL;
+ }
+}
+
+char *
+stabsread_objc_colon (name)
+ char *name;
+{
+ char *s = name;
+ if (s[0] == '-' || *s == '+')
+ {
+ if (s[1] != '[')
+ {
+ error ("invalid symbol name \"%s\"", name);
+ }
+ s = strchr (s, ']');
+ if (s == NULL)
+ {
+ error ("invalid symbol name \"%s\"", name);
+ }
+ return strchr (s, ':');
+ }
+ else
+ {
+ return strchr (s, ':');
}
}

Index: gdb/stabsread.h
===================================================================
RCS file: /cvs/src/src/gdb/stabsread.h,v
retrieving revision 1.8
diff -u -p -r1.8 stabsread.h
--- gdb/stabsread.h 18 Jul 2002 17:22:50 -0000 1.8
+++ gdb/stabsread.h 17 Sep 2002 19:31:04 -0000
@@ -219,6 +219,8 @@ extern struct symbol *ref_search (int);
extern int resolve_cfront_continuation
(struct objfile *objfile, struct symbol *sym, char *p);

+extern char *stabsread_objc_colon (char *name);
+
extern void free_header_files (void);

extern void init_header_files (void);
Index: gdb/symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.65
diff -u -p -r1.65 symfile.c
--- gdb/symfile.c 1 Aug 2002 17:18:32 -0000 1.65
+++ gdb/symfile.c 17 Sep 2002 19:31:05 -0000
@@ -1966,6 +1966,7 @@ init_filename_language_table (void)
/* OBSOLETE add_filename_language (".ch", language_chill); */
/* OBSOLETE add_filename_language (".c186", language_chill); */
/* OBSOLETE add_filename_language (".c286", language_chill); */
+ add_filename_language (".m", language_objc);
add_filename_language (".f", language_fortran);
add_filename_language (".F", language_fortran);
add_filename_language (".s", language_asm);
Index: gdb/symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.69
diff -u -p -r1.69 symtab.c
--- gdb/symtab.c 30 Aug 2002 03:24:00 -0000 1.69
+++ gdb/symtab.c 17 Sep 2002 19:31:07 -0000
@@ -49,6 +49,8 @@
#include <ctype.h>
#include "cp-abi.h"

+int allow_objc_selectors_flag = 1;
+
/* Prototype for one function in parser-defs.h,
instead of including that entire file. */

@@ -58,6 +60,9 @@ extern char *find_template_name_end (cha

static void completion_list_add_name (char *, char *, int, char *, char *);

+static void build_canonical_line_spec (struct symtab_and_line *,
+ char *, char ***);
+
static void rbreak_command (char *, int);

static void types_info (char *, int);
@@ -438,6 +443,43 @@ symbol_init_demangled_name (struct gener
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
}
}
+ if (demangled == NULL &&
+ (gsymbol->language == language_objc ||
+ gsymbol->language == language_auto))
+ {
+ demangled =
+ objc_demangle (gsymbol->name);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_objc;
+ gsymbol->language_specific.objc_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), (obstack));
+ free (demangled);
+ }
+ else
+ {
+ gsymbol->language_specific.objc_specific.demangled_name = NULL;
+ }
+ }
+ if (demangled &&
+ gsymbol->language != language_objc &&
+ (demangled = gsymbol->name) &&
+ demangled[0] == '_' &&
+ (demangled[1] == 'i' || demangled[1] == 'c') &&
+ demangled[2] == '_')
+ /* some other demangling succeeded, yet it looks like ObjC */
+ {
+ demangled =
+ objc_demangle (gsymbol->name);
+ if (demangled != NULL) /* yes, it was ObjC: let ObjC win */
+ { /* (C++ demangling is too forgiving) */
+ gsymbol->language = language_objc;
+ gsymbol->language_specific.objc_specific.demangled_name =
+ obsavestring (demangled, strlen (demangled), (obstack));
+ free (demangled);
+ }
+ }
+
#if 0
/* OBSOLETE if (demangled == NULL */
/* OBSOLETE && (gsymbol->language == language_chill */
@@ -807,7 +849,7 @@ lookup_symbol_aux (const char *name, con
}

- /* C++: If requested to do so by the caller,
+ /* C++/Java/ObjC: If requested to do so by the caller,
check to see if NAME is a field of `this'. */
if (is_a_field_of_this)
{
@@ -1321,9 +1363,9 @@ find_main_psymtab (void)
for now we don't worry about the slight inefficiency of looking for
a match we'll never find, since it will go pretty quick. Once the
binary search terminates, we drop through and do a straight linear
- search on the symbols. Each symbol which is marked as being a C++
- symbol (language_cplus set) has both the encoded and non-encoded names
- tested for a match.
+ search on the symbols. Each symbol which is marked as being a ObjC/C++
+ symbol (language_cplus or language_objc set) has both the encoded and
+ non-encoded names tested for a match.

If MANGLED_NAME is non-NULL, verify that any symbol we find has this
particular mangled name.
@@ -3275,12 +3317,42 @@ make_symbol_completion_list (char *text,
{
/* It is not a quoted string. Break it based on the characters
which are in symbols. */
- while (p > text)
+ for (; p > text; --p)
{
if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
- --p;
- else
- break;
+ continue;
+ else
+ {
+ if (current_language->la_language == language_objc)
+ {
+ if (p[-1] == ':') /* might be part of a method name */
+ continue;
+ else if (p[-1] == '[' && (p[-2] == '-' || p[-2] == '+'))
+ p -= 2; /* beginning of a method name */
+ else if (p[-1] == ' ' || p[-1] == '(' || p[-1] == ')')
+ { /* might be part of a method name */
+ char *t = p;
+
+ /* Seeing a ' ' or a '(' is not conclusive evidence
+ that we are in the middle of a method name. However,
+ finding "-[" or "+[" should be pretty un-ambiguous.
+ Unfortunately we have to find it now to decide. */
+
+ while (t > text)
+ if (isalnum (t[-1]) || t[-1] == '_' ||
+ t[-1] == ' ' || t[-1] == ':' ||
+ t[-1] == '(' || t[-1] == ')')
+ --t;
+ else
+ break;
+
+ if (t[-1] == '[' && (t[-2] == '-' || t[-2] == '+'))
+ p = t - 2; /* method name detected */
+ /* else we leave with p unchanged */
+ }
+ }
+ break;
+ }
}
sym_text = p;
}
@@ -3328,10 +3400,72 @@ make_symbol_completion_list (char *text,
anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */

- ALL_MSYMBOLS (objfile, msymbol)
+ /* ObjC: In case we are completing on a selector, look thru the msymbols
+ again and feed all the selectors into the mill. */
+
+ ALL_OBJFILES (objfile)
{
- QUIT;
- COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
+ ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
+ {
+ static char *tmp = NULL;
+ static unsigned int tmplen = 0;
+
+ char *method, *category, *selector;
+ char *tmp2 = NULL;
+
+ QUIT;
+
+ method = SYMBOL_DEMANGLED_NAME (msymbol);
+ if (method == NULL)
+ method = SYMBOL_NAME (msymbol);
+ if (method == NULL)
+ continue;
+
+ /* add the minimal symbol no matter what */
+ completion_list_add_name (method, sym_text, sym_text_len, text, word);
+
+ /* is it a method? */
+ if ((method[0] != '-') && (method[0] != '+'))
+ continue;
+
+ if (sym_text[0] == '[')
+ /* complete on shortened method method */
+ completion_list_add_name (method + 1, sym_text, sym_text_len, text, word);
+
+ while ((strlen (method) + 1) >= tmplen)
+ {
+ tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
+ tmp = xrealloc (tmp, tmplen);
+ }
+
+ selector = strchr (method, ' ');
+ if (selector != NULL)
+ selector++;
+
+ category = strchr (method, '(');
+
+ if ((category != NULL) && (selector != NULL))
+ {
+ memcpy (tmp, method, (category - method));
+ tmp[category - method] = ' ';
+ memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
+ completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
+ if (sym_text[0] == '[')
+ completion_list_add_name (tmp + 1, sym_text, sym_text_len, text, word);
+ }
+
+ if (selector != NULL)
+ {
+ /* complete on selector only */
+
+ strcpy (tmp, selector);
+ tmp2 = strchr (tmp, ']');
+ if (tmp2 != NULL)
+ *tmp2 = '\0';
+
+ completion_list_add_name (tmp, sym_text, sym_text_len, text, word);
+ }
+ }
}

/* Search upwards from currently selected frame (so that we can
Index: gdb/symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.39
diff -u -p -r1.39 symtab.h
--- gdb/symtab.h 12 Sep 2002 19:19:37 -0000 1.39
+++ gdb/symtab.h 17 Sep 2002 19:31:07 -0000
@@ -89,6 +89,11 @@ struct general_symbol_info
char *demangled_name;
}
cplus_specific;
+ struct objc_specific
+ {
+ char *demangled_name;
+ }
+ objc_specific;
#if 0
/* OBSOLETE struct chill_specific *//* For Chill */
/* OBSOLETE { */
@@ -146,6 +151,10 @@ extern CORE_ADDR symbol_overlayed_addres
{ \
SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \
} \
+ else if (SYMBOL_LANGUAGE (symbol) == language_objc) \
+ { \
+ SYMBOL_OBJC_DEMANGLED_NAME (symbol) = NULL; \
+ } \
/* OBSOLETE else if (SYMBOL_LANGUAGE (symbol) == language_chill) */ \
/* OBSOLETE { */ \
/* OBSOLETE SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; */ \
@@ -170,12 +179,17 @@ extern void symbol_init_demangled_name (
(SYMBOL_LANGUAGE (symbol) == language_cplus \
|| SYMBOL_LANGUAGE (symbol) == language_java \
? SYMBOL_CPLUS_DEMANGLED_NAME (symbol) \
+ : (SYMBOL_LANGUAGE (symbol) == language_objc \
+ ? SYMBOL_OBJC_DEMANGLED_NAME (symbol) \
: /* OBSOLETE (SYMBOL_LANGUAGE (symbol) == language_chill */ \
/* OBSOLETE ? SYMBOL_CHILL_DEMANGLED_NAME (symbol) */ \
- NULL)
+ NULL))

/* OBSOLETE #define SYMBOL_CHILL_DEMANGLED_NAME(symbol) */
/* OBSOLETE (symbol)->ginfo.language_specific.chill_specific.demangled_name */
+
+#define SYMBOL_OBJC_DEMANGLED_NAME(symbol) \
+ (symbol)->ginfo.language_specific.objc_specific.demangled_name

/* Macro that returns the "natural source name" of a symbol. In C++ this is
the "demangled" form of the name if demangle is on and the "mangled" form
Index: gdb/utils.c
===================================================================
RCS file: /cvs/src/src/gdb/utils.c,v
retrieving revision 1.76
diff -u -p -r1.76 utils.c
--- gdb/utils.c 1 Aug 2002 17:18:33 -0000 1.76
+++ gdb/utils.c 17 Sep 2002 19:31:08 -0000
@@ -152,13 +152,13 @@ int quit_flag;

int immediate_quit;

-/* Nonzero means that encoded C++ names should be printed out in their
- C++ form rather than raw. */
+/* Nonzero means that encoded C++/ObjC names should be printed out in their
+ C++/ObjC form rather than raw. */

int demangle = 1;

-/* Nonzero means that encoded C++ names should be printed out in their
- C++ form even in assembler language displays. If this is set, but
+/* Nonzero means that encoded C++/ObjC names should be printed out in their
+ C++/ObjC form even in assembler language displays. If this is set, but
DEMANGLE is zero, names are printed raw, i.e. DEMANGLE controls. */

int asm_demangle = 0;
@@ -1696,6 +1696,51 @@ wrap_here (char *indent)
}
}

+/* Print input string to gdb_stdout, filtered, with wrap,
+ arranging strings in columns of n chars. String can be
+ right or left justified in the column. Never prints
+ trailing spaces. String should never be longer than
+ width. FIXME: this could be useful for the EXAMINE
+ command, which currently doesn't tabulate very well */
+
+void
+puts_filtered_tabular (char *string, int width, int right)
+{
+ int spaces = 0;
+ int stringlen;
+ char *spacebuf;
+
+ gdb_assert (chars_per_line > 0);
+ if (chars_per_line == UINT_MAX)
+ {
+ fputs_filtered (string, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ return;
+ }
+
+ if (((chars_printed - 1) / width + 2) * width >= chars_per_line)
+ fputs_filtered ("\n", gdb_stdout);
+
+ if (width >= chars_per_line)
+ width = chars_per_line - 1;
+
+ stringlen = strlen (string);
+
+ if (chars_printed > 0)
+ spaces = width - (chars_printed - 1) % width - 1;
+ if (right)
+ spaces += width - stringlen;
+
+ spacebuf = alloca (spaces + 1);
+ spacebuf[spaces] = '\0';
+ while (spaces--)
+ spacebuf[spaces] = ' ';
+
+ fputs_filtered (spacebuf, gdb_stdout);
+ fputs_filtered (string, gdb_stdout);
+}
+
+
/* Ensure that whatever gets printed next, using the filtered output
commands, starts at the beginning of the line. I.E. if there is
any pending output for the current line, flush it and start a new
@@ -2123,7 +2168,7 @@ print_spaces_filtered (int n, struct ui_
fputs_filtered (n_spaces (n), stream);
}
\f
-/* C++ demangler stuff. */
+/* C++/ObjC demangler stuff. */

/* fprintf_symbol_filtered attempts to demangle NAME, a symbol in language
LANG, using demangling args ARG_MODE, and print it filtered to STREAM.
@@ -2153,6 +2198,9 @@ fprintf_symbol_filtered (struct ui_file
case language_java:
demangled = cplus_demangle (name, arg_mode | DMGL_JAVA);
break;
+ case language_objc:
+ demangled = objc_demangle (name);
+ break;
#if 0
/* OBSOLETE case language_chill: */
/* OBSOLETE demangled = chill_demangle (name); */
@@ -2272,7 +2320,7 @@ initialize_utils (void)
add_show_from_set
(add_set_cmd ("demangle", class_support, var_boolean,
(char *) &demangle,
- "Set demangling of encoded C++ names when displaying symbols.",
+ "Set demangling of encoded C++/ObjC names when displaying symbols.",
&setprintlist),
&showprintlist);

@@ -2300,7 +2348,7 @@ initialize_utils (void)
add_show_from_set
(add_set_cmd ("asm-demangle", class_support, var_boolean,
(char *) &asm_demangle,
- "Set demangling of C++ names in disassembly listings.",
+ "Set demangling of C++/ObjC names in disassembly listings.",
&setprintlist),
&showprintlist);
}
Index: gdb/valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.72
diff -u -p -r1.72 valops.c
--- gdb/valops.c 14 Sep 2002 02:09:39 -0000 1.72
+++ gdb/valops.c 17 Sep 2002 19:31:14 -0000
@@ -48,10 +48,8 @@ extern int overload_debug;
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);

-static CORE_ADDR find_function_addr (struct value *, struct type **);
static struct value *value_arg_coerce (struct value *, struct type *, int);

-
static CORE_ADDR value_push (CORE_ADDR, struct value *);

static struct value *search_struct_field (char *, struct value *, int,
@@ -91,7 +89,6 @@ int overload_resolution = 0;
int unwind_on_signal_p = 0;
\f

-
/* Find the address of function name NAME in the inferior. */

struct value *
@@ -211,7 +208,7 @@ value_cast (struct type *type, struct va
}
}

- if (current_language->c_style_arrays
+ if (current_language->c_style_arrays
&& TYPE_CODE (type2) == TYPE_CODE_ARRAY)
arg2 = value_coerce_array (arg2);

@@ -1219,7 +1216,7 @@ value_arg_coerce (struct value *arg, str
/* Determine a function's address and its return type from its value.
Calls error() if the function is not valid for calling. */

-static CORE_ADDR
+CORE_ADDR
find_function_addr (struct value *function, struct type **retval_type)
{
register struct type *ftype = check_typedef (VALUE_TYPE (function));
@@ -1814,6 +1811,23 @@ call_function_by_hand (struct value *fun
error ("Cannot invoke functions on this machine.");
}
}
+
+struct value *
+call_function_by_hand_expecting_type (struct value *function,
+ struct type *expect_type,
+ int nargs, struct value **args,
+ int restore_frame)
+{
+ if (CALL_DUMMY_P)
+ {
+ /* FIXME: Changes to func not implemented yet */
+ return hand_function_call (function, nargs, args);
+ }
+ else
+ {
+ error ("Cannot invoke functions on this machine.");
+ }
+}
\f

@@ -3231,18 +3245,17 @@ value_full_object (struct value *argp, s

-/* C++: return the value of the class instance variable, if one exists.
+/* Return the value of the local variable, if one exists.
Flag COMPLAIN signals an error if the request is made in an
inappropriate context. */

struct value *
-value_of_this (int complain)
+value_of_local (const char *name, int complain)
{
struct symbol *func, *sym;
struct block *b;
int i;
- static const char funny_this[] = "this";
- struct value *this;
+ struct value * ret;

if (selected_frame == 0)
{
@@ -3256,7 +3269,7 @@ value_of_this (int complain)
if (!func)
{
if (complain)
- error ("no `this' in nameless context");
+ error ("no %s in nameless context", name);
else
return 0;
}
@@ -3266,26 +3279,39 @@ value_of_this (int complain)
if (i <= 0)
{
if (complain)
- error ("no args, no `this'");
+ error ("no args, no %s", name);
else
return 0;
}

/* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
symbol instead of the LOC_ARG one (if both exist). */
- sym = lookup_block_symbol (b, funny_this, NULL, VAR_NAMESPACE);
+ sym = lookup_block_symbol (b, name, NULL, VAR_NAMESPACE);
if (sym == NULL)
{
if (complain)
- error ("current stack frame not in method");
+ error ("current stack frame does not contain a variable named \"%s\"", name);
else
return NULL;
}

- this = read_var_value (sym, selected_frame);
- if (this == 0 && complain)
- error ("`this' argument at unknown address");
- return this;
+ ret = read_var_value (sym, selected_frame);
+ if (ret == 0 && complain)
+ error ("%s argument unreadable", name);
+ return ret;
+}
+
+/* C++/Objective-C: return the value of the class instance variable,
+ if one exists. Flag COMPLAIN signals an error if the request is
+ made in an inappropriate context. */
+
+struct value *
+value_of_this (int complain)
+{
+ if (current_language->la_language == language_objc)
+ return value_of_local ("self", complain);
+ else
+ return value_of_local ("this", complain);
}

/* Create a slice (sub-string, sub-array) of ARRAY, that is LENGTH elements
Index: gdb/value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.34
diff -u -p -r1.34 value.h
--- gdb/value.h 13 Sep 2002 00:18:33 -0000 1.34
+++ gdb/value.h 17 Sep 2002 19:31:14 -0000
@@ -535,6 +535,12 @@ extern void clear_value_history (void);

extern void clear_internalvars (void);

+/* Objective-C */
+
+extern struct value *value_of_local (const char *name, int complain);
+
+extern struct value *value_nsstring (char *ptr, int len);
+
/* From values.c */

extern struct value *value_copy (struct value *);
@@ -548,6 +554,10 @@ extern struct value *value_slice (struct
extern struct value *call_function_by_hand (struct value *, int,
struct value **);

+extern struct value *call_function_by_hand_expecting_type (struct value *,
+ struct type *, int,
+ struct value **, int);
+
extern int default_coerce_float_to_double (struct type *, struct type *);

extern int standard_coerce_float_to_double (struct type *, struct type *);
@@ -565,5 +575,7 @@ extern struct value *value_allocate_spac
extern CORE_ADDR default_push_arguments (int nargs, struct value ** args,
CORE_ADDR sp, int struct_return,
CORE_ADDR struct_addr);
+
+extern CORE_ADDR find_function_addr (struct value *, struct type **);

#endif /* !defined (VALUE_H) */
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.120
diff -u -p -r1.120 gdb.texinfo
--- gdb/doc/gdb.texinfo 5 Sep 2002 12:13:08 -0000 1.120
+++ gdb/doc/gdb.texinfo 17 Sep 2002 19:31:31 -0000
@@ -212,6 +212,10 @@ syntax.
it may be necessary to refer to some variables with a trailing
underscore.

+@cindex Objective-C
+@value{GDBN} can be used to debug programs written in Objective-C,
+using either the Apple/NeXT or the GNU Objective-C runtime.
+
@menu
* Free Software:: Freely redistributable software
* Contributors:: Contributors to GDB
@@ -3174,7 +3178,8 @@ end
@cindex overloading
@cindex symbol overloading

-Some programming languages (notably C@t{++}) permit a single function name
+Some programming languages (notably C@t{++} and Objective-C) permit a
+single function name
to be defined several times, for application in different contexts.
This is called @dfn{overloading}. When a function name is overloaded,
@samp{break @var{function}} is not enough to tell @value{GDBN} where you want
@@ -7127,6 +7132,9 @@ C source file
@itemx .c++
C@t{++} source file

+@itemx .m
+Objective-C source file
+
@item .f
@itemx .F
Fortran source file
@@ -7407,7 +7415,7 @@ being set automatically by @value{GDBN}.
@node Support
@section Supported languages

-@value{GDBN} supports C, C@t{++}, Fortran, Java,
+@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java,
@c OBSOLETE Chill,
assembly, and Modula-2.
@c This is false ...
@@ -7426,8 +7434,9 @@ books written on each of these languages
language reference or tutorial.

@menu
-* C:: C and C@t{++}
-* Modula-2:: Modula-2
+* C:: C and C@t{++}
+* Objective-C:: Objective-C
+* Modula-2:: Modula-2
@c OBSOLETE * Chill:: Chill
@end menu

@@ -7951,7 +7960,84 @@ available choices, or to finish the type
@xref{Completion,, Command completion}, for details on how to do this.
@end table

-@node Modula-2
+@node Objective-C
+@subsection Objective-C
+
+This section provides information about some commands and command
+options that are useful for debugging Objective-C code.
+
+@menu
+* Method Names in Commands::
+* The Print Command with Objective-C::
+@end menu
+
+@node Method Names in Commands, The Print Command with Objective-C, Objective-C, Objective-C
+@subsubsection Method Names in Commands
+
+The following commands have been extended to accept Objective-C method
+names as line specifications:
+
+@itemize
+@item @code{clear}
+@item @code{break}
+@item @code{info line}
+@item @code{jump}
+@item @code{list}
+@end itemize
+
+For example, to set a breakpoint at the @code{create} instance method of
+class @code{Fruit} in the program currently being debugged, enter:
+
+@example
+break -[Fruit create]
+@end example
+
+To list ten program lines around the @code{initialize} class method,
+enter:
+
+@example
+list +[NSText initialize]
+@end example
+
+In the current version of GDB, the plus or minus sign is required. In
+future versions of GDB, the plus or minus sign will be optional, but you
+can use it to narrow the search. It is also possible to specify just a
+method name:
+
+@example
+break create
+@end example
+
+You must specify the complete method name, including any colons. If
+your program's source files contain more than one @code{create} method,
+you'll be presented with a numbered list of classes that implement that
+method. Indicate your choice by number, or type @samp{0} to exit if
+none apply.
+
+As another example, to clear a breakpoint established at the
+@code{makeKeyAndOrderFront:} method of the @code{NSWindow} class, enter:
+
+@example
+clear -[NSWindow makeKeyAndOrderFront:]
+@end example
+
+@node The Print Command with Objective-C
+@subsubsection The Print Command With Objective-C
+
+The print command has also been extended to accept methods. For example:
+
+@example
+print -[object hash]
+@end example
+
+will tell gdb to send the -hash message to object and print the
+result. Also an additional command has been added, @code{print-object}
+or @code{po} for short, which is meant to print the description of an
+object. However, this command may only work with certain Objective-C
+libraries that have a particular hook function, called
+@code{_NSPrintForDebugger} defined.
+
+@node Modula-2, , Objective-C, Support
@subsection Modula-2

@cindex Modula-2, @value{GDBN} support
@@ -9089,6 +9175,20 @@ outside of functions (i.e.@: excluding l
Print the names and data types of all variables (except for local
variables) whose names contain a match for regular expression
@var{regexp}.
+
+@kindex info classes
+@item info classes
+@itemx info classes @var{regexp}
+Display all Objective-C classes in your program, or
+(with the @var{regexp} argument) all those matching a particular regular
+expression.
+
+@kindex info selectors
+@item info selectors
+@itemx info selectors @var{regexp}
+Display all Objective-C selectors in your program, or
+(with the @var{regexp} argument) all those matching a particular regular
+expression.

@ignore
This was never implemented.
Index: gdb/testsuite/configure.in
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/configure.in,v
retrieving revision 1.6
diff -u -p -r1.6 configure.in
--- gdb/testsuite/configure.in 1 Aug 2002 17:18:35 -0000 1.6
+++ gdb/testsuite/configure.in 17 Sep 2002 19:31:33 -0000
@@ -18,6 +18,7 @@ configdirs="gdb.arch \
gdb.base \
gdb.c++ \
gdb.java \
+ gdb.objc \
gdb.disasm \
gdb.mi \
gdb.threads \
Index: gdb/testsuite/gdb.base/default.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/default.exp,v
retrieving revision 1.13
diff -u -p -r1.13 default.exp
--- gdb/testsuite/gdb.base/default.exp 10 Sep 2002 07:03:18 -0000 1.13
+++ gdb/testsuite/gdb.base/default.exp 17 Sep 2002 19:31:34 -0000
@@ -636,9 +636,9 @@ gdb_test "show print address" "Printing
#test show print array
gdb_test "show print array" "Prettyprinting of arrays is on." "show print array"
#test show print asm-demangle
-gdb_test "show print asm-demangle" "Demangling of C\[+\]+ names in disassembly listings is on." "show print asm-demangle"
+gdb_test "show print asm-demangle" "Demangling of C\[+\]+/ObjC names in disassembly listings is on." "show print asm-demangle"
#test show print demangle
-gdb_test "show print demangle" "Demangling of encoded C\[+\]+ names when displaying symbols is on." "show print demangle"
+gdb_test "show print demangle" "Demangling of encoded C\[+\]+/ObjC names when displaying symbols is on." "show print demangle"
#test show print elements
gdb_test "show print elements" "Limit on string chars or array elements to print is 200." "show print elements"
#test show print object
Index: gdb/testsuite/gdb.base/help.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/help.exp,v
retrieving revision 1.11
diff -u -p -r1.11 help.exp
--- gdb/testsuite/gdb.base/help.exp 24 Apr 2002 03:07:33 -0000 1.11
+++ gdb/testsuite/gdb.base/help.exp 17 Sep 2002 19:31:36 -0000
@@ -390,9 +390,9 @@ gdb_test "help set print address" "Set p
# test help set print array
gdb_test "help set print array" "Set prettyprinting of arrays\." "help set print array"
# test help set print asm-demangle
-gdb_test "help set print asm-demangle" "Set demangling of C\[+\]+ names in disassembly listings\." "help set print asm-demangle"
+gdb_test "help set print asm-demangle" "Set demangling of C\[+\]+/ObjC names in disassembly listings\." "help set print asm-demangle"
# test help set print demangle
-gdb_test "help set print demangle" "Set demangling of encoded C\[+\]+ names when displaying symbols\." "help set print demangle"
+gdb_test "help set print demangle" "Set demangling of encoded C\[+\]+/ObjC names when displaying symbols\." "help set print demangle"
# test help set print elements
gdb_test "help set print elements" "Set limit on string chars or array elements to print\.\[\r\n\]+\"set print elements 0\" causes there to be no limit\." "help set print elements"
# test help set print object
@@ -482,9 +482,9 @@ gdb_test "help show print address" "Show
# test help show print array
gdb_test "help show print array" "Show prettyprinting of arrays\." "help show print array"
# test help show print asm-demangle
-gdb_test "help show print asm-demangle" "Show demangling of C\[+\]+ names in disassembly listings\." "help show print asm-demangle"
+gdb_test "help show print asm-demangle" "Show demangling of C\[+\]+/ObjC names in disassembly listings\." "help show print asm-demangle"
# test help show print demangle
-gdb_test "help show print demangle" "Show demangling of encoded C\[+\]+ names when displaying symbols\." "help show print demangle"
+gdb_test "help show print demangle" "Show demangling of encoded C\[+\]+/ObjC names when displaying symbols\." "help show print demangle"
# test help show print elements
gdb_test "help show print elements" "Show limit on string chars or array elements to print\.\[\r\n\]+\"set print elements 0\" causes there to be no limit\." "help show print elements"
# test help show print object
Index: gdb/testsuite/gdb.base/maint.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/maint.exp,v
retrieving revision 1.13
diff -u -p -r1.13 maint.exp
--- gdb/testsuite/gdb.base/maint.exp 14 May 2002 18:30:53 -0000 1.13
+++ gdb/testsuite/gdb.base/maint.exp 17 Sep 2002 19:31:36 -0000
@@ -454,7 +454,7 @@ set timeout $oldtimeout

send_gdb "help maint\n"
gdb_expect {
- -re "Commands for use by GDB maintainers\\..*Includes commands to dump specific internal GDB structures in.*a human readable form, to cause GDB to deliberately dump core,.*to test internal functions such as the C.. demangler, etc\\..*List of maintenance subcommands:.*maintenance check-symtabs.*maintenance demangle.*(maintenance dump-me.*)?maintenance info.*maintenance internal-error.*maintenance print.*maintenance set.*maintenance show.*maintenance space.*maintenance time.*Type.*help maintenance.*followed by maintenance subcommand name for full documentation\\..*Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ -re "Commands for use by GDB maintainers\\..*Includes commands to dump specific internal GDB structures in.*a human readable form, to cause GDB to deliberately dump core,.*to test internal functions such as the C../ObjC demangler, etc\\..*List of maintenance subcommands:.*maintenance check-symtabs.*maintenance demangle.*(maintenance dump-me.*)?maintenance info.*maintenance internal-error.*maintenance print.*maintenance set.*maintenance show.*maintenance space.*maintenance time.*Type.*help maintenance.*followed by maintenance subcommand name for full documentation\\..*Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
{ pass "help maint" }
-re ".*$gdb_prompt $" { fail "help maint" }
timeout { fail "(timeout) help maint" }
@@ -487,7 +487,7 @@ gdb_expect {

send_gdb "help maint demangle\n"
gdb_expect {
- -re "Demangle a C\\+\\+ mangled name\\.\r\nCall internal GDB demangler routine to demangle a C\\+\\+ link name\r\nand prints the result\\..*$gdb_prompt $"\
+ -re "Demangle a C\\+\\+/ObjC mangled name\\.\r\nCall internal GDB demangler routine to demangle a C\\+\\+ link name\r\nand prints the result\\..*$gdb_prompt $"\
{ pass "help maint demangle" }
-re ".*$gdb_prompt $" { fail "help maint demangle" }
timeout { fail "(timeout) help maint demangle" }
@@ -614,7 +614,7 @@ gdb_expect {

send_gdb "help maint\n"
gdb_expect {
- -re "Commands for use by GDB maintainers\\.\[\r\n\]+Includes commands to dump specific internal GDB structures in\[\r\n\]+a human readable form, to cause GDB to deliberately dump core,\[\r\n\]+to test internal functions such as the C\\+\\+ demangler, etc\\..*Type.*help maintenance.*followed by maintenance subcommand name for full documentation\\.\[\r\n\]+Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
+ -re "Commands for use by GDB maintainers\\.\[\r\n\]+Includes commands to dump specific internal GDB structures in\[\r\n\]+a human readable form, to cause GDB to deliberately dump core,\[\r\n\]+to test internal functions such as the C\\+\\+/ObjC demangler, etc\\..*Type.*help maintenance.*followed by maintenance subcommand name for full documentation\\.\[\r\n\]+Command name abbreviations are allowed if unambiguous\\..*$gdb_prompt $"\
{ pass "help maint" }
-re ".*$gdb_prompt $" { fail "help maint" }
timeout { fail "(timeout) help maint" }